一百万个结构数组,根据其中一项值排序,用双链表还是数组排序效率更好,请给出最快C或C++算法代码。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一百万个结构数组,根据其中一项值排序,用双链表还是数组排序效率更好,请给出最快C或C++算法代码。相关的知识,希望对你有一定的参考价值。
类似于:
struct data
unsigned int a;
unsigned int b;
unsigned int c;
unsigned int d;
unsigned int e;
unsigned int f;
;
我现在用的是双链表插入排序,速度慢得惊人。
void Swap(Type &NodeA,Type &NodeB)
Type Temp=NodeA;
NodeA=NodeB;
NodeB=Temp;
void Qsort(int LeftRange,int RightRange,Type Array[])
int LPoint,RPoint;
unsigned int Mid;
if (LeftRange==RightRange) return ;
Mid=Array[(LeftRange+RightRange)/2].a;
LPoint=LeftRange;RPoint=RightRange;
do
LPoint++;RPoint--;
while (Array[LPoint].a<Mid) LPoint++;
while (Array[RPoint].a>Mid) RPoint--;
if (LPoint<RPoint)
Swap(Array[LPoint],Array[RPoint]);
while (LPoint<RPoint);
Qsort(LeftRange,RPoint);
Qsort(RPoint+1,RightRange);
从大到小排序:
采用数组排序,使用快速排序,例如说采用a 关键字排序的话:
void Swap(Type &NodeA,Type &NodeB)
Type Temp=NodeA;
NodeA=NodeB;
NodeB=Temp;
void Qsort(int LeftRange,int RightRange,Type Array[])
int LPoint,RPoint;
unsigned int Mid;
if (LeftRange==RightRange) return ;
Mid=Array[(LeftRange+RightRange)/2].a;
LPoint=LeftRange;RPoint=RightRange;
do
LPoint++;RPoint--;
while (Array[LPoint].a>Mid) LPoint++;
while (Array[RPoint].a<Mid) RPoint--;
if (LPoint<RPoint)
Swap(Array[LPoint],Array[RPoint]);
while (LPoint<RPoint);
Qsort(LeftRange,RPoint);
Qsort(RPoint+1,RightRange);
插入排序的时间复杂度是O(N^2)的时间复杂度,而快速排序的平均复杂度为O(N*Log(N)),且快速排序的时间常数小,虽然其最坏理论时间复杂度为O(N^2),但在实际运行中快速排序的速度较其他排序快很多,而且利用段长度小于3时用选择排序的话,验证速度提高10%~20%左右,但对于百万级的数据来说,普通的快速排序已然足够。 参考技术A 直接用自带的algorithm库里面的sort
#include<algorithm.h>
#include<iostream>
using namespace std;
struct data
.......
arr[1000000];
bool flag(data aa,data bb)
return aa>bb; //从大到小排序
//return aa<bb; 从小到大排序
int main()
......
sort(arr,arr+1000000,flag);//flag 是迭代器
是 nlogn的算法,1百万的数据不进行其他操作应该一秒左右可以出来。
面试难题:用有限的内存对一百万个数字输入进行排序
【中文标题】面试难题:用有限的内存对一百万个数字输入进行排序【英文标题】:Interview puzzle: Sorting a million number input with limited memory 【发布时间】:2012-11-26 09:08:26 【问题描述】:我尝试使用外部排序来回答这个问题,但面试官回答说复杂度很高 n.n(log(n)) 即 n 平方 *logn。 有没有更好的选择。
为了简化问题: 让我们假设我们有 1000 个元素要排序,并且仅分配给 100 个元素的空间。比外部排序花费更少时间的最佳算法是什么。
【问题讨论】:
@AliImran 您不知道数据的范围,或者即使它具有对其进行排序的字符串表示形式。 了解更多信息:-en.wikipedia.org/wiki/Sorting_algorithm 【参考方案1】:我不知道你(或面试官)指的是哪种外部类型,但是
我的建议是 10 路(在您的情况下)合并:
将文件分成 MAX_MEM 大小的块(100 个元素) 这是O(1)
对内存中的每个块进行排序并存储为单独的文件
这是O((n/max_mem) * (max_mem) log(max_mem)))
= O(n log(max_mem))
将所有块作为元素流打开
通过在每个步骤中选择最低元素来合并所有流。
这是 O(n log(n/max_mem))
使用 minHeap 或 O(n^2/max_mem)
琐碎(在实践中可能更快)
删除区块
关于计算,这是O(n (log(max_mem)+log(n/max_mem)))
=O(n log(n))
关于磁盘 I/O,如果一次完成所有合并,则2*n
读取和2*n
写入仅。
更一般地说,它是(1+[depth of the merge tree])*n
所有写入都是顺序的。 第一次读取是顺序读取,第二次读取是顺序读取,从 10 个文件交错。
如果有更多数据,则需要重复或递归合并(每个块 100 个,然后重复选择 N 个块)。此时,正如@amit 的回答中所述,将拆分+排序步骤替换为替换/选择是值得的,尤其是当数据已经几乎排序时(您可能会完全避开合并步骤)。
请注意,较高的 N 可能会增加计算量(非常轻微,如果您使用正确的结构),但会显着减少磁盘 I/O 量(最多达到一定量;如果一次合并太多块,您可能读取缓冲区的内存不足,导致不必要的读取)。磁盘 I/O 很昂贵,而 CPU 周期则不然。
【讨论】:
正如问题中所述,我已经回答了这个问题,这需要 n*n(logn) 时间,对于面试官来说这是非常高的时间 @AnshuKandhari 不会花这么长时间。为什么要这样做? 第二个参数有一半是错误的。确实,基数排序需要更多内存,但所需的内存取决于您在每次传递中使用的位数(桶数)。因此,所需的内存可能会小于合并排序的要求,例如 from here:-***.com/questions/3539265/… @Jan:你会首先获取 10 个 100 个元素的块并对它们进行排序。 Tim 复杂度= 10*100(log 100) @AnshuKandhari 这个是O(n log(max_mem))
,而不是O(n^2 log(max_mem))
。 (从技术上讲,第二个语句阅读 theta 而不是 big-oh)。【参考方案2】:
也许面试官希望你问:这些号码是 J. Bentley (Cracking the Oyster) 提到的唯一七位电话号码吗?
【讨论】:
【参考方案3】:标准的做法是External Sort。
在外部排序中 - 不仅具有O(nlogn)
复杂性很重要 - 尽可能减少磁盘读取/写入,并使最多的读取和写入顺序(而不是随机)也很重要 - 因为按顺序进行磁盘访问效率更高。
这样做的标准方法确实是 k-way 合并排序,正如@JanDvorak 所建议的那样,但是我打算纠正的建议有一些错误和补充:
-
首先,对输入执行RS (Replacement-Selection) 会减少初始“运行”次数(递增序列的数量),因此通常会减少后期合并排序所需的迭代总数。
我们需要内存来缓冲(读取和写入输入) - 因此,对于内存大小 M 和文件大小 M*10,我们不能进行 10 路合并 - 这将导致大量读取磁盘(读取每个元素,而不是块)。
k
的标准公式 - 合并的“顺序”是 M/(2b)
(其中 M 是您的内存大小,b
是每个“缓冲区”(通常是磁盘块)的大小。
每个合并排序步骤都是通过从先前迭代中生成的每个“运行”中读取 b
条目来完成的 - 将 M/2
填充到内存中。其余内存用于“预测”(允许以最少的 IO 等待持续工作)——从一次运行中请求更多元素,并用于输出缓冲区——以保证块中的顺序正确。
使用这种方法的总迭代次数为log_k(N/(2M))
,其中k
是运行次数(之前计算的),M
是内存大小,N
是文件大小。每次迭代都需要对整个文件进行 1 次顺序读取和 1 次顺序写入。
也就是说,file_size/memory_size 的比率通常远大于 10。如果您只对 10 的比率感兴趣,则可能会进行局部优化,但对于 file_size/memory_size >> 10
的更常见情况则不适用
【讨论】:
以上是关于一百万个结构数组,根据其中一项值排序,用双链表还是数组排序效率更好,请给出最快C或C++算法代码。的主要内容,如果未能解决你的问题,请参考以下文章
java题:一百万个乱序数字排序,中间有重复的,但由于内存不够,不能一下存储100万个数,怎样才排序?