目录
1.冒泡排序
2.选择排序
3.插入排序
4.希尔排序
5.归并排序
6.快速排序
特点:多次遍历列表,比较相邻的元素,将较大值放在正确的位置上。
特别注意!如果列表中有n个元素,那么第一轮遍历要比较n-1对。当遍历完n-1轮后,最小的元素一定在正确的位置上。
#冒泡排序
def bubbleSort(alist):
for n in range(len(alist)-1,0,-1):
for i in range(n):
if alist[i]>alist[i+1]:
alist[i],alist[i+1]=alist[i+1],alist[i]
if __name__=="__main__":
alist=[10,9,8,7,6,5,4,3,2,1]
n=10
bubbleSort(alist)
print("排序后的数组:")
for i in range(n):
print("%d"%alist[i])
特点:每次遍历时只做一次交换,每次遍历时寻找最大值,并在遍历完成后就会放在正确的位置上。
若给n个元素排序,则需遍历n-1轮,这是因为最后一个元素要到n-1轮遍历后才就位。
相较于冒泡排序,两者算法的比较次数相同,所以时间复杂度都是O(n^2),但由于减少了交换次数,因此选择排序算法更快。
#选择排序
def selectionSort(alist):
for n in range(len(alist)-1,0,-1):
max=0
for i in range(1,n+1):
if alist[i]>alist[max]:
max=i
alist[n],alist[max]=alist[max],alist[n]
if __name__=="__main__":
alist=[10,9,8,7,6,5,4,3,2,1]
n=10
selectionSort(alist)
print(alist)
通常情况下,我们认为第一个元素时有序的,从元素1到元素n-1,每一轮都将当前元素与有序子列表中的元素进行比较。将比它大的元素右移;当遇到一个比它小的元素或抵达子列表的终点时,就可插入当前元素。
#插入排序
def insertionSort(alist):
for i in range(1,len(alist)):
key=alist[i]
j=i
while j>0 and alist[j-1]>key: #列表的前一个数大于该key值时,
alist[j]=alist[j-1]
j=j-1
alist[j]=key
if __name__=="__main__":
alist=[10,99,8,77,16,15,48,3,24,1]
insertionSort(alist)
print("排序后的数组:")
print(alist)
特点:1.当数组长度很大时,若最小值在很末端,用插入排序则要逐一比较,遍历整个序列,非常低效。希尔排序就能很好的规避这个问题:直接利用分组的方式,让前端和末端的元素经行比较。2.一开始n的增量很大,每一个子列表的元素很少,所以对每个列表用插入排序进行内部排序是很高效的;而后随着增量n的不断减小,这个数组是越来越有序的,此时使用插入排序也是很有利的。
#希尔排序
def shellSort(alist):
n=len(alist)//2
while n>0:
for startposition in range(n):#起始位置默认从第一个数开始
gapInsertionSort(alist, startposition, n)
n=n//2
def gapInsertionSort(alist,start,gap):
for i in range(start+gap,len(alist),gap):
temp = alist[i]
j = i
while j >= gap and alist[j - gap] > temp:
alist[j] = alist[j - gap]
j -= gap
alist[j] = temp
if __name__=="__main__":
alist=[10,99,8,77,16,15,48,3,24,1]
#alist = [12,34,54,2,3]
n = len(alist)
shellSort(alist)
print("排序后的数组:")
print(alist)
方法:1.将序列中带排序的数字分为若干组,每个数字分成一组;2.将若干组两两合并,保证合并后的组是有序的;3.重复第二步操作直到只剩下一组(当列表为空或只有一个元素,那么它就是有序的)
#归并排序
def mergeSort(alist):
print("Splitting",alist)
#拆分
if len(alist)>1:
mid=len(alist)//2
lefthalf=alist[:mid]
righthalf=alist[mid:]
mergeSort(lefthalf)
mergeSort(righthalf)
# 归并
i=0 # 初始化第一个子数组的索引
j=0 # 初始化第二个子数组的索引
k=0 # 初始归并子数组的索引
while i
方法:1.选定基准值key;2.若待排序数小于基准值,放左边;3.若待排序数大于基准值,放右边;4.对左右分别进行以上操作
#快速排序
def quickSort(alist):
digui(alist,0,len(alist)-1)
def digui(alist,first,last):
if first=pivotvalue and right>=left:
right=right-1
if right
总结:
冒泡排序,选择排序,插入排序时间复杂度都为O(n*n)
希尔排序的时间复杂度介于O(n)和O(n*n)之间
归并排序的时间复杂度为O(n*logn)
快速排序的时间复杂度为O(n*logn),但当分割点不靠近列表中部时会降到O(n*n)
(归并排序和快速排序都要使用额外的存储空间)