美文网首页
3.3 分治模式的完美诠释:归并排序

3.3 分治模式的完美诠释:归并排序

作者: Aurochsy | 来源:发表于2019-03-23 16:20 被阅读0次

Chapter3: 更好的查找与排序算法

3. 分治模式的完美诠释:归并排序

1. 基本思想

对于一次递归的调用来说

  • 划分

    • 取中间坐标,将原数组划分为两部分
    • 分别递归对左右数组进行排序,该层调用的结果为左边数组有序,右边数组有序,但是左边数组的元素不一定比右边数组的小,如 [1,3,4,6,2,4,6,8]
  • 合并

    • 比如对于数组arr=[1,5,3,7,2,6,8,4] 进行一次归并排序调用(包括划分和左右数组排序)后,得到左数组 arr1=[1,3,5,7] ,右数组 arr2=[2,4,6,8]
    • 初始化: 让 left 指针指向做数组第一个元素,right 数组指向右数组第一个元素,设置一个辅助数组 tmpArr=int [8] ;
    • arr1[left]arr2[right] 比较,arr1[left]=1arr2[right]=2 小,将 arr1[left] 存入 tmpArr[0] ; arr1[left]指针下移1位,即left++, 此时 arr1[left]=3arr2[right]=2大,则将arr2[right] 存入tmpArr[1]; right++...循环直至其中一个数组的元素全部存入临时数组,另一个数组剩下的元素直接赋值到临时数组后面
归并排序示意图 某层递归调用上的合并示意图

2. 代码实现

#include<iostream>
#include<cstdlib>
using namespace std;

void mergeSort(int* arr,int begin,int end); 
void merge(int* arr,int begin,int mid,int end);

int main(){
    int arr[6]={1,3,2,5,4,7};
    int arrLen=sizeof(arr)/sizeof(arr[0]);
    
    mergeSort(arr,0,arrLen-1);
    
    for(int i=0;i<arrLen;i++){
        printf("%d ",arr[i]);
    }
    return 0;
} 

void mergeSort(int* arr,int begin,int end){
    if(begin<end){//注意这个出口条件,不然会陷入死循环 
        int mid=begin+((end-begin)>>1);
        mergeSort(arr,begin,mid);//递归调用起到划分作用
        mergeSort(arr,mid+1,end);
        merge(arr,begin,mid,end);
    }
}

//合并函数
void merge(int* arr,int begin,int mid,int end){
    int len=end-begin+1;//当前划分状态下的数组长度 
    int tmpArr[len];//辅助数组
     
    int leftP=begin;//左指针 
    int rightP=mid+1;//右指针 
    int i=0;//辅助数组当前存取的下标 
    //printf("initial. len=%d\n",len);
    
    while((leftP<=mid)&&(rightP<=end)){
        if(arr[leftP]<=arr[rightP]){
            tmpArr[i]=arr[leftP];
            i++;
            leftP++;
            //或直接写为 tmpArr[i++]=arr[leftP++];
        }
        else{
            tmpArr[i]=arr[rightP];
            i++;
            rightP++; 
        }
    }
    while(leftP<=mid){//如果左数组有剩余元素 
        tmpArr[i]=arr[leftP];
        i++; 
        leftP++;
    }
    while(rightP<=end){//如果右数组有剩余元素 
        tmpArr[i]=arr[rightP];
        i++;
        rightP++;
    }
    /*将排序好的辅助数组复制到原数组中,
    因为递归要用到上一层排好序的原数组,并所以这一步必不可少*/ 
    i=0;  
    while(begin<=end){
        arr[begin++]=tmpArr[i++];
    }
    //注意每次递归数组的开始位置不一样,为begin,不一定是0,所以不能用下面的赋值方法 
//  for(i=0;i<len;i++){
//      arr[i]=tmpArr[i];
//  }       

}

3. 快速排序和归并排序的比较

快速排序关键在于划分,归并排序关键在于合并

快速排序划分的左右两个数组左边数组的元素一定小于右边数组的元素,但是在左数组或右数组内元素不一定有序

归并排序划分的左右两个数组左边的数组的元素不一定小于右边的元素,但是在左右数组内的元素分别是有序的

快速排序的思想

  • 分解

    数组 A[p..r] 被划分为两个子数组 A[p...q-1]A[q+1,r] , 使得 A[q] 为大小居中的数,左侧 A[p..q-1] 中的每个元素都 <= 它, 而右侧 A[q+1,r] 中的每个元素都 >= 它。其中计算下标 q 也是划分过程的一部分。

  • 解决

    通过递归调用快速排序,分别对子数组 A[p...q-1] 和 A[q...r] 进行排序

  • 合并

    不存在合并的问题

4. 参考资料

[1] 图解排序算法(四)之归并排序

相关文章

  • 3.3 分治模式的完美诠释:归并排序

    Chapter3: 更好的查找与排序算法 3. 分治模式的完美诠释:归并排序 1. 基本思想 对于一次递归的调用来...

  • 数据结构复习笔记 - 排序(下)

    归并排序和快速排序 时间复杂度为 O(nlogn) 归并排序 归并排序使用的就是分治思想。分治,顾名思义,就是分而...

  • 归并排序(MergeSort)——算法导论

    一、归并排序 归并排序算法完全遵循分治模式。直观上其操作如下: (1)分解:分解等排序的n个元素的序列成各具n/2...

  • python实现归并算法

    归并排序是采用分治法的一个非常典型的应用,另一个可以采用分治法的是快速排序,归并算法比快速排序速度稍低。归并排序的...

  • 12 基本排序算法:归并排序

    归并排序 原理 归并排序思想 该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(d...

  • 排序算法之归并排序

    归并排序(Merge Sort) 归并排序是利用归并的思想实现排序的方式,该算法采用的是经典的分治算法 归并排序过...

  • 归并排序&快速排序

    归并排序 利用归并的思想实现排序方法,该算法采用经典的分治策略,分而治之。 代码实现 基础设置 归并排序 —— 非...

  • 数据结构--归并排序与基数排序

    一、归并排序归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-a...

  • 算法排序之归并排序和快速排序

    归并排序和快速排序用的都是分治的思想,用递归的编程技巧来实现.咱们先来看归并排序. 归并排序 归并排序的核心思想就...

  • 归并排序(二路归并排序)

    归并排序的思路 归并排序是通过“归并”操作完成排序的,将两个或者多个有序子表归并成一个子表。归并排序是“分治法”的...

网友评论

      本文标题:3.3 分治模式的完美诠释:归并排序

      本文链接:https://www.haomeiwen.com/subject/mpalvqtx.html