排序算法-归并排序-c++实现-详细图解

基本思想

  1. 用递归的形式对序列进行拆分,并对拆分后的小块序列排序
  2. 将小块序列不断合并成最终排好序的长序列

操作演示

原素组的形式
最开始的原始数组
对数组进行第一次拆分

在这里插入图片描述
对数组进行第二次拆分
在这里插入图片描述
对数组进行第三次拆分
在这里插入图片描述
到这一步为止,原数组已被拆分为数个长度为1的小数组。

这一步的可以通过对原数组进行递归拆分来实现

void MergSort(int a[], int length){
    if(length > 1){
        int* list1 = a;
        int list1_size = length / 2;
        int* list2 = a + list1_size;
        int list2_size = length - list1_size;

        MergSort(list1, list1_size);
        MergSort(list2, list2_size);

        //用于对拆分后的子数组进行排序
        Merge(list1, list1_size, list2, list2_size);
    }
}

特别注意的是:

  1. 虽然在图形中,我们讲数组分割为了很多个小数组,但是在实际的内存操作中,我们并没有为这些拆分后的数组分配额外的内存
  2. 我们实际上是通过两个数组指针,list1、list2来对原数组进行虚拟的拆分操作

操作如图所示:
在这里插入图片描述

根据代码中的递归调用顺序,在进行了第一次拆分之后,会先对左半部分进行拆分。
操作后的到的结果如下:
红色线条表示第一次递归拆分
黑色线条表示第二次递归拆分
蓝色线条表示第三次递归拆分
在这里插入图片描述
至此,左半部分拆分完毕,此时,程序会调用的语句为

Merge(list1, list1_size, list2, list2_size);

此时,函数中的参数为:

参数Value
list15
list1_size1
list22
list2_size1

Merge函数

核心思想

1.构建一个临时数组temp[],将list1和list2里面的数据进行比较,按顺序放在temp数组里
2.使用temp数组,对list1进行覆盖

代码组成
void Merge(int* list1, int list1_size, int* list2, int list2_size){
    /**temp这个临时数组的大小是和原始数组的大小相同的*/
    int temple[8] ={};

    /**list1_point: 用来指向list1中现在正在进行比较的数的序列号*/
    /**list2_point: 用来指向list2中现在正在进行比较的数的序列号*/
    /**temple_point: 用来指向temple中这在进行处理的数的序列号*/
    int list1_point = 0;
    int list2_point =0;
    int temple_point = 0;

    /**如果list1中的数和list2中的数都没有遍历完,就不断对list1和list2中的数据进行比较*/
    while(list1_point < list1_size && list2_point <list2_size){
        /**list1和list2中,谁里面的数更小,就把谁的数放到temp里面去,并且它和temp的序列号都会前进一格*/
        if(list1[list1_point] > list2[list2_point]){
            temple[temple_point] = list2[list2_point];
            temple_point++;
            list2_point++;
        }
        else{
            temple[temple_point] = list1[list1_point];
            temple_point++;
            list1_point++;
        }
    }
    
    //右边列表空了,但是左边列表还有数,要把他放到现在的临时数组中去
    while(list1_point < list1_size){
        temple[temple_point] = list1[list1_point];
        temple_point++;
        list1_point++;
    }
    //左边列表空了,但是右边列表还有数,要把他放到现在的临时数组中去
    while(list2_point < list2_size){
        temple[temple_point] = list2[list2_point];
        temple_point++;
        list2_point++;
    }

    //第一波排序完了,把临时数组里的数字,按顺序放到list1里面去,因为list1开头还是原来的数组,只是用指针将原来的数组分割成了两个部分,实际上原数组并没有改变
    for(int m = 0; m < list1_size + list2_size; m++){
        list1[m] = temple[m];
    }

}
操作演示

这是现在原始列表的原始形式,为了方便讲解,现将数组的一部分单独拿出来
这是现在原始列表的原始形式,为了方便讲解,现将数组的一部分单独拿出来

在这里插入图片描述
这是Merge函数,进行操作时的数据形式。

比较操作完成之后,所得到的结果数据形式结果为:

在这里插入图片描述
最后使用temple来覆盖原数组
在这里插入图片描述
当执行完上述的这一次操作后,原始数组也会发生改变。
在这里插入图片描述
之后的操作也和上述的操作同理,就不再详细演示了。

完整代码

#include <iostream>
#include <cstdlib>

void Merge(int* list1, int list1_size, int* list2, int list2_size){
    /**temp这个临时数组的大小是和原始数组的大小相同的*/
    int temple[8] ={};

    /**list1_point: 用来指向list1中现在正在进行比较的数的序列号*/
    /**list2_point: 用来指向list2中现在正在进行比较的数的序列号*/
    /**temple_point: 用来指向temple中这在进行处理的数的序列号*/
    int list1_point = 0;
    int list2_point =0;
    int temple_point = 0;

    /**如果list1中的数和list2中的数都没有遍历完,就不断对list1和list2中的数据进行比较*/
    while(list1_point < list1_size && list2_point <list2_size){
        /**list1和list2中,谁里面的数更小,就把谁的数放到temp里面去,并且它和temp的序列号都会前进一格*/
        if(list1[list1_point] > list2[list2_point]){
            temple[temple_point] = list2[list2_point];
            temple_point++;
            list2_point++;
        }
        else{
            temple[temple_point] = list1[list1_point];
            temple_point++;
            list1_point++;
        }
    }
    
    //右边列表空了,但是左边列表还有数,要把他放到现在的临时数组中去
    while(list1_point < list1_size){
        temple[temple_point] = list1[list1_point];
        temple_point++;
        list1_point++;
    }
    //左边列表空了,但是右边列表还有数,要把他放到现在的临时数组中去
    while(list2_point < list2_size){
        temple[temple_point] = list2[list2_point];
        temple_point++;
        list2_point++;
    }

    //第一波排序完了,把临时数组里的数字,按顺序放到list1里面去,因为list1开头还是原来的数组,只是用指针将原来的数组分割成了两个部分,实际上原数组并没有改变
    for(int m = 0; m < list1_size + list2_size; m++){
        list1[m] = temple[m];
    }

}

void MergSort(int a[], int length){
    if(length > 1){
        int* list1 = a;
        int list1_size = length / 2;
        int* list2 = a + list1_size;
        int list2_size = length - list1_size;

        MergSort(list1, list1_size);
        MergSort(list2, list2_size);

        //用于对拆分后的子数组进行排序
        Merge(list1, list1_size, list2, list2_size);
    }
}

int main(){
    int a[8] = {5, 2, 9, 1, 4, 7, 8, 3};
    int length = sizeof(a) / sizeof(a[0]);

    //传进来的时候length=4
    MergSort(a, length);
    
     for(int m=0; m < length; m++){
        std::cout << a[m] << " ";
    }
    system("pause");
}

运行结果为:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值