简单排序
- 统一接口
- 默认从小到大排序
- 内部排序:内存足够存储所有数据,在内存中对数据进行排序操作
- 稳定性:如果排序前两个相等的数据是挨在一起的,必须对两个都叫小明的人排序,起初小明1在小明2左边,那么排完后还是得在他左边,不能变成右边。
冒泡排序
- 加了一个flag来标记数据是否已有序,如果一趟排序中全程没有进行交换,那么flag为0,说明数据已有序,可以结束了。
- 缺点:耗时
- 优点:简单,适用于单向链表的排序
- 算法实例:第九讲->9.1第2节
插入排序
- 稳定性:元素不比当前元素大的时候不用往后移,所以是稳定的。
- 比冒泡法好,因为冒泡需要交换,交换需要3步,而这里往后移只需比它大的元素往后移,都移完了再把当前元素插入就行了。
- 算法实例:第九讲->9.1第3节
- 用冒泡和插入分别对这串数据排序的话,交换次数都是9次,而这里面逆序对的个数也是9次。因为美交换一次消去一个逆序对,因此有几个逆序对就需交换几次。
- I是原始序列中逆序对的个数。插入排序不仅跟数据个数有关,还跟逆序对个数有关。
快速排序
分而治之
- 算法实例:第十讲->10.1第1小节
选主元
- 如果数据已经排好序,但是主元都是选第一个的话,那就相当于没有排序。
- 随机取的话,随机函数是很费时的。
- 我们可以取第一个元素、中间一个元素和最后一个元素中第二大的。
- 利用算法把这三个元素从小到大排序,然后等一下就返回那个第二大的。不过等一下是要等什么呢?我们先把中间这个第二大的元素换到最后一个元素的前一个元素(等一下就返回倒数第二个元素),因为我们知道第一个元素一定比等下作为枢纽的元素小,最后一个元素一定比它大,如果规定相等就放在后面的话,那么第二大元素本身就是枢纽,我们知道肯定是要放在后面的,所以我们提前把它放在后面,那等一下只比较第二个到倒数第三个元素与枢纽的大小关系就好了,而中间那个元素就换成了原来倒数第二的元素。否则中间那个元素本身就是枢纽,是已经知道大小关系的,却还要再比一次,就有点浪费时间了。
小规模数据的处理
- 分而治之将数据分得很小的时候调用简单排序,不要一直递归下去。
算法实现
- 要在外面套一个壳,否则不符合接口规范。
- 算法实例:第十讲->10.1所有小节
表排序
- 一种间接排序
- 不需要动元素本身,只是动元素的指针。也就是用它们的下标代替元素本身来排序,下标排在哪个位置,元素就在哪个位置。
物理排序
- 就是排完下标后怎么排元素
- 我们有结论:N个数字的排列由若干个独立的环组成;比如,表的第一个元素是3,第三个元素是1,…,这样下去一定会回到3的,也就是形成了一个环。
- 那这样我们可能会陷入环的死循环里,所以我们要判断什么时候环结束了。可以把访问过的table的元素设置为和A下标一样,这样在访问前判断一下元素和下标是否一样就知道环是否结束了。
复杂度分析
- 算法实例:第十讲->10.2第1、3小节
桶排序
- 给每个程序都设置个桶
- 但是如果桶很多但是人很少怎么办呢?
- 算法实例:第十讲->10.3第1小节
基数排序
- 分桶跟进制有关系,这里是10进制就分10个桶
- 如果桶的个数非常小的话,那么复杂度接近线性复杂度。
- 算法实例:第十讲->10.3第2小节
在多关键字排序上的应用
- 算法实例:第十讲->10.3第3小节