讲解在5分钟
荷兰国旗 在10分钟 这里定义了两个区域 小于区和大于区
30分钟
如下图 就是给定一个数 一般我们以最后一位数 当成num (后面是随机快排 会将这个数和其它的数进行随机交换 所以叫做随机快排)
这个数 小于的放左边 等于放中间 大于放右边
加上这一行就代表是随机快排 swap就代表随机了一个位置
随机快排是最常用的排序
55分钟
注意在工程上不允许递归行为的出现 任何递归行为可以变成循环 我们自己压这个断点 不用系统帮我们压栈
怎么改成非递归?
1:16开始 堆排
堆结构就是一颗完全二叉树 完全二叉树要么是一颗满的二叉树(任何一个非叶节点 孩子一定是全的这就是满二叉树 最底下一层都是叶节点)
或者从左到右 依次补齐的树 也是完全二叉树
堆在实际中可以用数组来实现 可以把一个数组理解为一颗完全二叉树 这个二叉树实际上是我们脑补出来的
通过下标 之间的数值关系计算 就可以计算出 左右关系和父节点
两种堆 大根堆和小根堆
大根堆 在这颗完全二叉树中任何一颗子树的最大值就是头部 小根堆任何一颗子树的最小值就是头部 对于任何一颗子树就是这样
怎么把数组转换成堆??1:27
建立大根堆
代码 1:35
heapInsert就是 向上插入的过程 如果比父节点大就交换
heapInsert是建立大根堆的过程
建立大根堆的复杂度 1:38时
当一个数 加进来时 之和沿途的点有关 和其它的数没有关系
所以一个数加进来 就和高度有关
一颗二叉树 节点数为N的话 那么她的高度为logN , 所以这里建立大根堆的复杂度和节点高度有关 log1+log2+..logN-1=N N个节点加入进来变成大根堆的复杂度就是
O(N)
heapify的作用就是为了 当堆顶弹出了 最后一个和堆顶arr[0]进行交换 然后进行heapify下沉的操作
heapify就是 当数组当中某个值变小了 这里举例是变小了 往下沉 怎么重新转换成大根堆 讲解在1:45时
这里由6->1
1这个值 找到他的左右两个孩子 找到左右两个孩子中最大的那个交换 同理交换后再次找到 左右两个孩子
代码讲解 1:50时
heapSize代表 我们可能是0~i范围上 进行限定范围 就是标记是否越界 进行heapify
0->heapSize-1这个范围上已经形成了堆 再往右就越界
我们index位置上面的值发生了变化 变小了 导致index应该下沉
总结 2:00时
我们可以认为堆是可以在数组上面伸缩的 注意我们这里还是没有讲堆排序 只是讲了堆这个结构
2:02时
有一个流 突出数 我们想找到流中随时突出的中位数 吐出的数是无序的
要求任何时候求出吐出所有数的中位数
我们需要使用堆结构
笨办法是 创建一个大的数组 然后就往数组里面存 算出中位数 收集的代价是O(1) 我们需要O(n*logn)的排序代价 而且是每次插入数都需要排序 浪费时间
解决办法:2:04时 准备两个堆大根堆和小根堆 具体实现看视频
贪心结构都是利用堆的 优先级队列就是堆而不是双向链表
2:20 这里可以先不用理解 因为还没有说比较器
这个就是整个的代码实现
堆排序就是利用堆结构完成的排序 2:20时
1)让数组变成大根堆
2)堆顶位置和最后一个进行交换 让堆的大小减1
6就相当于永远不动了 heapSize--
3)然后3做heapify的调整 然后依次作此操作
整个数组就从小到大就排完序了
代码2:25