排序算法

来源:互联网 发布:小猪微电商系统源码 编辑:程序博客网 时间:2024/06/06 03:17
1、插入排序
每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。
1.1 直接插入排序
原理:将数组分为无序区和有序两个区,然后不断将无序区的第一个元素按大小顺序插入到有序区中去,最终将所有无序的都移动到有序区完场排序。
要点:设立哨兵,作为临时存储和判断数组边界使用。
  1. voidInsertSort(int*L,int length)
  2. {
  3. int i,j;
  4. for(i =1;i<length;i++)//扩大有序区地址
  5. {
  6. j = i+1;
  7. if(L[j]< L[i])
  8. {
  9. L[0]= L[j];//存储待排序元素
  10. while(L[0]< L[i])//在有序区找位置插入
  11. {
  12. L[i+1]= L[i];//移动
  13. i--;
  14. }
  15. L[i+1]= L[0];
  16. }
  17. i = j-1;//还原有序区指针
  18. }
  19. }
当插入第i (i > 1) 个对象时,前面的V[0], V[1], …, v[i-1]已经排好序。这时,用v[i]的关键码与v[i-1], v[i-2], …的关键码顺序进行比较,找到插入位置即将v[i]插入,原来位置上的对象向后顺移。
最好情况下,排序前对象已经按关键码大小从小到大有序,每趟只需与前面的有序对象序列的最后一个对象的关键码比较 1 次,移动 2 次对象,总的关键码比较次数为 n-1,对象移动次数为 2(n-1)。
最坏情况下,第 i 趟时第 i 个对象必须与前面 i 个对象都做关键码比较,并且每做 1 次比较就要做 1 次数据移动。则总的关键码比较次数KCN和对象移动次数RMN分别为n/2。
1.2折半插入
原理:设在顺序表中的对象序列V[0],[1],[2].....。其中前i个是已经排序好的对象,再插入v[i]时,用折半搜索的方式查找。 
  1. voidBinaryInsert( datalist<Type>&list,int i )
  2. {
  3. int left =0,Right= i-1;
  4. Element<Type> temp =list.Vector[i];
  5. while( left <=Right)
  6. {
  7. int middle =( left +Right)/2;
  8. if( temp.getKey ()<list.Vector[middle].getKey ())
  9. Right= middle -1;
  10. else
  11. left = middle +1;
  12. }
  13. for(int k = i-1; k >= left; k--)
  14. list.Vector[k+1]=list.Vector[k];
  15. list.vector[left] = temp;
  16. }
