排序-归并排序

基本思想

“归并”的含义就是将两个或两个以上的有序表组合成一个新的有序表。

下面的示意图来自博客图解排序算法(四)之归并排序

代码:(递归版本)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;


void Merge(vector<int>&num, int left, int mid, int right)
{
    vector<int>a(num.begin(), num.end()); //开辟一个辅助数组,并将待排序的数组赋值给新开辟的数组
    int i, j, k;
    for(i=left, j = mid+1, k = left; i<=mid && j<=right; k++)
    {
        if(a[i] > a[j])  // 比较 a 的左右两段中的元素,
            num[k] = a[j++]; // 将较小者复制到num中,
        else
            num[k] = a[i++];
    }
    // 下面的两个 while 循环只会执行其中的一个。
    while(i <= mid)
        num[k++] = a[i++]; //若第一个表没有检测完,则复制
    while(j <= right)
        num[k++] = a[j++];//若第二个表没有检测完,则复制

}

void MergeSort(vector<int>&num, int left, int right)
{
    if(left < right)
    {
        int mid = ((right - left) >> 1) + left;
        MergeSort(num, left, mid);
        MergeSort(num, mid+1, right);
        Merge(num, left, mid, right);
    }
}

int main()
{
    int numbers[] = {53, 17, 78, 9, 45, 65, 87, 32};
    vector<int>num(numbers, numbers+8);

    cout<<"数组的原来序列为:";
    vector<int>::iterator it = num.begin();
    for(it = num.begin(); it != num.end(); it++)
        cout<< *it <<' ';
    cout<< endl<<endl;

    // 归排序
    MergeSort(num, 0, num.size()-1);

    cout <<"经过归并排序后,数组变为: ";
    for(it = num.begin(); it != num.end(); it++)
        cout<< *it <<' ';
    cout<< endl;
    return 0;
}




 代码:迭代版本

#include <iostream>
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;


void MergeSort(vector<int>&num, int n)
{
    int i, next, left_min, right_min, left_max, right_max;
    // i 用于 for 循环迭代,temp 用来存储临时数组,
    vector<int>temp(num.begin(), num.end());
    // i 是步长,第一次是1个元素与1个元素相比,第2个是两个元素与2个元素相比
    for(i = 1; i<n; i *= 2)
    {
        // left_min 最后是要小于 n-i 的,这一点可以通过画图得到
        // left_min = right_max 是指上一组排序完成之后,将上一组的 right_max 赋值给下一组的 left_min
        for(left_min=0; left_min < n-i; left_min = right_max)
        {

            right_min = left_max = left_min + i;
            right_max = right_min + i;
            next = 0;
            if(right_max > n) // 因为奇数的数组最后很有可能 right_max > n,所以将它限制到最大为 n
                right_max = n;

            // 在这里跟递归中的归并操是一样的,从两个数组中取小的出来放入临时数组
            while(left_min < left_max && right_min < right_max)
            {
                if(num[left_min] < num[right_min])
                {
                    temp[next++] = num[left_min++];
                }
                else
                    temp[next++] = num[right_min++];
            }
            // 但是上面的过程并不会同时将左右两个数组的元素都放入临时存储数组 temp 中
            // 要么左边会剩一点,要么右边会剩一点,所以这个时候要对剩余的进行操作
            // 如果左边剩了,说明这些应该是最大的,应该放在数组的右边
            while(left_min < left_max)
            {
                num[--right_min] = num[--left_max];
            }
            // 将临时存储的元素放入数组中得到最后的结果
            while(next>0)//如果最后是右边数组有剩余,那么num数组中在right_min 和right_max 之间的数就不需要动了,因为他们是左右数组比较交换时是最大的。
                num[--right_min] = temp[--next];
        }
    }
}

int main()
{
    int numbers[] = {53, 17, 78, 9, 45, 65, 87, 32};
    vector<int>num(numbers, numbers+8);

    cout<<"数组的原来序列为:";
    vector<int>::iterator it = num.begin();
    for(it = num.begin(); it != num.end(); it++)
        cout<< *it <<' ';
    cout<< endl<<endl;

    // 归排序
    MergeSort(num, num.size());

    cout <<"经过归并排序后,数组变为: ";
    for(it = num.begin(); it != num.end(); it++)
        cout<< *it <<' ';
    cout<< endl;
    return 0;
}




 

参考文献:

  1. 图解排序算法(四)之归并排序
  2. 35. 排序算法(8):归并排序的迭代实现
  3. 维基百科-归并排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值