Python排序算法
下面所有的排序方法都会使用swap函数,来交换两个列表中的位置,代码如下所示:
def swap(lyst,i,j):
temp = lyst[i]
lyst[i]=lyst[j]
lyst[j]=temp
1.选择排序:
原理(整数列表从小到大排序):先搜索整个列表,找到最小项的位置下标,如果不是第一项,就把第一项跟最小项位置对调,之后再搜索第二项到最后一项,重复操作。
大致流程:
未排序的列表 | 第一轮之后 | 第二轮之后 | 第三轮之后 | 第四轮之后 |
---|---|---|---|---|
5 | 1* | 1 | 1 | 1 |
3 | 3 | 2* | 2 | 2 |
1 | 5* | 5 | 3* | 3 |
2 | 2 | 3* | 5* | 4* |
4 | 4 | 4 | 4 | 5* |
def selectionSort(lyst):
i=0
while i < len(lyst) -1:#做n-1次搜索
minIndex = i#先以搜索范围内最前面的项为最小项
j = i + 1
while j < len(lyst):#开始搜索
if lyst[j] < lyst[minIndex]:
minIndex = j
j += 1
if minIndex != i:#如果最前面的项和最小项不是同一项,交换这两项
swap(lyst,minIndex,i)
i += 1
这个过程中,对于大小为n的列表,最外侧循环执行n-1次,内侧循环第一次执行n-1次,第二次n-2次。。。最后一次n次,因此一共要执行(n-1)+(n-2)+…+1=n(n-1)/2次,时间复杂度为O(n^2)
2.冒泡排序:
策略:从列表开头处开始,并且比较一对数据项,直到移动到列表末尾,每当成对的两项之间的顺序不正确时,算法就交换其位置,这个过程的效果就是将最大项以冒泡的方式排到列表的末尾。然后,算法从列表第二项开始再重复这个过程,直到从列表最后一项开始执行。
未排序的列表 | 第1轮之后 | 第2轮之后 | 第3轮之后 | 第4轮之后 |
---|---|---|---|---|
5 | 4* | 4 | 4 | 4 |
4 | 5* | 2* | 2 | 2 |
2 | 2 | 5* | 1* | 1 |
1 | 1 | 1 | 5* | 3* |
3 | 3 | 3 | 3 | 5* |
python代码实现如下:
def bubbleSort(lyst):
n=len(lyst)
while n > 1:#执行完,需要n-1次冒泡
i = 1#开始冒泡排序
while i < n:
if lyst[i] < lyst[i-1]:#如果前项大于后项,那么这两项交换
swap(lyst,i,i-1)
i += 1
n -= 1
外侧必执行n-1次,内侧也是从n-1次执行到1次,所以时间复杂度和选择排序是一样的,都是O(n^2)
这个算法有一种改进,通过在提前设置一个bool类型的标志,如果发生了调用swap函数,那么bool改变值,但如果没有,函数直接退出,这样的话,在最好的情况下,只需要把数据遍历一遍就可以了,但平均和最坏情况还是O(n^2),代码如下:
def bubbleSort(lyst):
n=len(lyst)
while n > 1:
swapped = False
i = 1
while i < n:
if lyst[i] < lyst[i-1]:
swap(lyst,i,i-1)
swapped = True
i += 1
if not swapped:return
n -= 1
3.插入排序:
插入排序的工作方式像许多人排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌.
插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序.
这么理解可能有些抽象,我们直接用图标展示:
未排序的列表 | 第1轮之后 | 第2轮之后 | 第3轮之后 | 第4轮之后 |
---|---|---|---|---|
2 | 2 | 1* | 1 | 1 |
5← | 5(没有插入) | 2 | 2 | 2 |
1 | 1← | 5 | 4* | 3* |
4 | 4 | 4← | 5 | 4 |
3 | 3 | 3 | 3← | 5 |
代码实现:
def insertionSort(lyst):#可以想象成玩斗地主的时候,给手里的牌整理的过程
i = 1
while i < len(lyst):
itemToInsert = lyst[i]#这里其实相当于把扑克牌拿出来
j=i-1
while j >= 0:#拿出来的扑克牌跟在它前面所有的扑克牌相比较,如果有一个比拿出来的扑克牌大,拿出来的扑克牌就插入到那个比它大的扑克牌前面的位置
if itemToInsert < lyst[j]:
lyst[j+1] = lyst[j]
j -= 1
else:break
lyst[j+1] = itemToinsert
i += 1
假设所有都是未排序的(比方54321)那么它每一次还是要向选择排序一样每一项都要遍历,复杂度为O(n^2),但如果有排好序的,复杂度就会降低,排好序的项越多,复杂度越低,当全部都是排好序的时候,复杂度是O(n)
4.快速排序
主要思想是分而治之,把一个列表分成不同的小份,运用递归解决(具体比较抽象,建议看视频)
def quicksort(array)
if len(array)<2:
return array
else:
baseValue=array(0)
less=[m for m in array[1:] if m < baseValue]
eqal=[w for w in array if w==baseValue]
greater=[n for n in array[1:] if n >baseValue]
return quickSort(less)+equal+quickSort(greater)
5.归并排序
# 记录归并排序
def MergeSort(lists):
if len(lists) <= 1:
return lists
middle = len(lists)//2
left = MergeSort(lists[:middle])
right = MergeSort(lists[middle:])
return merge(left, right)
def merge(a, b):
c = []
h = j = 0
while j < len(a) and h < len(b):
if a[j] < b[h]:
c.append(a[j])
j += 1
else:
c.append(b[h])
h += 1
if j == len(a):
for i in b[h:]:
c.append(i)
else:
for i in a[j:]:
c.append(i)
return c