算法分析:对分查找比顺序查找快,所以对分插入排序就平均性能来说比直接插入排序要快。
它所需要的关键码比较次数与待排序对象序列的初始排列无关,仅依赖于对象个数。在插入第 i 个对象时,需要经过 log2i +1  次关键码比较,才能确定它应插入的位置。因此,将 n 个对象(为推导方便,设为 n=2k )用对分插入排序所进行的关键码比较次数为:
nlog2n
当 n 较大时,总关键码比较次数比直接插入排序的最坏情况要好得多,但比其最好情况要差。
在对象的初始排列已经按关键码排好序或接近有序时,直接插入排序比对分插入排序执行的关键码比较次数要少。对分插入排序的对象移动次数与直接插入排序相同,依赖于对象的初始排列。
对分插入排序是一个稳定的排序方法
1.3链表插入
原理:在每个对象的结点中增加一个链表指针数据成员LINK
算法分析:使用链表插入排序,每插入一个对象,最大关键码比较次数等于链表中已排好序的对象个数,最小关键码比较次数为1。故总的关键码比较次数最小为 n-1,最大为n(n-1)/2
用链表插入排序时,对象移动次数为0。但为 了实现链表插入,在每个对象中增加了一个链域 link,并使用了vector[0]作为链表的表头结点,总共用了 n 个附加域和一个附加对象。
算法从 i = 2 开始,从前向后插入。并且在vector[current].Key == vector[i].Key时,current还要向前走一步,pre跟到current原来的位置,此时, vector[pre].Key == vector[i].Key。将vector[i]插在vector[pre]的后面,所以,链表插入排序方法是稳定的。
1.4希尔排序
基本思想:又称增量缩小排序。先将序列按增量划分为元素个数相同的若干组,使用直接插入排序法进行排序,然后不断缩小增量直至为1,最后使用直接插入排序完成排序。
要点:增量的选择以及排序最终以1为增量进行排序结束。
  1. void shellsort(datalist<Type>&list)
  2. {
  3. int gap = list.currentsize/2;
  4. while(gap)
  5. {
  6. shellInsert(list,gap);
  7. gap = gap == 2?1:(int)(gap/2.2);
  8. }
  9. }
  10. shellInsert ( datalist<Type> & list; const int gep ) {
  11. //一趟希尔排序,按间隔gap划分子序列 for ( int i = gap; i < list.CurrentSize; i++) {Element<Type> temp = list.Vector[i];int j = i;while ( j >= gap && temp.getKey ( ) < list.Vector[j-gap].getKey ( ) ) { list.Vector[j] = list.Vector[j-gap]; j -= gap; } list.Vector[j] = temp; } }
算法分析:
开始时 gap 的值较大,子序列中的对象较少,排序速度较快;随着排序进展,gap 值逐渐变小,子序列中对象个数逐渐变多,由于前面工作的基础,大多数对象已基本有序,所以排序速度仍然很快。

2、交换排序
两两比较待排序对象的关键码,如果发生逆序(即排列顺序与排序后的次序正好相反),则交换之,直到所有对象都排好序为止。
2.1冒泡排序(从后面到前面有序)
思想:设待排序对象序列中的对象个数为 n。最多作 n-1 趟,i = 1, 2, 。。。, n-2 。在第 i 趟中顺次两两比较v[n-j-1].Key和v[n-j].Key,j = n-1, n-2, 。。,  i。如果发生逆序,则交换v[n -j-1]和v[n-j]。
  1. int arr[10]={7,6,4,3,5,1,2,9,10,8};
  2. for(int i=0;i<LENGTH-1;i++)
  3. {
  4. for(int j=0;j<LENGTH-i-1;j++)
  5. {
  6. if(arr[j]>arr[j+1])
  7. {
  8. swap(&arr[j],&arr[j+1]);
  9. }
  10. }
  11. }
  12. //冒泡排序优化版本
  13. bool flag =true;
  14. for(int i=0;i<LENGTH-1&& flag;i++)
  15. {
  16. flag =false;//若是有序,就不用比了
  17. for(int j=0;j<LENGTH-i-1;j++)
  18. {
  19. if(arr[j]>arr[j+1])
  20. {
  21. swap(&arr[j],&arr[j+1]);
  22. flag =true;
  23. }
  24. }
  25. }

3.选择排序

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

是所有 sorting 里面 swap 次数最少的,当 swap 代价很高的时候,选择使用选择排序。

  1. 通过n-i次比较,从n-i+1个数据中找到最小的数据,并和第i个数据交换。
  2. int min =0;
  3. for(int i=0; i<LENGTH-1; i++)
  4. {
  5. min = i;//定义当前下标为最小值
  6. for(int j=i+1;j<LENGTH;j++)
  7. {
  8. if(arr[min]> arr[j])//如果存在更小的值
  9. {
  10. min = j;//调整min下标
  11. }
  12. }
  13. if(i != min)//若i不为最小值,交换
  14. {
  15. swap(&arr[min],&arr[i]);
  16. }
  17. }

4、快排
任取待排序对象序列中的某个对象 (例如取第一个对象) 作为基准,按照该对象的关键码大小,将整个对象序列划分为左右两个子序列:
 左侧子序列中所有对象的关键码都小于或等于基准对象的关键码
 右侧子序列中所有对象的关键码都大于基准对象的关键码
  1. int partation(keytype ar[],int left,int right)
  2. {
  3. int i= left,j = right;
  4. ar[0]= ar[i];
  5. while(i<j)
  6. {
  7. while(i<j && ar[0]<ar[j]){j--};
  8. ar[i] = ar[j];
  9. while(i<j && ar[i] <ar[0])++i
  10. ar[j] = ar[i];
  11. }
  12. ar[i] = ar[0];
  13. return i;
  14. }
  15. void quick(int ar[],int left,int right)
  16. {
  17. if(left < right)
  18. {
  19. int pos = partation(ar,left,right);
  20. quick(ar,left,pos-1);
  21. quick(ar,pos+1,right);
  22. }
  23. void quicksortint ar[],int n
  24. {
  25. quick(ar,1,n);
  26. }
  27. void quick_sort_loop(int *arr, int len)
    {
        int *stack = (int *)malloc(len * sizeof(int) * 20);//借助空间
        assert(stack != NULL);
        int top = 0;
        stack[top++] = 0;
        stack[top++] = len-1;
        int low;
        int high;
        int part;
        while(top != 0)
        {
            high = stack[--top];//len-1
            low = stack[--top];//0
            //不断循环排列
            part = partition(arr, low, high);
            if (low < part-1)
            {
                stack[top++] = low;
                stack[top++] = part-1;
            }
            if (part+1 < high)
            {
                stack[top++] = part+1;
                stack[top++] = high;
            }
            
        }
        free(stack);
    }
算法分析:
从快速排序算法的递归树可知,快速排序的趟数取决于递归树的深度。
如果每次划分对一个对象定位后,该对象的左侧子序列与右侧子序列的长度相同,则下一步将是对两个长度减半的子序列进行排序,这是最理想的情况。
在n个元素的序列中,对一个对象定位所需时间为 O(n)。若设 t(n) 是对 n 个元素的序列进行排序所需的时间,而且每次对一个对象正确定位后,正好把序列划分为长度相等的两个子序列,此时,总的计算时间为:o(n log2n )
要求存储开销为 o(log2n)。
可以证明,函数quicksort的平均计算时间也是o(nlog2n)。实验结果表明:就平均计算时间而言,快速排序是我们所讨论的所有内排序方法中最好的一个。

5、锦标旗排序
首先取得 n 个对象的关键码,进行两两比较,得到 【n/2】 个比较的优胜者(关键码小者),作为第一步比较的结果保留下来。然后对这 【n/2】 个对象再进行关键码的两两比较,…,如此重复,直到选出一个关键码最小的对象为止。
如果n不是2的K次幂,则让叶结点数补足到2的k次方个。叶结点上面一层的非叶结点是叶结点的关键码俩俩比较的结果。
 每个结点除了存放对象的关键码 data 外,还存放了此对象是否要参选的标志 Active 和此对象在满二叉树中的序号index。
算法分析:
锦标赛排序构成的树是满的完全二叉树,其深度为 log2(n+1),其中 n 为待排序元素个数。
除第一次选择具有最小关键码的对象需要进行 n-1 次关键码比较外,重构胜者树选择具有次小、再次小关键码对象所需的关键码比较次数均为 O(log2n)。总关键码比较次数为O(nlog2n)。
对象的移动次数不超过关键码的比较次数,所以锦标赛排序总的时间复杂度为O(nlog2n)。
多了附加存储。如果有 n 个对象,必须使用至少 2n-1 个结点来存放胜者树。
稳定

6、堆排
堆排序分为两个步骤:第一步,根据初始输入数据,利用堆的调整算法 FilterDown( ) 形成初始堆,第二步,通过一系列的对象交换和重新调整堆进行排序。
  1. void heap_adjust(int*arr,int start,int end)
  2. {
  3. int tmp = arr[start];
  4. for(int i=2*start+1;i<=end;i=i*2+1)
  5. {
  6. if(i+1<=end && arr[i]< arr[i+1])
  7. {
  8. i++;
  9. }
  10. if(tmp < arr[i])
  11. {
  12. arr[start]= arr[i];
  13. }
  14. else
  15. {
  16. break;
  17. }
  18. start = i;
  19. }
  20. arr[start]= tmp;
  21. }
  22. void heap_sort(int*arr,int len)
  23. {//12,3,5,7,9,0,23,16,90,20,30
  24. //建堆
  25. for(int i=len/2-1;i>=0;i--)//n/2 * log2N
  26. {
  27. heap_adjust(arr, i, len-1);
  28. }
  29. swap(&arr[0],&arr[len-1]);
  30. //堆调整
  31. for(int i=len-2;i>0;i--)// n log2N
  32. {
  33. heap_adjust(arr,0,i);
  34. swap(&arr[0],&arr[i]);
  35. }//1.5N * log2N
  36. }// 稳定性?????? 递归版本
  37. int main()
  38. {
  39. int arr[]={12,3,5,7,9,0,23,16,90,20,30};
  40. int len =sizeof(arr)/sizeof(arr[0]);
  41. heap_sort(arr, len);
  42. show(arr, len);
  43. return0;
  44. }
初始化大根堆,交换arr[0] = arr[n-1],从0号到n-1号,重新调整为大根堆,交换arr[0] = arr[n-2],,,,,,直至交换0号与1号。
算法分析:
堆排序的时间复杂性为O(nlog2n)。
算法的空间复杂性为O(1)。
堆排序是一个不稳定的排序方法。

7、归并排序
设两个有序表A和B的对象个数(表长)分别为 al 和 bl,变量 i 和 j 分别是表A和表B的当前检测指针。设表C是归并后的新有序表,变量 k 是它的当前存放指针。
当 i 和 j 都在两个表的表长内变化时,根据A[i]与B[j]的关键码的大小,依次把关键码小的对象排放到新表C[k]中;
当 i 与 j 中有一个已经超出表长时,将另一 个表中的剩余部分照抄到新表C[k]中。
  1. void merge(int*arr,int len,int gap)
  2. {
  3. int i =0;
  4. int*crr =(int*)malloc(sizeof(int)* len);
  5. assert(crr != NULL);
  6. int L1 =0;
  7. int H1 = L1+gap-1;
  8. int L2 = H1+1;
  9. int H2 =(L2+gap-1)<=(len-1)?(L2+gap-1):(len-1);/////?????
  10. while(L2<=len-1)/////?????
  11. {
  12. while(L1<=H1 && L2<=H2)
  13. {
  14. if(arr[L1]<= arr[L2])
  15. {
  16. crr[i++]= arr[L1++];
  17. }
  18. else
  19. {
  20. crr[i++]= arr[L2++];
  21. }
  22. }
  23. while(L1<=H1)
  24. {
  25. crr[i++]= arr[L1++];
  26. }
  27. while(L2<=H2)
  28. {
  29. crr[i++]= arr[L2++];
  30. }
  31. L1 = H2+1;
  32. H1 = L1+gap-1;
  33. L2 = H1+1;
  34. H2 =(L2+gap-1)<=(len-1)?(L2+gap-1):(len-1);/////?????
  35. }
  36. while(L1<=len-1)/////?????
  37. {
  38. crr[i++]= arr[L1++];
  39. }
  40. for(int i=0;i<len;i++)
  41. {
  42. arr[i]= crr[i];
  43. }
  44. free(crr);
  45. }
  46. void merge_sort(int*arr,int len)///空间复杂0(n)
  47. {
  48. for(int i=1;i<len;i*=2)//2N*log2N
  49. {
  50. merge(arr, len, i);//2N
  51. }
  52. }
  1. template <class Type>void merge ( datalist<Type> & initList, datalist <Type> & mergedList, const int l, const int m, const int n ) { int i = 0, j = m+1, k = 0; while ( i <= m && j <= n ) //两两比较 if ( initList.Vector[i].getKey ( ) <=initList.Vector[j].getKey ( ) ) 
  2. { mergedList.Vector[k] = initList.Vector[i]; i++; k++; } else {  
  3. mergedList.Vector[k] = initList.Vector[j]; j++; k++; } if ( i <= m ) for ( int n1 = k, n2 = i; n1 <= n && n2 <= m;n1++, n2++ ) mergedList.Vector[n1] = initList.Vector[n2]; else for ( int n1 = k, n2 = j; n1 <= n && n2 <= n;n1++, n2++) mergedList.Vector[n1] = initList.Vector[n2];}
  4. template <class Type> void MergePass ( datalist<Type> & initList,datalist<Type> & mergedList, const int len ) { int i =0; while ( i+2*len <= initList.CurrentSize-1 ){ merge ( initList, mergedList, i, i+len-1, i+2*len-1); i += 2 * len; } if ( i+len <= initList.CurrentSize-1 ) merge ( initList, mergedList, i, i+len-1, initList.CurrentSize-1 ); else for ( int j=i; j <= initList.CurrentSize-1; j++ ) mergedList.Vector[j] = initList.Vector[j];}
  5. (两路)归并排序的主算法
  6. template<classType>
  7. voidMergeSort( datalist<Type>&list){
  8. //按对象关键码非递减的顺序对表list中对象排序
  9. datalist<Type>& tempList (list.MaxSize);
  10. int len =1;
  11. while( len <list.CurrentSize){
  12. MergePass(list, tempList, len ); len *=2;
  13. MergePass( tempList,list, len ); len *=2;
  14. }
  15. delete[]tempList;
  16. }
算法:
函数 MergePass( ) 做一趟两路归并排序,要调用merge ( )函数    n/(2*len)  O(n/len) 次,函数MergeSort( )调用MergePass( )正好log2n 次,而每次merge( )要执行比较O(len)次,所以算法总的时间复杂度为O(nlog2n)。

8、基数排序
(1)基数排序是采用“分配”与“收集”的办法,用对多关键码进行排序的思想实现对单关键码进行排序的方法。
(2)最高位优先MSD (Most Significant Digit first)
最高位优先法通常是一个递归的过程:
 先根据最高位关键码K1排序,得到若干对象组,对象组中每个对象都有相同关键码K1。
再分别对每组中对象根据关键码K2进行排序,按K2值的不同,再分成若干个更小的子组,每个子组中的对象具有相同的K1和K2值。
 依此重复,直到对关键码Kd完成排序为止。
 最后,把所有子组中的对象依次连接起来,就得到一个有序的对象序列。
(3)最低位优先LSD (Least Significant Digit first) 
首先依据最低位关键码Kd对所有对象进行一趟排序,再依据次低位关键码Kd-1对上一趟排序的结果再排序,依次重复,直到依据关键码K1最后一趟排序完成,就可以得到一个有序的序列。使用这种排序方法对每一个关键码进行排序时,不需要再分组,而是整个对象组都参加排序。
(4)为了有效地存储和重排 n 个待排序对象,以静态链表作为它们的存储结构。在对象重排时不必移动对象,只需修改各对象的链接指针即可。
  1. template<classType>
  2. voidRadixSort(staticlinklist<Type>&list,constint d,constint radix)
  3. {
  4. int rear[radix],front[radix];
  5. for(int i =1;i<list.CurrentSize;i++)
  6. }
  7. //queue中存数据
  8. void base_stor(int *arr,int len,int wide)
    {
        int m,n;
        int *tmp = arr;
        int i,j,k;
        LOOP_QUEUE base[10];
        for (i=0;i<10;i++)
        {
            InitQueue(&base[i]);
        }
        for (j=0;j<wide;j++)
        {
            for (k=0;k<10;k++)
            {
                n = arr[k] / (int)pow(10,(double)j);//计算^y
                m = n % 10;
                Push(&base[m],arr[k]);
            }
            k = 0;
            for (k=0;k<10;k++)
            {
                while (!IsEmpty(&base[k]))
                {
                    Pop(&base[k],tmp);
                    tmp++;
                }
            }
            tmp = arr;
        }
    }

(5)算法分析:
则称radix为基数。例如,关键码984可以看成是一个3元组(9, 8, 4),每一位有0, 1, …, 9等10种取值,基数radix = 10。关键码‘data’可以看成是一个4元组(d, a, t, a),每一位有‘a’, ‘b’, …, ‘z’等26种取值,radix = 26。
若每个关键码有d 位,需要重复执行d 趟“分配”与“收集”。每趟对 n 个对象进行“分配”,对radix个队列进行“收集”。总时间复杂度为O ( d ( n+radix ) )。
若基数radix相同,对于对象个数较多而关键码位数较少的情况,使用链式基数排序较好。
基数排序需要增加n+2radix个附加链接指针。
基数排序是稳定的排序方法。

9、归并排序
 当待排序的对象数目特别多时,在内存中不能一次处理。必须把它们以文件的形式存放于外存,排序时再把它们一部分一部分调入内存进行处理。这样,在排序过程中必须不断地在内存与外存之间传送数据。这种基于外部存储设备(或文件)的排序技术就是外排序。
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<assert.h>
  4. #include<time.h>
  5. void showex(int*arr,int len)
  6. {for(int i=0;i<len;i++)
  7. {
  8. printf("%5d ",arr[i]);
  9. if(i%5==4)
  10. {
  11. printf("\n");
  12. }
  13. }
  14. printf("\n");
  15. }
  16. void swap(int*p1,int*p2)
  17. {
  18. int tmp;
  19. tmp =*p1;
  20. *p1=*p2;
  21. *p2 = tmp;
  22. }
  23. char*arr_path ="f:\\arr.dat";
  24. voidCreateArrFile(unsignedlonglong n)
  25. {
  26. FILE*fw = fopen(arr_path,"wb");
  27. assert(fw != NULL);
  28. srand(100);
  29. for(unsignedlonglong i =0;i < n;++i)
  30. {
  31. int tmp = rand();
  32. fwrite(&tmp,sizeof(int),1,fw);
  33. }
  34. fclose(fw);
  35. }
  36. void showArrFile()
  37. {
  38. FILE*fr = fopen(arr_path,"rb");
  39. assert(fr != NULL);
  40. int tmp;int i =0;
  41. while(fread(&tmp,sizeof(int),1,fr)!=0)
  42. {
  43. printf("%8d",tmp);
  44. if(i%5==0)
  45. {
  46. printf("\n");
  47. }
  48. ++i;
  49. }
  50. printf("\n");
  51. fclose(fr);
  52. }
  53. void bubble_sort(int*arr,int len)
  54. {
  55. for(int i=0;i<len-1;i++)
  56. {
  57. for(int j=0;j<len-1-i;j++)
  58. {
  59. if(arr[j]> arr[j+1])
  60. {
  61. swap(&arr[j],&arr[j+1]);
  62. }
  63. }
  64. }
  65. }
  66. char*tmp_path ="f:\\tmp.dat";
  67. voidHandlerArrFile()
  68. {
  69. int arr[2000];
  70. FILE* fr = fopen(arr_path,"rb");
  71. assert(fr != NULL);
  72. FILE* fw = fopen(tmp_path,"wb");
  73. assert(fw != NULL);
  74. int count =0;
  75. while((count = fread(arr,sizeof(int),2000,fr))!=0)
  76. {
  77. bubble_sort(arr,count);
  78. fwrite(arr,sizeof(int),count,fw);
  79. }
  80. fclose(fr);
  81. fclose(fw);
  82. remove(arr_path);
  83. rename(tmp_path,arr_path);
  84. }
  85. #define LEN 30000
  86. #define SIZE 1000
  87. voidMergeArrFile(int gap)
  88. {
  89. FILE*fr = fopen(arr_path,"rb");
  90. FILE*fw = fopen(tmp_path,"wb");
  91. assert(fw != NULL && fr != NULL);
  92. int L1 =0;
  93. int H1 = L1 +gap-1;
  94. int L2 = H1+1;
  95. int H2 = L2+gap-1<LEN-1?L2+gap-1:LEN-1;
  96. int arr[1000],brr[1000],crr[2000];
  97. int i=1000,j=1000,k=0;
  98. //归并过程
  99. while(L2 <= LEN-1)
  100. {
  101. while(L1 <= H1 && L2<= H2)
  102. {
  103. if(i ==1000)
  104. {
  105. fseek(fr,L1*sizeof(int),SEEK_SET);//读数据1
  106. fread(arr,sizeof(int),1000,fr);
  107. i=0;
  108. }
  109. if(j ==1000)
  110. {
  111. fseek(fr,L2*sizeof(int),SEEK_SET);//读数据2
  112. fread(brr,sizeof(int),1000,fr);
  113. j =0;
  114. }
  115. if(arr[i]<=brr[i])
  116. {
  117. crr[++k]= arr[++i];
  118. L1++;
  119. }
  120. else
  121. {
  122. crr[++k]= brr[++j];
  123. L2++;
  124. }
  125. if(k ==1000)
  126. {
  127. fwrite(crr,sizeof(int),1000,fw);
  128. k =0;
  129. }
  130. }
  131. fwrite(crr,sizeof(int),k,fw);
  132. k =0;
  133. while(L1<=H1)
  134. {
  135. fseek(fr,L1*sizeof(int),SEEK_SET);
  136. fread(crr,sizeof(int),1,fr);
  137. fwrite(crr,sizeof(int),1,fw);
  138. L1++;
  139. }
  140. while(L2<=H2)
  141. {
  142. fseek(fr,L2*sizeof(int),SEEK_SET);
  143. fread(crr,sizeof(int),1,fr);
  144. fwrite(crr,sizeof(int),1,fw);
  145. L2++;
  146. }
  147. i =1000;
  148. j =1000;
  149. L1 = H2+1;
  150. H1= L1+gap-1;
  151. L2 = H1+1;
  152. H2 = L2+gap-1<LEN-1?L2+gap-1:LEN-1;
  153. }
  154. while(L1<=LEN-1)
  155. {
  156. fseek(fr,L1*sizeof(int),SEEK_SET);
  157. fread(crr,sizeof(int),1,fr);
  158. fwrite(crr,sizeof(int),1,fw);
  159. L1++;
  160. }
  161. fclose(fr);
  162. fclose(fw);
  163. remove(arr_path);
  164. rename(tmp_path,arr_path);
  165. }
  166. voidFileSort(int num)
  167. {
  168. HandlerArrFile();
  169. for(int i =2000;i<num; i = i*2)
  170. {
  171. MergeArrFile(i);
  172. }
  173. }
  174. int main()
  175. {
  176. CreateArrFile(30000);
  177. //showArrFile();
  178. FileSort(30000);
  179. //showArrFile();
  180. //HandlerArrFile();
  181. showArrFile();
  182. return0;
  183. }



0 0
原创粉丝点击