[MIT6.006] 3. Insertation Sort, Mege Sort 插入排序,归并排序
关于第2节课《Models of Computation, Document Distance》由于内容过于简单,所以不在这里进行记录,它主要就是讲了Python很多操作是constant time(即无C语言地址指针机制,所以比较费时且耗内存),此外就是谈及了一个文档距离(Document Distance)问题,简单来说就是将文档内所有词形成词袋,用词袋下的特征算余弦距离。需要注意的就是余弦相似度越大,文档就越相似,而余弦距离=1-余弦相似度,因此余弦距离越小,代表文档相似度就越高。
第3节课只讲解了两种排序算法:冒泡排序(课程上用Insertation Sort讲述的思路就是冒泡排序,而实际上Insertation Sort应为插入排序)和归并排序(Merge Sort)。除了这两个还有其他排序方法例如:选择排序,快速排序,插入排序,堆排序,基数排序等等(这些会进行拓展补充或后面的课程会进行讲述)。
对各类排序方法整理如下:
| 排序算法 | 时间复杂度 |
| 冒泡排序 | Ο(n2) |
| 归并排序 | Ο(nlog2n) |
| 选择排序 | Ο(n2) |
| 插入排序 | Ο(n2) |
| 快速排序 | 极端Ο(n2),最好Ο(nlog2n) |
| 堆排序 | Ο(n) |
| 希尔排序 | Ο(ns) (1<s<2) |
| 基数排序 | Ο(nlog2(r)m) (r为基数,m为堆数) |
注:这里讲解上表中标蓝色和红色的排序算法。红色为课程讲解的算法。
1. 冒泡排序
冒泡排序就是像气泡一样使用pairwise swap成对交换的方式进行排序。下图显示了从左到右冒泡排序的机制:
key不断地移动,然后如果key下的数小于它前面的数,则进行两两交换,并保证换过的数大于左边最近的数,如果不是,那得继续交换,直到key达到最后一个元素,并且是以升序排列的。由于时间复杂度是看最坏情况,那么key的移动得n次,而若第n次对比交换很糟糕(例如1在数列最后面),那么对比得进行n次,最后时间复杂度就为Ο(n2)。
2. 归并排序
如下图,假设要对长度为n的数列A进行排序,归并排序的思想就是Divide&Conquer分开并克服,首先将A着半拆分为左数列L和有数列R,然后分别对L和R进行各自的排序,最后进行L和R的合并操作。

在该课程里,讲师提到了归并排序用的是一种叫Two Fingers双指算法,这里我用上图的列子进行讲述:
- 如果数列a为[20,13,7,2,12,11,9,1],将它折半拆为左数列L:[20,13,7,2],右数列R:[12, 11, 9, 1];
- 对数列L和R各自进行排序,方法用冒泡排序或其他排序手段都行;
- 之后用箭头(指代手指)指向数列L和R最小的元素,进行比较,并先输出这个最小的元素,如上图就是min(1,2)=1。
- 之后在该最小元素下移动箭头至下一个元素,将其与原来另一个数列元素进行比较,如上图就是数列R的箭头移至9, 数列L由于上一步不是最小值,所以箭头不变,则对比箭头所指元素的到min(2, 9)=2,输出结果。重复上述操作箭头到达各自数列末尾。
如下图所示,这里复杂度为Ο(nlog2n)。这里可以简单的分为两块:(1)二路归并需要进行log2n次;(2)双指算法对单次二路归并进行n次箭头移动(帮助进行最小值比较操作)。因此就是nlog2n次。
注:接下来选择排序,插入排序和快速排序的内容整理自《Python程序员面试算法宝典》一书。
3. 选择排序
选择排序的思想很简单:找到一个数列的最小值,然后将它与当前第一个记录交换。时间复杂度为Ο(n2)。
4. 插入排序
插入排序的思想也很简单:初始化一个空数列b,找到数列a中的最小值,然后插入到空数列b中,再不断找最小值,不断插入到数列b末尾即可。时间复杂度为Ο(n2)。

