归并排序是分治法的一种体现,建立在归并操作上。归并排序的思想是将一个数组分成两部分A,B,如果A, B是有序的,那只要将A, B合并起来即可,那么如何保证A, B是有序的呢?那就将A, B按一样的方法各自分成两部分...如此到当分出来的A, B都只有一个元素的时候,A, B都是有序的了。
这就是分治法的一种体现。这样因为A, B都是有序的,合并起来后就是一个完整的有序序列了。
那么,改如何进行合并?他的思想是:先新开一个大小为A, B大小之和的数组cSeq,设两个指针a, b分别指向A, B的第一个元素,然后将a, b正想的元素较大的那个赋到cSeq。并将指向较大的那个的指针指向下一个....如此知道某个指针遍历完了其对应的数组,这时停止遍历并将没有遍历完的那个数组剩下的元素直接赋到cSeq的后面。其实现如下:
1 void merge(int* aSeq, int lenOfA, int* bSeq, int lenOfB, int* cSeq) { 2 int i = 0, j = 0, k = 0; 3 4 while (i < lenOfA && i < lenOfB) { 5 if (aSeq[i] < bSeq[j]) 6 cSeq[k++] = aSeq[i++]; 7 else 8 cSeq[k++] = bSeq[j++]; 9 } 10 11 //将为遍历完的数组接到cSeq的后面 12 while (i < lenOfA) 13 cSeq[k++] = aSeq[i++]; 14 15 while(j < lenOfB) 16 cSeq[k++] = bSeq[j++]; 17 }
下面来看看归并排序的效率,设某数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。
归并排序使用递归来实现,因为归并是分治的,递归是比较常用的方法。递归思想是:先分别sort A, B两部分,然后将A, B合并。最终的程序如下:
#include <iostream> #include <stdio.h> using namespace std; void merge(int* aSeq, int begin, int mid, int end, int *cSeq) { int i = begin, j = mid + 1, k = 0; while(i <= mid && j <= end) { if (aSeq[i] < aSeq[j]) cSeq[k++] = aSeq[i++]; else cSeq[k++] = aSeq[j++]; } while (i <= mid) cSeq[k++] = aSeq[i++]; while (j <= end) cSeq[k++] = aSeq[j++]; //将合并后的数组赋给原数组,cSeq只是一个临时使用数组 //但是因为新开数组需要时间消耗,所以直接开好一个以后一直用... for (int i = 0; i != k; i++) aSeq[begin + i] = cSeq[i]; } void merge_sort(int *arrayToSort, int left, int right, int* temp) { if (left < right) { int midOfArray = (left + right) / 2; //首先将两部分排序,然后将两部分合并 merge_sort(arrayToSort, left, midOfArray, temp); merge_sort(arrayToSort, midOfArray + 1, right, temp); merge(arrayToSort, left, midOfArray, right, temp); } } void output(int *arrayToPrint, int len) { for (int i = 0; i != len; i++) printf("%d ", arrayToPrint[i]); } int main(int argc, char const *argv[]) { cout << "Enter the length of the array: "; int lenOfArray; scanf("%d", &lenOfArray); cout << "Enter the element of the array: "; int *arrayL = new int[lenOfArray]; for (int i = 0; i != lenOfArray; i++) scanf("%d", &arrayL[i]); int *temp = new int[lenOfArray]; merge_sort(arrayL, 0, lenOfArray - 1, temp); output(arrayL, lenOfArray); return 0; }
其实就算法来说,在一般情况下归并排序和快速排序是比较理想的了。。