归并排序的迭代实现

之前在另一篇文章中C++ 归并排序与快速排序详细分析了归并排序的递归实现,但是会占用大量的时间和空间,算法的效率低下;使用迭代的方式代替递归的方式虽然比较难想,但是会增大效率。

如何写迭代?

根据上面的图,我们可以先把数组划分为n组,刚开始每组只有一个值。然后相邻的小组不断进行两两合并,最终合并成为一个组。

可以用一个变量来枚举步长1,2,4,……,对由每个步长分开的区间,都合并一下。 
比如,一开始数组为[8 7 6 5 4 3 2 1]。 
第一遍,步长为1,将相邻的两个区间合并: 
7 8 6 5 4 3 2 1 
7 8 5 6 4 3 2 1 
7 8 5 6 3 4 2 1 
7 8 5 6 3 4 1 2

第二遍,步长为2,将相邻的两个区间合并: 
5 6 7 8 3 4 1 2 
5 6 7 8 1 2 3 4

第三遍,步长为4,将相邻的两个区间合并: 
1 2 3 4 5 6 7 8

步长是外层循环,以步长为基本单位的每一对分组经过排序形成新的double分组不断迭代是内层循环。

【代码】

#include<iostream>
#include<vector>

using namespace std;

// 区间[head1, head2-1]和[head2, tail2]都是排好序的,现在需要合并
void mergeSortHelper(vector<int>& v, int head1, int head2, int tail2) {
    int tail1 = head2 - 1, index = 0, len = tail2 - head1 + 1, start = head1;
    vector<int> tmp(len);
    while (head1 <= tail1 || head2 <= tail2) {
        if (head1 > tail1)
            tmp[index++] = v[head2++];
        else if (head2 > tail2)
            tmp[index++] = v[head1++];
        else {
            if (v[head1] <= v[head2])
                tmp[index++] = v[head1++];
            else
                tmp[index++] = v[head2++];
        }
    }
    
    for (int i = 0; i < len; ++i)
        v[start+i] = tmp[i];
}

void mergeSort(vector<int>& v) {
    int len = v.size();
    // 倍进枚举步长1,2,4,……
    for (int step = 1; step <= len; step <<= 1) {
        int offset = step + step;
        for (int index = 0; index < len; index += offset)
            mergeSortHelper(v, index, min(index+step, len-1), min(index+offset-1, len-1));
    }
}

int main(){
    vector<int> a = {3,1,2,4,5,8,7,6};
    mergeSort(a);
    for(int i=0;i<8;++i)
        cout<<a[i]<<" ";
}

本文参考:https://blog.csdn.net/Jacketinsysu/article/details/52472364

猜你喜欢

转载自blog.csdn.net/zpznba/article/details/88395447