Skip to content

Commit

Permalink
Merge pull request wangzheng0822#76 from Liam0205/notes
Browse files Browse the repository at this point in the history
[notes][11_sorts] done.
  • Loading branch information
wangzheng0822 authored Oct 23, 2018
2 parents b7c6d52 + d9021fa commit 729f0de
Showing 1 changed file with 100 additions and 0 deletions.
100 changes: 100 additions & 0 deletions notes/11_sorts/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 排序(上)

| 排序算法 | 时间复杂度 | 是否基于比较 |
|---------|----|----|
| 冒泡、插入、选择 | $O(n^2)$ | [y] |
| 快排、归并 | $O(n\log n)$ | [y] |
| 桶、基数、计数 | $O(n) | [x] |

开篇问题:插入排序和冒泡排序的时间复杂度相同,都是 $O(n^2)$,在实际软件开发中,为什么我们更倾向于使用插入排序而不是冒泡排序?

## 如何分析「排序算法」?

### 算法执行效率

1. 最好、最坏、平均情况的时间复杂度
2. 时间复杂度的系数、低阶、常数——在渐进复杂度相同的情况下,需要比较系数、低阶和常数
3. 比较和交换(移动)的次数——基于比较的排序算法的两种基本操作

### 算法的内存消耗

是否为原地排序算法(In-place sort algorithm),即算法的空间复杂度是否为 $O(1)$。

### 排序的稳定性

经过排序算法处理后,值相同的元素,在原序列和排序后序列中的相对位置保持不变,则称该排序算法是稳定的。

> 待排序的 `item` 并不是简单的值,而是一个基于对象中的某个 `key` 进行排序时,排序的稳定性就有意义了。
## 冒泡排序

* 每次循环都从序列起始位置开始
* 循环中的每个动作,都对比相邻两个元素的大小是否满足偏序要求,若不满足,则交换顺序

![冒泡排序例图](https://static001.geekbang.org/resource/image/88/34/8890cbf63ea80455ce82490a23361134.jpg)

分析:

* 原地排序
* 稳定排序(偏序关系是严格的偏序关系,如 `<``>`
* 时间复杂度
* 最好 $O(n)$
* 最坏 $O(n^2)$
* 平均 $O(n^2)$

### 冒泡排序的平均时间复杂度非严格分析

* 有序度:序列中满足偏序关系的两两组合的元素对的个数
* 满有序度:排序完成的序列的有序度,它等于 $n(n - 1) / 2$
* 逆序度:序列中不满足偏序关系的亮亮组合的元素对的个数

显然,$\text{逆序度} = \text{满有序度} - \text{有序度}$。

在冒泡排序中,每产生一次「交换」操作,$\text{逆序度}--$。于是,平均情况下,需要 $n(n - 1)/4$ 次交换操作,它已经是 $O(n^2)$ 了。因此,尽管比较操作的数量会大于交换操作的数量,但我们依然能说,冒泡排序的平均时间复杂度是 $O(n^2)$。

> 分析过程不严格,但足够说明问题。
## 插入排序

1. 将待排序数列分为已排序区间和未排序区间
2. 取未排序区间的第一个元素
3. 遍历已排序区间,按照偏序关系,寻找合适的位置,插入未排序区间的第一个元素
4. 重复 2 -- 3 直至未排序区间长度为零

![插入排序例图](https://static001.geekbang.org/resource/image/fd/01/fd6582d5e5927173ee35d7cc74d9c401.jpg)

分析:

* 原地排序
* 稳定排序(值相同的元素,往后插)
* 时间复杂度
* 最好 $O(n)$
* 最坏 $O(n^2)$
* 平均 $O(n^2)$(乘法法则)

## 选择排序

1. 将待排序数列分为已排序区间和未排序区间
2. 遍历未排序区间,取未排序区间的最小元素
3. 交换上述最小元素与未排序区间中的第一个元素的位置
4. 重复 2 -- 3 直至未排序区间长度为零

![选择排序例图](https://static001.geekbang.org/resource/image/32/1d/32371475a0b08f0db9861d102474181d.jpg)

分析:

* 非原地排序
* 非稳定排序
* 时间复杂度
* 最好 $O(n^2)$
* 最坏 $O(n^2)$
* 平均 $O(n^2)$(乘法法则)

## 开篇问题

* 对同一份未排序序列数据,冒泡排序和插入排序所需的交换(移动)次数是一定的,且是相等的
* 单次数据交换,冒泡排序所需的时间更长(三次赋值操作,插排只需要一次)

另有插入排序的优化版本[希尔排序](https://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F)

![小结](https://static001.geekbang.org/resource/image/34/50/348604caaf0a1b1d7fee0512822f0e50.jpg)

0 comments on commit 729f0de

Please sign in to comment.