快速排序、归并排序、堆排序的C++实现_独家原创

作为最常用的三大排序方法,必须掌握。这里给出递归写法C++实现,相比迭代写法会更容易理解。

代码实现

#include <iostream>
#include <vector>

using namespace std;

class Solution {
public:
    void SortArr(vector<int>& nums) {
        //quickSort(nums, 0, nums.size() - 1);
        //mergeSort(nums, 0, nums.size() - 1);
        heapSort(nums);
    }

private:
    void quickSort(vector<int>& nums, int l, int r) {
        if (l < r) {
            int pos = partition2(nums, l, r);
            quickSort(nums, l, pos - 1);
            quickSort(nums, pos + 1, r);
        }
    }

    // 以pivot分隔,选最左为pivot
    // 第一种Partition方式,对撞指针法
    int partition(vector<int>& nums, int l, int r) {
        // 随机化加速,抑制最坏时间复杂度
        int i = rand() % (r - l + 1) + l;
        swap(nums[i], nums[l]);
        int pivot = nums[l];
        while (l < r) {
            // 右侧第一个小于pivot的元素
            while (l < r && nums[r] >= pivot) --r;
            nums[l] = nums[r];
            // 左侧第一个大于pivot的元素
            while (l < r && nums[l] <= pivot) ++l;
            nums[r] = nums[l];
        }
        nums[l] = pivot;
        return l;
    }

    // 第二种Partition方式,快慢指针法
    int partition2(vector<int>& nums, int l, int r) {
        // 随机化加速,抑制最坏时间复杂度
        int tmp = rand() % (r - l + 1) + l;
        swap(nums[tmp], nums[l]);
        int pivot = nums[l];
        int i = l + 1;
        for (int j = l + 1; j <= r; ++j) {
            if (nums[j] <= pivot) {
                swap(nums[i], nums[j]);
                ++i;
            }
        }
        swap(nums[i-1], nums[l]);
        return i-1;
    }

    void mergeSort(vector<int>& nums, int l, int r) {
        if (l == r) return;

        // 分解
        int mid = l + (r - l) / 2;
        mergeSort(nums, l, mid);
        mergeSort(nums, mid + 1, r);

        // 合并
        int i = l, j = mid + 1, pos = 0;
        vector<int> tmp(r - l + 1); // 合并时需要辅助数组
        while (i <= mid && j <= r) {
            tmp[pos++] = nums[i] <= nums[j] ? nums[i++] : nums[j++];
        }
        // 还有剩余
        while (i <= mid) {
            tmp[pos++] = nums[i++];
        }
        while (j <= r) {
            tmp[pos++] = nums[j++];
        }
        copy(tmp.begin(), tmp.end(), nums.begin() + l);
    }

    void heapSort(vector<int>& vec) {
        int sz = vec.size();
        // S1.建大顶堆
        // sz/2-1是最后一个非叶子节点
        for (int i = sz / 2 - 1; i >= 0; --i) {
            down(vec, i, sz);
        }

        // S2.大顶堆一个一个把最大的移到末尾
        for (int i = sz - 1; i > 0; --i) {
            swap(vec[0], vec[i]); // 把最大的移到末尾
            down(vec, 0, i); // 维持大顶堆,只需调整i=0,注意sz变为了i
        }
    }

    void down(vector<int> &vec, int i, int sz) {
        // 核心就是找i和其lSon、rSon三者最大的换到i的位置
        int lSon = i * 2 + 1;
        int rSon = i * 2 + 2;
        int maxIdx = i;
        if (lSon < sz && vec[lSon] > vec[maxIdx]) maxIdx = lSon;
        if (rSon < sz && vec[rSon] > vec[maxIdx]) maxIdx = rSon;

        if (maxIdx != i) {
            swap(vec[i], vec[maxIdx]);
            down(vec, maxIdx, sz);
        }
    }
};

int main() {
    Solution sln = Solution();
    vector<int> nums = { 1, 3, 5, 2, 2, 6 };
    sln.SortArr(nums);
    for (int num : nums) {
        cout << num << ' ';
    }
    return 0;
}

快排本身有劣势,数字一样变n方。

实现思路可参考:

算法 | 菜鸟分类 | 菜鸟教程 (runoob.com)

漫画:“排序算法” 大总结 - 知乎 (zhihu.com)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值