归并排序:建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
主要思想为:将已有序的子序列合并,得到完全有序的序列。
简单来说:就是将待排序序列分为若干个最小子序列(子序列长度为1或2),先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并排序过程图如下:
正如我们所知,最普通的排序算法,其思想类似于穷举法,即遍历待排序数列,每一个元素都与数列中的元素作对比,找到相应的位置,故时间复杂度一般为O(n^2)。而归并排序采用的则是“分而治之”的思想,即:先将待排序数列不断地向下二分,获得最终的最简子数列,将子序列排序,在不断合并子序列。
这样做的好处在哪呢?向下二分使得子序列的分解时间下降为O(lgn),而传统方法的分解时间为O(n)。很多人可能就很奇怪了,为什么说传统方法的分解时间是O(n)啊?
拿冒泡排序来说吧,冒泡排序中,其实就是不断将长度为n的数列分为长度为1和长度为n-1的两个子序列,拿长度为1的序列不断与n-1序列中的每一个元素作比较,找到最合适的位置。
而在子序列的排序过程中,虽然归并排序和传统排序相似,时间复杂度均为O(n),但事实上,归并排序中元素多余的移动会更少一些(当然,优化后的冒泡排序效果差不多,详见:Click Me!!!)。
我这里只是写了一个最简单的实现,在写的过程中我考虑了很多优化的方案,以后会和大家分享哒~
#include <stdio.h>
#define MAX 5
void merge(int a[], int start, int end,int result[]);
int main(){
int start = 0;
int end = MAX - 1;
int a[MAX] = { 2, 3, 8, 6, 1 };
int result[MAX];
merge(a, start, end, result);
for (int i = 0; i < MAX; i++){
printf("%d", result[i]);
}
getchar();
}
void merge(int a[], int start, int end, int result[]){
int mid = (end + start) / 2;
if (end - start == 1){
if (a[start] > a[end]){
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
}else if (end - start <= 0){
}else{
merge(a, start, mid, result);
merge(a, mid + 1, end, result);
int pointerA = start;
int pointerB = mid + 1;
for (int i = start; i < (end - start + 1); i++){
if (a[pointerA] < a[pointerB]){
if (pointerA <= mid ){
result[i] = a[pointerA];
pointerA++;
}
else{
result[i] = a[pointerB];
pointerB++;
}
}
else{
if (pointerB <= end){
result[i] = a[pointerB];
pointerB++;
}
else{
result[i] = a[pointerA];
pointerA++;
}
}
}
}
}
原文地址:http://blog.csdn.net/u012403246/article/details/45666915