归并排序
来源:互联网 发布:red hat linux 9 编辑:程序博客网 时间:2024/06/13 06:55
- 概述:
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divideand Conquer)的一个非常典型的应用。归并排序先分解要排序的序列,从1分成2,2分成4,依次分解,当分解到只有1个一组的时候,就可以排序这些分组,然后依次合并回原来的序列中,这样就可以排序所有数据。
#include <iostream> using std::cin; using std::cout; using std::endl; /** * 合并两个子列中的数据到一个数组中,每个子列都是有序的从小到大排列 * @ l 左边界 r右边界 * @unsorted unsorted数组unsorted[l..r-1] 其中unsorted[r..mid-1] unsorted[mid..r-1]分别是有序的数组 * @sorted 过度数组 */ template<class T> static void Merge(T unsorted[] ,size_t l,size_t mid,size_t r,T sorted[]) { int i = l,j=mid; //声明iterator int k =0; //同时从两个队列中获取最小的元素,直到其中一个为空 while(i<mid &&j<r) if(unsorted[i]>unsorted[j]) sorted[k++] = unsorted[j++]; else sorted[k++] = unsorted[i++]; //整合非空的队列到数组中 while(i<mid) sorted[k++] = unsorted[i++]; while(j<r) sorted[k++] = unsorted[j++]; //将已经有序的队列重新放置到由原来的数组 for(int v=0;v<k;unsorted[l+v]=sorted[v++]); }template<class T>static void printArray(T* arr,size_t l,size_t r){for(int i=l;i<r;i++)std::cout<<arr[i]<<" ";}//递归进行归并排序 template<class T> static void MergeSort(T unsorted[],size_t l,size_t r,T sorted[]) { if(l+1<r) { size_t mid = (l+r)>>1; MergeSort(unsorted,l,mid,sorted); MergeSort(unsorted,mid,r,sorted); Merge(unsorted,l,mid,r,sorted); } } void testMergeSort() { int arr[] = {1,3,5,67,4,23,5,7,3,6,4,33}; int lenght = sizeof(arr)/sizeof(int); int* sorted = new int[lenght]; cout<<"Before sorted:"; printArray(arr,0,lenght); cout<<"\n";MergeSort(arr,0,lenght,sorted);printArray(arr,0,lenght);delete[] sorted; cout<<endl;int arr2[] = {4,1};lenght = sizeof(arr2)/sizeof(int);sorted = new int[lenght];cout<<"Before sorted:"; printArray(arr2,0,lenght); cout<<"\n";MergeSort(arr2,0,lenght,sorted);printArray(arr2,0,lenght);delete[] sorted;} int main() { testMergeSort(); return 1; }
- 稳定性:
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序是稳定的排序算法。
- 复杂度分析:
Merge操作是线性的,也就是那个n,然后分治时候是T(n/2),所以公式是
T(n)=2T(n/2)+n
经过简单地数学推导就可以知道时间复杂度为O(nlogn)
空间复杂度O(n),用来作为过渡数组的
- 另附python测试代码:
import randomimport timedef mergesort(seq):if len(seq) <= 1:return seqmid = len(seq) >> 1left = mergesort(seq[:mid])right = mergesort(seq[mid:])return merge(left, right)def merge(left, right):result = []i, j = 0, 0while i < len(left) and j < len(right):if left[i] <= right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result += left[i:]result += right[j:]return resultif __name__ == '__main__':seqtarget = range(1,10**6)seq = seqtarget[:]time_result = []for i in range(10):random.shuffle(seq)start = time.clock()seq = mergesort(seq)end = time.clock()time_result.append(end - start)assert(seqtarget == seq)print time_resultprint "The avg sort 10^6 time is: %f" % (sum(time_result)/len(time_result))
Result:
The avg sort 10^4 time is: 0.038085The avg sort 10^5 time is: 0.476787The avg sort 10^6 time is: 6.205277The avg sort 10^7 time is: 82.397774
Hadoop出现之后,归并排序的变得更加流行,在分布式集群中运行归并排序算法,让原本望而生畏的归并排序算法变得更加浅显易懂。因此在此要感谢Hadoop的贡献者们。
0 0
- 归并排序-归并排序
- 归并和归并排序
- 归并与归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 排序::归并
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- Codeforces Round #279 (Div. 2) D. Chocolate
- 对C++中函数原型作用域的理解
- 每日学习心得:SharePoint 为列表中的文件夹添加子项(文件夹)、新增指定内容类型的子项、查询列表中指定的文件夹下的内容
- 第十三周项目三—成绩处理函数版
- POJ 1129-Channel Allocation(四色定理+迭代深搜)
- 归并排序
- uva--10602+贪心
- 正则表达式基础应用(切割split(regex))
- 网站的所有页面底部多出来了一个js代码
- Hibernate Projections(投影、统计、不重复结果)
- oracle的一些操作
- php学习笔记(十四)变量
- 分布式系统的事务处理
- 第七章 复用代码 && 第八章 多态