排序算法及其效率分析(二)外排序
来源:互联网 发布:阿里云 宕机 经济损失 编辑:程序博客网 时间:2024/06/06 13:11
一般我们常见的冒泡,插入,选择,堆,快速或者归并都是要求数据在内存,即内部排序;但是当文件很大,不能全部放入内存时候,就需要进行外排序了:
例如:
int main(){fstream inout;inout.open("D:/large.dat",ios::out|ios::binary);for(int i=0;i<2000000;i++){int val=rand();inout.write(reinterpret_cast<char*>(&val),sizeof(val));}inout.close();inout.open("D:/large.dat",ios::in|ios::binary);int x;for(int i=0;i<10;i++){inout.read(reinterpret_cast<char*>(&x),sizeof(x));cout<<x<<" ";}inout.close();system("pause");return 0;}200万个int型数据存在"large.dat"的文件,需要进行外排序。
阶段1:反复从文件读取数据存入一个数组,使用内排序算法对数组排序,然后将数组写回一个临时文件。比如设置该数组规模MAX=100000,则有:
阶段2:将每对有序数据段合并成一个大的有序数据段
实现阶段1代码:
int ini(int segment,char*oldfile,char*f1){int num=0;fstream in;in.open(oldfile,ios::in |ios::binary);fstream out;out.open(f1,ios::out|ios::binary);int *list=new int[segment];while(!in.eof()){int i;for(i=0;i<segment&&!in.eof();i++)in.read(reinterpret_cast<char*>(&list[i]),sizeof(list[i]));//从源文件读取到数组里if(in.eof())i--;if(i<=0) break;else num++;quicksort(list,i);//使用内部排序函数,比如插入,归并等排序for(int j=0;j<i;i++)out.write(reinterpret_cast<char*>(&list[j]),sizeof(list[j]));}//将排序好数组存在临时文件f1里delete []list;in.close();out.close();}实现阶段2
首先将f1文件的前一半数据复制到f2,然后将f1与f2数据段对应合并,写入临时文件f3
//将f1中Num个数据段分半,前一半到f2void copyfile(int num,int segmentsize,fstream &f1,fstream&f2){int i;for(i=0;i<(num/2)*segmentsize;i++) {int x;f1.read(reinterpret_cast<char*>(&x),sizeof(x));f2.write(reinterpret_cast<char*>(&x),sizeof(x));}}下面是真正合并阶段:
由于每次合并都是两个数据段的合并,所以首先实现两个数据段的合并:
//合并两个数据段void mergetwoseg(int segmentsize,fstream&f1,fstream&f2,fstream&f3){int fromf1;f1.read(reinterpret_cast<char*>(&fromf1),sizeof(fromf1));int fromf2;f2.read(reinterpret_cast<char*>(&fromf2),sizeof(fromf2));int f1count=1;int f2count=1;while(1){if(fromf1<fromf2){f3.write(reinterpret_cast<char*>(&fromf1),sizeof(fromf1));if(f1.eof()||f1count++>=segmentsize){if(f1.eof())break;f3.write(reinterpret_cast<char*>(&fromf2),sizeof(fromf2));break;}else {f1.read(reinterpret_cast<char*>(&fromf1),sizeof(fromf1));}}else{f3.write(reinterpret_cast<char*>(&fromf2),sizeof(fromf2));if(f2.eof()||f2count>=segmentsize){if(f2.eof())break;f3.write(reinterpret_cast<char*>(&fromf1),sizeof(fromf1));break;}else {f2.read(reinterpret_cast<char*>(&fromf2),sizeof(fromf2));}}}while(!f1.eof()&&f1count++<segmentsize){int x;f1.read(reinterpret_cast<char*>(&x),sizeof(x));if(f1.eof())break;f3.write(reinterpret_cast<char*>(&x),sizeof(x));}while(!f2.eof()&&f2count++<segmentsize){int y;f2.read(reinterpret_cast<char*>(&y),sizeof(y));if(f2.eof())break;f3.write(reinterpret_cast<char*>(&y),sizeof(y));}}最后是合并所有的:
void merigefile(int num,int segmentsize,char*f1,char*f2,char*f3){for(int i=0;i<num;i++) mergetwoseg(segmentsize,f1,f2,f3);while(!f1.eof()){int x;f1.read(reinterpret_cast<char*>(&x),sizeof(x));if(f1.eof())break;f3.write(reinterpret_cast<char*>(&x),sizeof(x));}}
算法性能:在阶段1从源文件读取n个元素并写入临时文件,开销O(n);在阶段2,有序数组数目n/num,每个合并步骤都将数目减少一半,log(n/num)步骤后,数目为1,每次合并从f1读取一半数据段写入f2,f1剩余数据段与f2中数据段进行合并,每次合并O(n),故O(n)*log(n/num)=O(nlogn)
0 0
- 排序算法及其效率分析(二)外排序
- 排序算法及其效率分析(一)内排序
- 排序算法及其效率比较
- 外排序(大数据文件排序)
- 几种常见排序算法及其效率
- 排序算法分析(二)
- 外排序和归并排序
- 内排序和外排序
- 内排序与外排序
- 归并排序实现外排序
- 内排序和外排序
- 插入排序算法及其分析
- 插入排序及其算法分析
- 排序算法源码及效率分析汇总
- 几种排序算法及其代码实现(二)
- 常见排序算法及其C语言实现(二)
- 内排序与外排序的关系
- 合并排序:数组和单链表,外排序
- leetcode Remove Nth Node From End of List
- java面向对象——包和接口
- cocos3.5塔防游戏开发---复习cocos2dx结束(明天重启仙剑)
- c++常识要点
- 《Shazam It! Music Recognition Algorithms, Fingerprinting, and Processing》译文
- 排序算法及其效率分析(二)外排序
- Python标准库:内置函数str(object='') str(object=b'', encoding='utf-8', errors='strict')
- 解决安装了msyql,却无法再服务列表出现MySQL
- SemEval2015语义评测任务总结
- 折半查找
- 1123123123
- 何乐不为
- rails常用資料庫查詢操作、方法淺析
- Ruby 之 class 中的 private、 protected、public