面试/笔试数据结构之排序算法篇
面试时数据结构应该是面试官们一定会问到的知识块,最常见的就是对于排序、查找等算法的考察。这里先列出一些常见易考,并且比较重要的排序算法。这里都以排成增序为例,如有错误、不好之处敬请指出。
1、 直接插入排序
假设我们有一个序列{a0,a1,a2,a3……an},将a0看成是一个有序序列,a1~an看成是无序序列,插入排序就是将a1和a0比较,如果比a0小则将其插到a0前面,如果比a0大,则不做事情,这样一次之后前两个位置就是有序的,第三个到第n个仍是无序的。然后,再a2和前两个做比较,将其插入到合适的位置,这样之后,前三个元素都是有序的,第四个到第n个是无序的。如此往复,直到序列有序即可。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
2、 希尔排序
假设我们有一个序列{a0,a1,a2,a3……an},希尔排序的基本思想是会将序列分割成若干个子序列,然后再对各个子序列进行插入排序。因此希尔排序会有一个增量d,其初始值一般为序列长度的一半,即d=n/2,这样将一个序列分为两个子序列,再分别对两个子序列做插入排序。之后d取值为n/4,再对子序列做插入排序,如此往复,直到d=1,此时序列基本有序,再对其进行一次插入排序即可。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
上面的代码是最能体现希尔排序思想的,下面给出两种稍加改进的代码。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
3、 冒泡排序
两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
下面也给出冒泡排序的另外两种实现。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
4、 快速排序
假设我们有一个序列{a0,a1,a2,a3……an},在快速排序算法里,我们将第一个元素用作枢轴纪录关键字key,并有一个low指针指向第一个元素,有一个high指针指向最后一个元素,当low < high时,将a[high]和key做比较,如果a[high]>=key,则high–,否则交换low和high位置的元素;当low < high时,将a[low]和key做比较,如果a[low]<=key,则low++,否则交换low和high位置的元素。直到low>=high,一次排序结束,此时key左边的值都比它小,key右边的值都比它大。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
下面的代码是对快排的一种优化。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
5、 简单选择排序
假设我们有一个序列{a0,a1,a2,a3……an},简单选择排序就是将这n个元素遍历一遍选出最小的,再和第一个交换;再从剩下2~n个元素中选出最小的和第二个交换,重复以上步骤即可。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
6、 堆排序
输出堆顶的最小值之后,使剩下n-1个元素的序列重又建成一个堆,则得到n个元素中的次小值。如此反复执行,便能得到一个有序序列。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
下面给出上述各种算法的时间复杂度、空间复杂度、稳定性等。