如何在很大数量级的数据中(比如1个亿)筛选出前10万个最小值?之四
单向链表
用单向链表,还更麻烦。因为,插入时,必须修改插入点的前一节点的后续值。因此,做查找时,临时维护一个前趋。也不知道有没好处。代码如下:
//---------------------- //单向链 struct SOutOne { int value, next; }; void SortLinkOne(int Data[], int m, int n, SOutOne Out[]) { for(int count= 0, head= 0, end= 0, i= 0; i<= m; i++) if(i== m) //结束 { if(head> 0) { SOutOne t= Out[0]; Out[0]= Out[head], Out[head]= t; //链首换到0 for(int j= 0; j< count; j++) if(j!= end && Out[j].next== 0) Out[j].next= head; } } else if(count== n && Data[i]>= Out[end].value) //无效数据 continue; else { for(int end1, see1, see= head, j= 0; ; see1= see, see= Out[see].next, j++) { if(j== count) //追加 { if(Out[count].value= Data[i], count> 0) Out[end].next= count, end= count; //新尾 count++; break; } else if(Data[i]< Out[see].value) //插入 { end1= count== n? end: count; if(Out[end1].value= Data[i], count< n || see!= end1) { Out[end1].next= see; if(see== head) head= end1; else Out[see1].next= end1; if(count< n) count++; else for(int lim= n- 1, see= head, j= 0; ; see= Out[see].next, j++) if(j== lim) { end= see; break; } } break; } } } } void control(int n) { int m= n< 9? n+ 2: n* pow(10, 3); //小数据调试 double tms= GetTickCount(); int *Data= new int[m], *DataSort= new int[m]; for(int i= 0; i< m; i++) //得随机数 DataSort[i]= Data[i]= random(m); ShowTime("制造随机数用时", tms); sort(DataSort, DataSort+ m); ShowTime("标准排序用时", tms); SOutOne*Out= new SOutOne[n+ 1]; err: SortLinkOne(Data, m, n, Out); ShowTime("单向链处理用时", tms); for(int see= 0, i= 0; i<= n; see= Out[see].next, i++) if(i== n) { ShowMessage("找好"); break; } else if(DataSort[i]!= Out[see].value) { ShowMessage("出错"); goto err; } delete []DataSort; delete []Data; delete []Out; }
一亿取十万,用时:2794秒。你没看错。约是折半查找的十倍。链表,在这,空间用得多,速度还很慢。下一步,看看堆排序。据说,堆排序特别适合这里使用。