归并排序的实现

来源:互联网 发布:淘宝上一直给差评 编辑:程序博客网 时间:2024/06/07 23:20

       最近工作中要用到排序,当然要选择O(nlgn)时间复杂度的算法,还要求是稳定的,周末就温习了一下排序算法,归并排序刚好能满足。自己也想练练手,就先实现了简单的对递归版本,之后实现了非递归的版本。它的空间复杂度为O(n)。  因为递归版本会使用函数堆栈,深度受到栈内存的限制,所以数据量不能太大,需要注意下。

//【归并排序--递归版本】#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <assert.h>void swap(int *a, int *b){int t = *a;*a = *b;*b = t;}void merge(int a[], int m, int n){int *b = (int*)malloc(sizeof(int)*n);assert(b != NULL);memcpy(b, a, sizeof(int)*n);int i = 0, j = m, k = 0;while(i < m && j < n){if (b[i] <= b[j]){a[k++] = b[i];i++;}else{a[k++] = b[j];j++;}}if (i < m){while (i < m) a[k++] = b[i++];}else{while (j < n) a[k++] = b[j++];}}void mergeSort(int a[], int n){if (n <= 1) return;if (n == 2) {if (a[0] > a[1])swap(a+0, a+1);return;}int m = n/2;mergeSort(a, m);mergeSort(a + m, n - m);merge(a, m, n);}void setRandData(int a[], int n){srand(time(NULL));for (int i = 0; i < n; i++){a[i] = rand();}}int main(){const int N = 10000000;int *a = (int*)malloc(sizeof(int) * N);assert(a != NULL);setRandData(a, N);//for (int i = 0; i < N; i++)//{//printf("%d\t", a[i]);//}printf("\n");clock_t t0 = clock();mergeSort(a, N);clock_t t1 = clock();printf("Take time %d ms\n", t1 - t0);for (int i = N/2; i < N && i < (N/2 + 200); i++){printf("%d    ", a[i]);}system("pause");return 0;}

//【归并排序--非递归版本】#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <assert.h>inline int min(int a, int b){return a < b ? a : b;}void setRandData(int a[], int n){srand(time(NULL));for (int i = 0; i < n; i++){a[i] = rand() * rand();}}void mergeSort(int a[], int n){int i, j, t, start1, end1, start2, end2, len;int *b = (int*)malloc(sizeof(int) * n);assert(b != NULL);len = 1;//len为每次分块的大小,即按照1,2,4,6,8,...,n增长while (len < n){t = 0;i = 0;j = i + len;while (j != n){//start1,end1,start2,end2用于表示进行比较的两个数据块下标,//坐标范围分别为[start1,end1),[start2,end2)。start1 = min(n, i);end1   = min(n, i + len);start2 = min(n, i + len);end2   = min(n, i + len + len);i = start1;j = start2;while (i < end1 && j < end2){if (a[i] <= a[j]) {b[t++] = a[i++];}else{b[t++] = a[j++];}}if (i < end1){while (i < end1)b[t++] = a[i++];}else{while (j < end2)b[t++] = a[j++];}//assert(i == end1 && j == end2 && t == end2);i = t;}len = min(n, len * 2);memcpy(a, b, sizeof(int) * n);}free(b);}int main(){const int N = 100000000;int *a = (int*)malloc(sizeof(int) * N);assert(a != NULL);setRandData(a, N);//for (int i = 0; i < N; i++)//{//printf("%d\t", a[i]);//}printf("\n");clock_t t0 = clock();mergeSort(a, N);clock_t t1 = clock();printf("Take time %d ms\n", t1 - t0);for (int i = N/2; i < N && i < (N/2 + 100); i++){printf("%d    \n", a[i]);}system("pause");return 0;}



【归并排序-使用模板】

mergesort.h

#ifndef __MERGESORT_H#define __MERGESORT_Hnamespace MyNamespace{typedef int (*Comparer)(const void *a, const void *b);template <typename T> int defaultCompare(T *a, T *b){if (*a == *b) return 0;return *a < *b ? -1 : 1;}template <typename T> void arrayCopy(T *a, const T *b, int n){while (--n >= 0) a[n] = b[n];}inline int minIndex(int a, int b){return a < b ? a : b;}template <typename T>int mergeSort(T a[], int n, Comparer comparer){T *b = NULL;int i, j, t, start1, end1, start2, end2, len;int cmpResult;b = new T[n];if (b == NULL) return -1;//len为每次分块的大小,即按照1,2,4,6,8,...,n增长len = 1;while (len < n){t = 0;i = 0;j = i + len;while (j != n){//start1,end1,start2,end2用于表示进行比较的两个数据块下标,//两个分块的下标范围为[start1,end1),[start2,end2)。start1 = minIndex(n, i);end1   = minIndex(n, i + len);start2 = minIndex(n, i + len);end2   = minIndex(n, i + len + len);//i,j分别表示当前进行比较的两个元素的下标i = start1;j = start2;while (i < end1 && j < end2){if (comparer != NULL)cmpResult = comparer(a+i, a+j);elsecmpResult = defaultCompare(a+i, a+j);b[t++] = (cmpResult <= 0) ?  a[i++] : a[j++];}if (i < end1){while (i < end1)b[t++] = a[i++];}else{while (j < end2)b[t++] = a[j++];}//assert(i == end1 && j == end2 && t == end2);i = t;}len = minIndex(n, len * 2);arrayCopy(a, b, n);}delete []b;b = NULL;return 0;}template <typename T>int mergeSort(T a[], int n){return mergeSort(a, n, NULL);}};#endif //__MERGESORT_H



main.cpp

#include <stdio.h>#include <stdlib.h>#include <string>#include <iostream>#include "mergesort.h"using namespace std;int myComparer(const int *a, const int *b){if (*a == *b) return 0;return *a < *b ? -1 : 1;}int myComparer2(const void *a, const void *b){if (*(int*)a == *(int*)b) return 0;return *(int*)a < *(int*)b ? -1 : 1;}struct S{int a;string str;bool operator== (const S &o){return (a == o.a) && (str == o.str);}bool operator< (const S &o){if (a != o.a) return a < o.a;return str < o.str;}};int main(){S ss[] = {{2, "ok"}, {1, "hi"},{4, "aa"}};int a[] = {3,2,7,9,8};//MyNamespace::mergeSort(a, 5, (MyNamespace::Comparer)myComparer);MyNamespace::mergeSort(a, 5, myComparer2);printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);////a[1] = 100;//MyNamespace::mergeSort(a, 5);//printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);MyNamespace::mergeSort(ss, 3);printf("%d,%s %d,%s\n", ss[0].a, ss[0].str.c_str(), ss[1].a, ss[1].str.c_str());system("pause");return 0;}

输出

2 3 7 8 91,hi 2,ok请按任意键继续. . .