求无序序列每个元素最接近的值

来源:互联网 发布:淘宝卖家套餐怎么设置 编辑:程序博客网 时间:2024/06/05 16:10

1、问题描述

给一个n个元素的线性表A,对于每个数Ai,找到它之前的数中,和它最接近的数。

即对于每个i,求 Ci = min{ |Ai -Aj |  | 1<= j < i}


1.2算法分析

有两种思路可以解决上诉问题:

(1) 遍历整个线性表,对每个元素 A[i] ,遍历 A[0] - A[i-1] , 求出与 A[i] 绝对值最小的元素。这种方法的效率为O(n^2)。


(2)先对线性表 A 进行排序, 将结果构造成双向链表 L 。反向遍历 A,将每个元素 A[i] , 比较 A[i] - A[i-1]  和A[i+1] - A[i] ,取两者中与 A[ i ] 更接近的,即是 A[ i ] 之前的数中与 A[ i ]最接近的。然后 将A[i] 从L中删去。则双向链表中剩下的元素就是 A[i] 前面的元素。这种方法的效率可以达到O(nlogn)。


1.3 算法过程图解




1.4 思路2算法实现

首先,需要的一个双向链表作为辅助,定义双向链表结构如下:

struct LNode{   struct LNode* next;   struct LNode* prev;   int key;};

给链表添加一些操作,来支持解决问题:

#include <stdio.h>#include <malloc.h>#include "lcl.h"//从数组里创建链表 struct LNode* create_list_from_array( int* array,int array_length){struct LNode* head,*prev_node=NULL,*node;int i=0;for(i=0;i<array_length;i++){node=(struct LNode*)malloc(LEN);node->key=array[i];node->next=NULL;node->prev=prev_node;if(prev_node==NULL)    //创建第一个结点时执行 {   head=node; }else{           prev_node->next=node;   } prev_node=node;}return head;}//求与node结点值最接近的结点,并打印 void get_near(struct LNode* node) {int a=0,b=0,c=0,ab=0,bc=0,near;if(node->prev==NULL&&node->next==NULL) {printf("no other num before %d \n",node->key);return;}if(node->prev==NULL){  printf("brefore and the most nearest %d num is:%d\n",node->key,node->next->key);  return;}if(node->next==NULL){  printf("brefore and the most nearest %d num is:%d\n",node->key,node->prev->key);  return;}a=node->prev->key;b=node->key;c=node->next->key;ab=b-a;bc=c-b;near=ab>bc?c:a;printf("brefore and the most nearest %d num is:%d\n",node->key,near);}//从链表删除值为n的一个元素 struct LNode* delete_last_n(struct LNode* list,int n){struct LNode* head=list,*node=list,*prev,*curr,*next;while(node!=NULL&&node->key<n){node=node->next;}prev=node->prev;curr=node;next=node->next;get_near(node);if(prev==NULL&&next==NULL){  free(curr);  return NULL;  }if(prev!=NULL){prev->next=next;}else{list=next;}if(next!=NULL){     next->prev=prev;}else{prev->next=NULL;}free(curr);    return list;}       


然后,需要一个排序算法对线性表进行排序,这里使用到归并排序:

extern void print_array(int* array,int n);//归并排序 void merge_array(int* array,int p,int q,int r){int l1=q-p+2,l2=r-q+1;int A[l1],B[l2]; //多加 1为最后一个元素赋最大值留着 int i=0,j=0,k=0;for(i=p,j=0;i<=q;i++,j++){A[j]=array[i];}A[j]=MAX_NUMBER;for(i=q+1,j=0;i<=r;i++,j++){B[j]=array[i];}B[j]=MAX_NUMBER;i=0,j=0,k=0;for(k=p;k<=r;k++){if(A[i]>B[j]){   array[k]=B[j];   j++;}else{   array[k]=A[i];   i++;}}}void merge_sort(int* array,int p,int r){     //归并排序,p为计数起点,一般是0,r为数组最后序号,为n-1 if(p<r){ int q=p+(r-p)/2;merge_sort(array,p,q);merge_sort(array,q+1,r);    merge_array(array,p,q,r);}} 


关键代码:

//初始化并运行程序 void init(int array_length)   {     int array[array_length],array2[array_length],i=0;   struct LNode* list;   get_iarray_scf(array,array_length);    //获取输入数组    copy_array(array,array2,array_length);   //保存初始数组    print_array(array,array_length);            //对数组排序    merge_sort(array,0,array_length-1);      //将排序结果创建双向链表    list=create_list_from_array(array,array_length);      // 从后往遍历输入数组,依次从双向链表删除    for(i=array_length-1;i>=0;--i)   {     list=delete_last_n(list,array2[i]);   }}

附录:

1、代码

2、参考教程







0 0
原创粉丝点击