归并排序笔记

March 10, 2016
Algorithm

[TOC]

归并排序是一种渐近最优的基于比较排序的算法, 意即: 其在最坏情况下的比较次数和任意基于比较的排序算法所需的最少比较次数都是~NlgN。其主要的优点是可以保证将任意长度为 N 的数组排序的时间复杂度为 O(NlgN); 其主要缺点是空间复杂度为 O(N)。

这里均以 C++ 实现, 为了避免陷入到语言细节里所以仅针对 vector 进行操作, 并且遵循 C++ 左闭右开的区间标准: [a,b)。值得注意的是区间表示一致性这个细节对针对数组和搜索(如二分查找)的算法有着举足轻重的影响。

至于倾向于 [a,b) 左闭右开区间表示的原因可参考链接。简单来说主要原因有二: 一是 end-begin 即可得到区间大小; 二是当区间退化为 0 时包含左界更加”natural”。

自顶向下的归并排序

递归实现的归并排序是算法设计中分治思想的典型应用。

主要是两个函数: 由 MergeSort() 负责递归调用, Merge() 负责归并。

自底向上的归并排序

实现归并排序的另一种方法是化递归为循环自底向上进行归并, 即先归并微型子数组, 然后再成对归并得到的子数组, 如此这般直至将整个数组归并在一起。该实现比递归方法代码量少, 但复杂度一样。

template<class T>
void Merge(std::vector<T> &vec, int nHead, int nMid, int nEnd) {
    std::vector<T> tmp(vec);
    int nLeftIndex = nHead, nRightIndex = nMid;
    for (int i = nHead; i < nEnd; ++i){
        if (nLeftIndex >= nMid) vec[i] = tmp[nRightIndex++];
        else if (nRightIndex >= nEnd) vec[i] = tmp[nLeftIndex++];
        else if (tmp[nLeftIndex] < tmp[nRightIndex]) vec[i] = tmp[nLeftIndex++];
        else vec[i] = tmp[nRightIndex++];
    }
}

template<class T>
void MergeSortBU(std::vector<T> &vec, int nHead, int nEnd) {
    int nLength = nEnd - nHead;
    for (int sz = 1; sz < nLength; sz += sz){
        for (int i = nHead; i < nLength - sz; i = i + sz + sz){
            int nMin = nLength < i + sz + sz ? nLength : i + sz + sz;
            Merge(vec, i, i + sz, nMin);
        }
    }
}

Reference:

Algorithms, 4th Edition

https://github.com/acgtyrant/Algorithm-and-Data-Structure/wiki

http://stackoverflow.com/questions/9963401/why-are-standard-iterator-ranges-begin-end-instead-of-begin-end

微软2016校招在线笔试题解

April 15, 2016
Algorithm

快速排序笔记

March 15, 2016
Algorithm
comments powered by Disqus