排序算法(3):归并排序

来源:互联网 发布:sql 必须使用别名 编辑:程序博客网 时间:2024/05/21 22:40

归并排序简介


归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

平均时间和最坏时间都是O(nlog(n)),辅助存储是O(n)。

1. 严蔚敏的书上说,递归写法很简洁,但实际上一般不用递归的做法。

2. 实际中,也一般不用两路归并。

对于第一个问题,这很神奇了。递归有的时候理解起来是很困难,但这一次恰好又是递归很好写,非递归很难写 -_-! 太诡异了。

对于第二个问题,为了学习该算法,我先用递归写两路合并,用数组实现


合并两个有序数组


合并两个有序的线性结构,数组也好,list也好,递归也好,非递归也好,前面都总结过了。
Review:两个线性结构的合并

今天要写的合并两个有序数组,其实是在一个有序数组中来合并。指定第一个的头、尾,指定第二个的头、尾,然后合并。
// 合并两个有序数组void unionArray(int x[], int low1, int high1, int low2, int high2) {int lowReserve = low1;// 怎么合并?int size = high2 - low2 + high1 - low1 + 2;int *B = new int[size]; // 临时的辅助数组int i = 0;while (low1<=high1 && low2<=high2) // 当low和high相等的时候,是某个数组中只剩最后一个元素没有合并了{if (x[low1] <= x[low2]) // 小的{B[i] = x[low1];low1++;}else {B[i] = x[low2];low2++;}i++;}// 一个到头了while (i<size){if (low1>high1) // L1 到头了{B[i] = x[low2];low2++;} else if(low2>high2){ // L2 到头了B[i] = x[low1];low1++;}i++;}for (int i = 0;i<size;i++){x[lowReserve] = B[i];lowReserve++;}delete[] B;}

两路归并排序

/************************************************************************//* 归并排序。数组实现。*//************************************************************************/#include <iostream>#include <time.h>#define N 6using namespace std;void swap(int &x, int &y) {int t = x;x = y;y = t;}// 合并两个有序数组void unionArray(int x[], int low1, int high1, int low2, int high2) {int lowReserve = low1;// 怎么合并?int size = high2 - low2 + high1 - low1 + 2;int *B = new int[size]; // 临时的辅助数组int i = 0;while (low1<=high1 && low2<=high2){if (x[low1] <= x[low2]) // 小的{B[i] = x[low1];low1++;}else {B[i] = x[low2];low2++;}i++;}// 一个到头了while (i<size){if (low1>high1) // L1 到头了{B[i] = x[low2];low2++;} else if(low2>high2){ // L2 到头了B[i] = x[low1];low1++;}i++;}for (int i = 0;i<size;i++){x[lowReserve] = B[i];lowReserve++;}delete[] B;}void mergeSortRecursion(int x[], int low, int high) {// 1. 结束条件if (low >= high){return;}// 只有2个元素的时候,才不往下递归了。就在两个元素之间比较了。else if (low + 1 == high) { // 两个元素if (x[low]>x[high]){swap(x[low],x[high]); // 从小到大排}return;}else { // 1. 对半剖开int mid = low + (high - low) / 2;mergeSortRecursion(x,low,mid); // 2. 对左边递归mergeSortRecursion(x,mid+1,high); // 3. 对右边递归// 执行到这里的时候,左边的已经排好序了,右边的也拍好序了// 4. 归并unionArray(x,low,mid,mid+1,high); // 合并两个排好序的,合并之后的结果,还是有序的}}void display(int * x){for (int i = 0;i<N;i++){cout<<x[i]<<" ";}cout<<"\n";}int main() {int x[N] = {5,3,2,1,4,77};cout<<"排序前"<<endl;display(x);clock_t s = clock();mergeSortRecursion(x,0,N-1);clock_t e = clock();cout<<"排序后"<<endl;display(x);cout<<"**********************************"<<endl;cout<<"the algorithm used "<<e-s<<" milliseconds."<<endl;system("pause");return 0;}
排序前
5 3 2 1 4 77
排序后
1 2 3 4 5 77
**********************************
the algorithm used 0 milliseconds.

归并排序的非递归形式


有待解决。








0 0
原创粉丝点击