C++编程练习(15)----“排序算法 之 归并排序“
归并排序
归并排序(Merging Sort)的原理:
假设初始序列含有 n 个记录,则可以看成是 n 个有序的子序列,每个子序列的长度为1,然后两两归并,得到 [n/2] ([ x ] 表示不小于 x 的最小整数)个长度为 2 或 1 的有序子序列;再两两归并,·······,如此重复,直至得到一个长度为 n 的有序序列为止,这种排序方法称为 2 路归并排序。
归并排序是一种较占用内存,效率高,稳定的算法。
整个排序过程如下图所示:
算法描述:
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
具体代码如下:
1、排序前的一些准备工作,建立合适的排序需要的结构。
/********* 排序用到的结构 头文件sort_struct.h ************/ #include <ctime> #include <cstdlib> #define MAXSIZE 100 //要排序数组个数最大值 class SqList{ public: int r[MAXSIZE+1]; int length; }; /* 交换L中数组r下标为i和j的值 */ void swap(SqList *L, int i, int j) { int temp = L->r[i]; L->r[i] = L->r[j]; L->r[j] = temp; } /* 显示数组内容 */ void showSqList(SqList *L) { for(int i=1;i<=L->length;i++) std::cout<<L->r[i]<<" "; std::cout<<std::endl; } /* 为数组随机产生一串数字 */ double random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } void RandomCreat(SqList *L,int len) { double random(double,double); srand(unsigned(time(0))); for(int i=1;i<=len;i++) { L->r[i] = int(random(0,100)); } }
2、编写主文件,实现排序与测试。
/********* C++堆排序算法 ************/ #include<iostream> #include<time.h> #include<Windows.h> #include"sort_struct.h" using namespace std; /* 将有序的SR[i...m]和SR[m+1...n]归并为有序的TR[1...n] */ void Merge(int SR[],int TR[],int i,int m,int n) { int j,k,l; for(j=m+1,k=i;i<=m && j<=n;k++) //将SR中记录由小到大归并入TR { if(SR[i]<SR[j]) TR[k] = SR[i++]; else TR[k] = SR[j++]; } if(i<=m) { for(l=0;l<=m-i;l++) TR[k+l] = SR[i+l]; //将剩余的SR[i...m]复制到TR } if(j<=n) { for(l=0;l<=n-j;l++) TR[k+l] = SR[j+l]; //将剩余的SR[j...n]复制到TR } } /* 将SR[]中相邻长度为s的子序列两两归并到TR[] */ void MergePass(int SR[],int TR[],int s,int n) { int i = 1; int j; while(i<=n-2*s+1) { Merge(SR,TR,i,i+s-1,i+2*s-1); //两两归并 i = i+2*s; } if(i<n-s+1) //归并最后两个序列 Merge(SR,TR,i,i+s-1,n); else //若最后只剩下单个子序列 for(j=i;j<=n;j++) TR[j] = SR[j]; } /* 对顺序表L作归并非递归排序 */ void MergeSort(SqList *L) { int *TR = new int[L->length+1]; //申请额外空间 int k = 1; while (k<L->length) { MergePass(L->r,TR,k,L->length); k = 2 * k; //子序列长度加倍 MergePass(TR,L->r,k,L->length); k = 2 * k; //子序列长度加倍 } delete[] TR; } int main() { SqList *L = new SqList; L->length = 10; RandomCreat(L,L->length); cout<<"排序前:"; showSqList(L); MergeSort(L); cout<<"归并排序后:"; showSqList(L); return 0; }
运行结果如下: