排序(严蔚敏版)

  1. 快排
class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        quick_sort(nums, 0, nums.size() - 1);
        return nums;
    }
    void quick_sort(vector<int>& nums, int l, int r) {
        if (l >= r) return;
        int left = l, right = r;
        swap(nums[l], nums[(l + r) / 2]);
        int pivot = nums[l];
        while (l < r) { //循环体内只扔了一对次,得一直扔到l==r
            // 这里的l<r,是怕r为了找这次要扔的数,跑到l左侧那就没必要了,因为r右侧都是比Pivot大的,l左侧都是比pivot小的,这里l和r都是一个位子一个位子移动的,只要移动到l和r重合,就已经完成使命了。如果r还要继续左移,
            //下面这两个while必须有一个有等于的,否则就会死循环,因为l<r并且谁的值都不变,没有脱离这个循环的改变
            while (nums[r] >= pivot && l < r) r--;//必须得r先扔给l,因为pivot=nums[l],l现在的位置是坑
            nums[l] = nums[r];
            while (nums[l] <= pivot && l < r) l++;
            nums[r] = nums[l];
        }
        // 因为l和r肯定有一个是坑(每次都是一个抛出去变成坑,然后移动另一个),结束循环肯定是l==r,因此这个坑一定是空的
        nums[l] = pivot;
        quick_sort(nums, left, l - 1);
        quick_sort(nums, l + 1, right);
    }
};
  1. 堆排

堆排首先要了解堆的结构
从最后一个非终端节点开始建堆
最后一个非终端节点下标的求法:从父子节点的关系考虑

  • 如果堆节点从0开始,父节点编号i,则子为2i+1,2i+2,因此通过子下标m求父应该(m-1)/2
  • 堆节点从1开始,父i,子2i,2i+1,子下标m,则父为m / 2

注意这里的m是子的下标,如果说数组长度len,则最后一个下标为m-1

// 堆的定义:1. 完全二叉树 2. 小顶堆:父节点小于等于子节点
// 小顶堆的特点就是堆顶是最小的,因为每个节点都有父节点,因此最小的元素一定是出现在堆顶的,否则就会有父节点把它压死。堆顶元素和整个堆的元素都有子孙关系,但左子堆的堆顶和右子堆的其它元素就没有子孙关系了,所以没有子孙关系的,高层可以比低层还重
// 堆的保持:可以摘除堆尾元素,对堆没影响。但摘除堆顶元素的空间就不行了,整个堆结构就被破坏了,可以放个大小不定的替代堆顶进行AdjustHeap操作
// 升序排列:要大顶堆,因为堆只保证堆顶元素是最大的或者最小的,每次只能输出堆顶的,输出之后,堆顶元素的位置得保留,放下一个
class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int r = nums.size() - 1;
        for (int i = (r - 1) / 2; i >= 0; i--) AdjustHeap(nums, i, r);
        for (int i = r; i > 0; i--) {
            swap(nums[0], nums[i]);
            AdjustHeap(nums, 0, i - 1);
        }
        return nums;
    }
    void AdjustHeap(vector<int>& nums, int l, int r) {
        int fa = l, son = l * 2 + 1;
        while (son <= r) {
        	// 调整son指向较大的儿子节点
            if (son + 1 <= r && nums[son] < nums[son + 1])  son++;
            // 千万不能忘了return,因为father>son就可以结束了
            if (nums[fa] >= nums[son]) return;
            swap(nums[fa], nums[son]);
            fa = son;
            son = fa * 2 + 1;
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值