搜索与排序—— 冒泡排序选择排序插入排序与希尔排序
Posted 鲸骑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搜索与排序—— 冒泡排序选择排序插入排序与希尔排序相关的知识,希望对你有一定的参考价值。
搜索与排序(三)—— 冒泡排序、选择排序、插入排序与希尔排序
本节开始,我们开始学习排序。排序可以对使某些算法从中受益,如之前讲过的二分法,就是建立在排好序的集合上的。
本节所演示的排序均为从小到大排序。
冒泡排序
冒泡排序可以说是排序中的经典了,虽然通常是被认为最低效的排序方法。。。但是还是得掌握一下。之所以称之为冒泡法,因为其原理是从第一项开始,将该项与剩下的项相比,小(大)则交换位置,这样逐个遍历集合中的项,每一轮遍历最小(大)的项将会被交换到顶部,犹如冒泡一般。
代码
1def bubbleSort(alist):
2 for i in range(len(alist)-1):
3 for j in range(i+1,len(alist)):
4 if alist[j]<alist[i]:
5 alist[i], alist[j] = alist[j], alist[i]
复杂度
O(n^2)
选择排序
选择排序改进了冒泡排序,每轮遍历找出最大值所在位序,结束该轮循环后再进行一次交换。
代码
1def selectionSort(alist):
2 for i in range(len(alist)-1,0,-1):
3 positionOfMax = i
4 for j in range(0, i):
5 if alist[j] > alist[positionOfMax]:
6 positionOfMax = j
7 alist[positionOfMax], alist[i] = alist[i], alist[positionOfMax]
复杂度
选择排序与冒泡排序有着数量相同的比较次数,复杂度也为O(n^2)。不过由于交换次数的减少,选择排序在实际中效率更高。
插入排序
插入排序始终在集合较低位置维持一个排序的子集合,然后再将每个新项“插回”原来的子列表。
在对某项进行操作之前,其前面的项已经为排好序的子列表(我们从集合的第二项开始,这样第一个元素即为单个元素的子列表),我们只需要将该项A与前子列表从后往前各个项B逐项比较,小则将B往后移一位。这样每轮比较后,将该插入原子列表中的“空位”。
代码
1def insertSort(alist):
2 for index in range(1, len(alist)):
3 currentvalue = alist[index]
4 position = index
5
6 while position > 0 and alist[position-1] > currentvalue:
7 alist[position] = alist[position-1]
8 position -= 1
9
10 alist[position] = currentvalue
复杂度
插入排序的最大比较次数是 n-1 个整数的总和。同样,是 O(n^2 )。然而,在最好的情况下,
每次通过只需要进行一次比较。这是已经排序的列表的情况。
关于移位和交换的一个注意事项也很重要。通常,移位操作只需要交换大约三分之一的处理
工作,因为仅执行一次分配。在基准研究中,插入排序有非常好的性能。
希尔排序
希尔排序通过将原始列表分解为多个较小的子列表来进行插入排序。选择这些子列表的方式是希尔排序的关键。
希尔排序分解子列表并不为连续的,而是采用增量(gap)等距构造子列表。
本节采用的增量为,第一轮为n/2,第二轮为n/4…直至增量变为1.
代码
1def shellSort(alist):
2 sublistcount = len(alist) // 2
3 while sublistcount > 0:
4 for startposition in range(sublistcount):
5 gapInsertionSort(alist, startposition, sublistcount)
6
7 sublistcount = sublistcount // 2
8
9def gapInsertionSort(alist, start, gap):
10 for index in range(start+gap, len(alist), gap):
11
12 currentvalue = alist[index]
13 position = index
14
15 while position >= gap and alist[position-gap] > currentvalue:
16 alist[position] = alist[position-gap]
17 position -= gap
18
19 alist[position] = currentvalue
复杂度
看起来似乎希尔排序不会比插入排序更好,因为其最后一轮都对整个集合执行了完整的插入排序,再加上前几轮的插入排序, 执行的操作似乎更多。但实际上,每一轮遍历都会产生比前一个“更有序”的列表,这使得下一轮的遍历非常高效。
对希尔排序的分析远远超出了本文的范围,我们可以说,它倾向于落在 O(n)和O(n^2 ) 之间的某处。
end
以上是关于搜索与排序—— 冒泡排序选择排序插入排序与希尔排序的主要内容,如果未能解决你的问题,请参考以下文章
八大基础排序中(直接插入排序,希尔排序,冒泡排序, 快速排序,归并排序,简单选择排序)
数据结构与算法 4:排序算法,选择/插入/冒泡/希尔/快速/归并