班里统计所有同学的考试排名成绩,50人左右
1.遍历,冒泡排序
第一次挑出成绩最好的,第一次挑出第二号的,依次循环下去。第一次比较49次,第二次比较48次
2.插缝,插入排序
- 拿出一张白纸写上一个人的分数,再拿第二张白纸写上第二人分数,
- 如果第二个大于第一个则放在第一个上面。
- 第三个如果大于第一个小于第二个,放在第一和第二中间,如下图
要提高效率,关键在于减少不必要的比较。
3.归并排序
少做事情的思想
简单版本
- ,把数组一分为二,各自进行冒泡排序,让把两个排好的数组进行合并。
- 合并的时候,由于左边依次从左边第一个,与右边的第一个比较,较小的拿出放到结果列表里。
- 如上面的 2和6 ,取2。
- 继续比较:4和6 ,取4。
- 继续比较:19和6 ,取6。
- 继续比较:19和10 ,取10。
- 继续比较:19和13 ,取13。
- 继续比较:19和20 ,取19。
- 继续比较:40和20 ,取20。
- 继续比较:最后一个40。
这里关键在于:由于左右两边都是排好序,最小的元素肯定是两个数组中其中一个。所以永远按两个元素的首元素比较取出,则永远都能拿到最小值。
升级版本
通过递归的方式,把数组继续拆分到单个不能再拆分。然后再回溯合并。
此过程叫做分治法(Divide and Conquer),也叫二路归并
- 自上而下的递归
- 自下而上的迭代 使用网上的流行图:
依次拆分到最小元素如:(3,44) (38,5),然后开始 (小排序+小排序) 合并成一个新的有序数组
4.快速排序
- 在一堆无序的数字里(最大为100)。挑选一个,比如51,这个51就是叫做
枢值。 - 把所有小于51的分为A组,所有大于等于51放B组。
- 依次继续再A组里面随机选一个值比如30做
枢值(由于A组都是小于51,所有拿到的值一定在0-50之间) - 则A被分解成:C组0-29,D组30到50。
- 同理 B 取出的是 70,则分成:E组51-69,F组70到100。
- 直到不能再细分组为止。
由于每次分组操作对下一次都是有意义的,没有做过多的无用功。
快速排序与归并排序比较
举例高中生找尖子
如果有一个200000的高中生,都在一个高中上课,每次要找到里面的尖子。效率肯定低。
-
归并排序: 把200000分别放到10所学习,每个学校各自找排序,10个学校各自排序,找到最前面尖子,再合并。
-
快速排序:
- 如果我们按几个分数线划分, 小于60,大于等于60 。
- 然后在60- 100之间,再找90-100,60-90。
- 这里其实可以忽略 小于60 和 60-90,因为我们只找,尖子,所以只关心90-100。
延展
- 算法复杂度 一般有: N* N的平方 , 或者 N*logN 。为了让计算机专家专注于量级上的变化。忽略了前面N。只关注于N的平方或logN。
- 根据高德纳的思想,使用微积分中的大写O来表示,所有同等复杂度的算法,在大O的概念下都是相等的。
- 冒泡排序是 O(n的平方),插入排序也是 O(n的平方)。是同一个量级。
- 归并排序和快速排序算法复杂度是logN。