zoukankan      html  css  js  c++  java
  • 排序算法总结(二)归并排序【Merge Sort】

    一.归并排序原理(Wikipedia)

      归并排序本质是分治思想的应用,并且各层分治递归可以同时进行

      1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

      2.设定两个指针,最初位置分别为两个已经排序序列的起始位置

      3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

      4.重复步骤3直到某一指针到达序列尾

      5.将另一序列剩下的所有元素直接复制到合并序列尾

    二.过程

    原始数据

    seg = 1时

    我的算法参考的是wikipedia上的算法,与VisuAlgo上所示的稍有区别,VisuAlgo上是先2个数字合并,然后合并成4个有序数列,然后在对后面的2个合并,在合并成4个有序数列,把这两组有序数列合并成一个长度为8的有序数列。

     

    wikipedia上,是先将所有的单个数字合并成有序的长度为2的有序数组,然后在将所长度为2的分别合并成长度为4的有序数组,循环知道合成长度为Len的有序数组。个人认为wikipedia上的方法更加容易表达,因为不用回退可以一次性处理完所有相同长度的数据。

    wikipedia上代码的排序过程如图所示:

    3.代码(参考了wikipedia上的代码,只需要第一次分配一次空间)

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 template <typename T>
     7 void MergeSort( vector<T> & nums ) {
     8     int seg = 1;
     9     int len = nums.size(); 
    10     vector<T> CopyNums(nums);
    11     for(int seg = 1; seg < len; seg += seg ){
    12         for(int start = 0; start < len; start += seg + seg ){
    13             int low = start;
    14             int mid = min( start + seg, len );//对于最后一次归并 
    15             int high = min( start + seg + seg, len );//最后一次归并长度会大于len
    16             int k = low;
    17             int start1 = low;
    18             int end1 = mid;
    19             int start2 = mid;
    20             int end2 = high;
    21             while( start1 < end1 && start2 < end2 ){
    22                 CopyNums[k++] = nums[start1]<nums[start2]? nums[start1++]:nums[start2++];
    23             }
    24             while( start1 < end1 ){
    25                 CopyNums[k++] = nums[start1++];//如果start1后还有元素没有归并,则将start1后的元素进行归并 
    26             } 
    27             while( start2 < end2 ){
    28                 CopyNums[k++] = nums[start2++];////如果start2后还有元素没有归并,则将start2后的元素进行归并  
    29             }
    30         }
    31         nums.swap(CopyNums);//在C++ STL中,耗时是常量,因为实际并没有交换他们的值,而只是交换了指针。
    32         //(i.e., the containers exchange references to their data, without actually performing any element copy or movement)37     }
    38 } 
    39 
    40 int main(){
    41     vector<int> nums{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
    42     cout<<" Before Sort:" ;
    43     for( auto m: nums){
    44         cout <<  m <<" ";
    45     }
    46     cout<<endl;
    47     MergeSort( nums );
    48     cout<< " After Sort:";
    49     for( auto m: nums){
    50         cout  << m <<" ";
    51     }
    52     cout<<endl;
    53 }

    4.总结

    1.空间复杂度,因为只有开始分配了一次与原始数据相同长度的空间,所以空间复杂度为O(n);

    2.时间复杂度,总的比较次数在(nlogn)/2和nlogn-n+1之间;

    3.归并排序是稳定的排序算法。 

  • 相关阅读:
    人间故事馆话题:聊聊那些被骗经历,让其他人不再被骗
    路过的风景
    路过的风景
    上海最适合拍照的旅游地点
    Java EE (11)
    五、服务器端的局域网
    P1294 高手去散步 洛谷
    堆排序【模板】
    P3383 【模板】线性筛素数 洛谷
    P1516 青蛙的约会 洛谷
  • 原文地址:https://www.cnblogs.com/rockwall/p/5741690.html
Copyright © 2011-2022 走看看