标签:
归并排序(merge sort):
思想:如果只有一个元素,排序结束。否则递归地将前半部分和后半部分归并排序,再将排序得到后的两部分合并到一起。合并的方法是:取排序后的前半和后半看作两个输入数组A和B,一个临时输出数组C,以及三个计数器Ap,Bp,Cp并将其初始对应数组的开始端。A[Ap]和B[Bp]的较小者被拷贝到C的下一个位置,相关计数器向前推进一步。当两个输入数组有一个用完的时候,将另一个数组中剩余部分拷贝到C中。最后将数组C元素拷贝回原数组对应的位置。
先看合并算法的代码:
void merge(int a[], int t[], int l_pos, int r_pos, int r_end) { int i, l_end, num, t_pos; l_end = r_pos - 1; t_pos = l_pos; num = r_end - l_pos + 1; while (l_pos <= l_end&&r_pos <= r_end) if (a[l_pos] <= a[r_pos]) t[t_pos++] = a[l_pos++]; else t[t_pos++] = a[r_pos++]; while (l_pos <= l_end) t[t_pos++] = a[l_pos++]; while (r_pos <= r_end) t[t_pos++] = a[r_pos++]; for (i = 0; i < num; i++, r_end--) a[r_end] = t[r_end]; }
void m_sort(int a[], int t[],int left,int right) { int center; if (left < right) { center = (left + right) / 2; m_sort(a, t, left, center); m_sort(a, t, center + 1, right); merge(a, t, left, center + 1, right); } } void merge_sort(int a[], int n) { int *t; t = (int *)malloc(n * sizeof(int)); if (t != NULL) { m_sort(a, t, 0, n - 1); free(t); } }
之所以上面的归并排序算法看起来有点复杂,还分了m_sort和merge_sort两个函数,是出于优化该算法的目的。每次merge都要用到一个临时数组,如果每次调用merge函数都要动态分配并释放一个数组,那么由malloc占用的时间会很多。
分析归并排序算法,我们设对n个元素归并排序最坏情形下所用时间T(n),观察m_sort,由于merge所用时间为O(n),最坏情形下为n我们得到一个关于T(n)的递推式:
T(1)=1(花费常数时间,我们把它记为1,记成θ(1)也可以)
T(N)=2T(n/2)+n
解这个递推式可得:T(n)=θ(nlogn)
在最坏情形下运行时间为θ(nlogn)那么归并算法的运行时间就是O(nlogn)。虽然它的运行时间是O(nlogn),但是在合并时需要线性附加内存,在整个算法中还要做许多数据拷贝,这严重影响了排序的速度。因此,对于重要的内部排序而言,快速排序会是一个更好的选择。
时间晚了,占坑明天填。
标签:
原文地址:http://www.cnblogs.com/evilkant/p/5771459.html