5. 快速排序
关于快排可以看知乎这篇文章的动图:https://zhuanlan.zhihu.com/p/93129029 , 看完就能理解它的机制,它是一种非常高效的排序算法,主要有三个零件:left左指针,right右指针和base基准数。举个例子如下图所示:
- 首先假设数列a为[6, 3, 7, 4, 1],则left左指针为数列a最开始的元素6,right右指针为数列b最末端的元素1,base基准数为left左指针6(注意这个base基准数从头到尾都不改动的)。
- 先从right指向的数与base对比:
- 如果right<base,则将right值替换left值,然后left向右移一位,同时right值替换为空值,且right指针位置不变,然后让left此时指的数与base对比。
- 如果right>base,则将right值替换right值(即保持不变),然后right向左移一位,同时left值替换为空值,且left指针位置不变,然后让right此时指的数与base对比。
- 重复上述操作,直到左右指针重叠,此时就直接将base值放入重叠位置即可。
总结上面的就是:先右开始对比,之后'小于则替换left并移left,然后新left对比base'或’大于则替换right并移right,然后新right对比base‘, left和right重合后用base替换。它的时间复杂度取决于base值真实在排序后的位置,如果base刚好为排序中间的位置,时间复杂度为Ο(nlog2n),如果base为数列最大值或最小值,则为Ο(n2)。
[MIT6.006] 3. Insertation Sort, Mege Sort 插入排序,归并排序的更多相关文章
- [MIT6.006] 6. AVL Trees, AVL Sort AVL树,AVL排序
之前第5节课留了个疑问,是关于"时间t被安排进R"的时间复杂度能不能为Ο(log2n)?"和BST时间复杂度Ο(h)的关系.第6节对此继续了深入的探讨.首先我们知道BST ...
- [MIT6.006] 4. Heaps and Heap Sort 堆,堆排序
第4节课仍然是讲排序,但介绍的是一种很高效的堆排序. 在编程过程中,有时候会需要进行extrat_max的操作,即从一个数列里挨个抽取最大值并将其它从原数列中移除.而排序问题也可以看作是一个extra ...
- MIT6.006Lec03:插入排序,归并排序,递归树
MIT6.006是算法导论课,Lec03主要讲插入排序,归并排序,以及分析方法(递归树)等. 插入排序,可以分为线性插入排序.二分插入排序,区别在于当把数组中某元素插入到前面的有序列表中时,前者遍历, ...
- [LeetCode] Insertion Sort List 链表插入排序
Sort a linked list using insertion sort. 链表的插入排序实现原理很简单,就是一个元素一个元素的从原链表中取出来,然后按顺序插入到新链表中,时间复杂度为O(n2) ...
- [LeetCode] 147. Insertion Sort List 链表插入排序
Sort a linked list using insertion sort. A graphical example of insertion sort. The partial sorted l ...
- LeetCode 147. Insertion Sort List 链表插入排序 C++/Java
Sort a linked list using insertion sort. A graphical example of insertion sort. The partial sorted l ...
- ORA-12805: parallel query server died unexpectedly ORA-04030 (sort subheap,sort key) 原因排查与解决方法
今日,某服务器pga调整为30G,_pga_max_size调整为8G之后(原来是2G,但是one passes语句较多,性能太低),执行出现ORA-12805: parallel query ser ...
- [Algorithms] Sorting Algorithms (Insertion Sort, Bubble Sort, Merge Sort and Quicksort)
Recently I systematicall review some sorting algorithms, including insertion sort, bubble sort, merg ...
- ruby 数组array 排序sort 和sort!
1. sort → new_ary click to toggle source sort { |a, b| block } → new_ary Returns a new array created ...
随机推荐
- super函数
Python面向对象中super用法与MRO机制:https://www.cnblogs.com/chenhuabin/p/10058594.html python 中 super函数的使用:http ...
- charles系列
charles 手机抓包 教程:https://www.axihe.com/charles/charles/proxy-phone.html坑:https://www.cnblogs.com/1-43 ...
- C语言从1打印到100再打印到1该如何编写?我只服最后一种写法!
我觉得这是一个送分题,奈何人才太多了,给出了各种古怪的写法,如果是做项目的话,我比骄建议一些正常的写法,就是大家都能看得懂的,不要搞什么花里胡哨,不过你要是交流的话,既然是交流,我不觉得要多正规,即使 ...
- Convert to Ones CodeForces(超水题)
题目大意:给你几个数,这些数里面只有0或1,你有两种操作:1.把一段区域内的所有数前后交换位置.2.把一段区域内所有数取反.(区域可大可小,可以是所有数也 ...
- spring boot:用redis+lua实现基于ip地址的分布式流量限制(限流/简单计数器算法)(spring boot 2.2.0)
一,限流有哪些环节? 1,为什么要限流? 目的:通过对并发请求进行限速或者一个时间单位内的的请求进行限速,目的是保护系统可正常提供服务,避免被压力太大无法响应服务. 如果达到限制速率则可以采取预定的处 ...
- 第十四章 Linux三剑客之老大—awk
一.awk # 擅长取列 计算 数组 函数 编程语言 内部命令 内部变量 NR #行号 $0 #完整的一行内容 $n # n 是数字 表示取出第几列 多列用逗号分割 -F #FS 分隔符的变量 NF ...
- 教你如何帮助前端同学快速生成API接口代码
最近我们团队开源的后端微服务框架go-zero增长势头比较迅猛,这篇文章我讲讲go-zero对前端团队的作用,并通过一个示例来给大家演示我们是怎么做的,希望能给后端的同学也可以帮助前端同学提高开发效率 ...
- js实现无缝连接轮播图(二)实现自定义属性,根据banner图片的数量动态生成小圆点
<!-- 这个animate.js 必须写到 index.js的上面引入 --><script src="js/animate.js"></scrip ...
- 【手摸手,带你搭建前后端分离商城系统】03 整合Spring Security token 实现方案,完成主业务登录
[手摸手,带你搭建前后端分离商城系统]03 整合Spring Security token 实现方案,完成主业务登录 上节里面,我们已经将基本的前端 VUE + Element UI 整合到了一起.并 ...
- java中true不是关键字?
java中true ,false , null在java中不是关键字,也不是保留字,它们只是显式常量值,但是你在程序中不能使用它们作为标识符. 其中const和goto是java的保留字.java中所 ...