随看随记
- 堆排序用的少的原因:对堆排序中的数据是乱的,在堆排序的过程中,需要进行大量的数据交换,而且在交换的过程中,因为二叉堆中的数据无序,所以在进行一次交换,可能会需要同时访问到一大片数据。需要消耗掉很大部分缓存,堆内存也不友好,因此没人用。都用快速排序。
Basic Sorting
Selection Sort,Heap Sort
- 选择排序的步骤
- 寻找最小的那一项。
- 将这一项和最前面哪一项进行交换,并修正他。
- 重复剩下未被修复的部分,直到所有的项目都被修复。
- 其运行逻辑为
- 将所有的新的项目都放到最大堆中,并且丢弃输出数组,创建新的输出数组
- 重复N此以下动作
- 从最大堆中弹出最大值
- 将最大值放入到输出数组的未使用部分的末尾中
对于堆来讲,将数据存入堆的时候就已经做了最大最小的排序了,依靠堆的数据结构就已经办到了,当堆不断pop出最小值时,就已经实现了上述最有复杂度的找最小值的问题,接下来做的就只剩下吧新的最小值加进去新的堆中就可以了。
- 使用创建堆的方法解决了寻找最大最小值的问题 ,减少了时间复杂度
- 同时也增加了空间复杂度,是由于创建了新的数组和堆的空间
- 为了节省多建立一个数组的空间又有了In-place Heapsort排序
二叉最小堆保证其子节点第一是大于其父节点的,并且保证左节点满员。
- 其和其原始的Heapsort排序不同是其在最开始没有建立起一个真实的Heap,而仅仅根据数组的顺序将其进行了Heap化。Dome
- 通过将上面的数进行一步一步的下沉从而慢慢的变成了Heap形式的数组。
- 在所有的数全部下沉成功后,建立好一个Heap形式的数组,将Heap中的最大弹出的值交换原数组的值最后的数值,并将交换后的数组进行堆式重排。
直至形式Heap中所有的值都弹出完毕,结束
- In-place Heapsort排序其空间复杂度为恒定值θ(N)。
- 空间复杂度主要和常数实例变量有关,In-place Heapsort并没有真的建立数组或堆的空间,仅仅在原有的数组的基础上进行了操作,没有增加空间复杂度;
Merge Sort
- 自顶向下合并搜索
- 将一个数组分成大致均匀的 2 块。
- 对每一半都进行合并算法(这个部分是递归,空间复杂度极大,前面有,想看的话去前面看,不建议使用)
- 合并两个排序的一半以形成最终结果。
Insertion Sort
- 插入排序
- 创建一个新的空的输出序列(数组)
- 添加每一个项目从输入中,并且将其插入到输出中正确的位置
Dome
- In-place Insertion Sort(就地插入排序) 节省了空间复杂度 Dome
- In-place Insertion Sort(就地插入排序)从0到N-1重复
- 将第i项指定为要寻找位置的项(暂时称为已知项)
- 向后交换项目,直到已知项在所有物品中找到的正确位置,并且检查的项目。
Quick Sort
Insertion Sort
- 如果序列本身就是基本有序,那么直接插入排序效率高;
- 序列的个数比较少时,直接插入排序效率高;
- 对于合并排序,当被拆分后的数组长度小于15个,那么自动转化成Insertion Sort算法,之后再进行合并操作
Backstory,Partitioning
- 快速排序的核心就是分区 这里的要求是将红色的排到白色的左边 蓝色排到白色的右边。
- 老师给出了一个简单但是不快的方法:新建数组,扫描三次,先扫描红色的部分,补充到新的数组的左边,然后扫描白色的放到红色的左边,再扫描蓝色的,放到白色的左边。
- 学生1:将数组从最右边向0扫描,如果遇到红色的就放到白色的左边,如果遇到蓝色的就不动。
- 学生2:将数组放进BST中,BST的根为白色的6,这样的话,左边都是小于6(红色的),右边都是大于6(蓝色的)。
Quick Sort
- 快速排序
- 将整个数组根据第一个项目进行分组
- 快速排序左半边
- 快速排序右半边
- 快速排序就是一个递归操作,详情见Dome。
Quick Sort Performance Caveats and Conclusion
Avoid the worst case
- 快速排序的效率和以下三个有关: 最坏的情况会导致Θ(N^2)的运行时间
- 选择你的分区的轴
- 在你轴的附近如何进行你的分区
- 优化其他部分来提高效率
- 在实践中确实发生了非常罕见的 Θ(N^2) 情况
错误排序:排序前的数组已经排序(或几乎排序)。
数据不好:包含所有重复项的数组。
- 避免最坏情况这里举两个例子
- 随机: 选择一个随机的轴或者对这组数据进行洗牌。
- 智能的轴选择: 始终使用这组数据的中位数或近似中位数作为支点。
- 如果递归过于深入则更换另一种排序方法
- 对数组进行预排查,如果已经进本有序了就不用这个排序方法了
More Quick Sort, Sorting Summary
Quicksort Flavors vs. Mergesort
分区算法
- 快速排序的分区方法:这里大小和相同的对比对象是先前选定的轴,在Demo中用最左端的item代替了(Demo)
- 左指针L喜欢小的项目,讨厌大的或相同的项目
- 右指针G喜欢大的项目,讨厌小的或相同的项目
- 两个指针走向彼此,在他们不喜欢的位置暂停下来交换他们不喜欢的东西;
- 当两个指针暂停,交换并且都向下一个移动一步
- 当G在L左边时,他们就停止走动。
- 将G和轴进行交换。因为G的位置就是其中点,轴的所在位置。
轴的选择算法
- BFPRT
- 使用中位数做轴是否会减小运行时间很难说,因为很有可能在寻找中位数时所花费的时间会大大超过其使用中位数减少的时间
特定情况的时间
Selection (Quick Select)(选择中位数的算法)
- 也是采用了分区的思想,当数组的数目是固定的时候,再进行快速选择以后,对于数组的最中间的数就是其中位数。
- 在最左边的数字为轴进行分区,保留有中间数的那一部分,然后另一部分被舍弃掉,如此往复,直到自己就是中间的那个位置,就可以找到中位数了。
Stability,Adaptiveness,and Optimization
- 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。