python实现各种排序
1. 快速排序
1:首先取序列第一个元素为基准元素pivot=R[low]。i=low,j=high。
2:从后向前扫描,找小于等于pivot的数,如果找到,R[i]与R[j]交换,i++。
3:从前往后扫描,找大于pivot的数,如果找到,R[i]与R[j]交换,j--。
4:重复2~3,直到i=j,返回该位置mid=i,该位置正好为pivot元素。 完成一趟排序后,以mid为界,将序列分为两部分,左序列都比pivot小,有序列都比pivot大,然后再分别对这两个子序列进行快速排序。
以序列(30,24,5,58,16,36,12,42,39)为例,进行演示:
1、初始化,i=low,j=high,pivot=R[low]=30:
i | j | |||||||
---|---|---|---|---|---|---|---|---|
30 | 24 | 5 | 58 | 16 | 26 | 12 | 41 | 39 |
2、从后往前找小于等于pivot的数,找到R[j]=12
i | j | |||||||
---|---|---|---|---|---|---|---|---|
30 | 24 | 5 | 58 | 16 | 26 | 12 | 41 | 39 |
- R[i]与R[j]交换,i++
i | j | |||||||
---|---|---|---|---|---|---|---|---|
12 | 24 | 5 | 58 | 16 | 26 | 30 | 41 | 39 |
3、从前往后找大于pivot的数,找到R[i]=58
i | j | |||||||
---|---|---|---|---|---|---|---|---|
12 | 24 | 5 | 58 | 16 | 26 | 30 | 41 | 39 |
- R[i]与R[j]交换,j--
i | j | |||||||
---|---|---|---|---|---|---|---|---|
12 | 24 | 5 | 30 | 16 | 26 | 58 | 41 | 39 |
4、从后往前找小于等于pivot的数,找到R[j]=16
i | j | |||||||
---|---|---|---|---|---|---|---|---|
12 | 24 | 5 | 30 | 16 | 26 | 58 | 41 | 39 |
- R[i]与R[j]交换,i++
i,j | ||||||||
---|---|---|---|---|---|---|---|---|
12 | 24 | 5 | 16 | 30 | 26 | 58 | 41 | 39 |
5、从前往后找大于pivot的数,这时i=j,第一轮排序结束,返回i的位置,mid=i
Low | mid-1 | mid | mid+1 | High | ||||
---|---|---|---|---|---|---|---|---|
12 | 24 | 5 | 16 | 30 | 26 | 58 | 41 | 3 |
此时已mid为界,将原序列一分为二,左子序列为(12,24,5,18)元素都比pivot小,右子序列为(36,58,42,39)元素都比pivot大。然后在分别对两个子序列进行快速排序,最后即可得到排序后的结果。
def quicksort(low,high,li):
if low >= high:
return li
i = low
j= high
pivot = li[low]
while i<j:
while i<j and li[j]>pivot:
j -= 1
li[i] = li[j]
while i<j and li[i]<pivot:
i += 1
li[j] = li[i]
li[j] = pivot
quicksort(low,i-1,li)
quicksort(i+1,high,li)
return li
lists=[30,24,5,58,18,36,12,42,39]
print("排序前的序列为:")
for i in lists:
print(i,end =" ")
print("\n排序后的序列为:")
for i in quicksort(0,len(lists)-1,lists):
print(i,end=" ")
2. 冒泡排序
冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
冒泡排序算法的运作如下:
- 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
def bubblesort(li):
for i in range(len(li)-1,0,-1):
for j in range(1,i):
if li[j-1]>li[j]:
li[j-1],li[j] = li[j],li[j-1]
return li
li = [54,26,93,17,77,31,44,55,20]
print(bubblesort(li))
3. 插入排序
插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
- 从第一个元素开始,该元素可以认为已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
这个算法和冒泡排序有点类似,都是两层for循环,一个是从正面挨个比,一个是倒着比
def insertsort(li):
for i in range(1,len(li)):
for j in range(i,0,-1):
if li[j-1]>li[j]:
li[j-1],li[j] = li[j],li[j-1]
return li
li = [54,26,93,17,77,31,44,55,20]
print(insertsort(li))
4. 希尔排序
希尔排序是先取一个小于待排序列表长度的正整数d1,把所有距离为d1的数据看成一组,在组内进行插入排序。然后取一个小于d1的正整数d2,继续用d2分组和进行组内插入排序。每次取的分组距离越来越小,组内的数据越来越多,直到di=1,所有数据被分成一组,再进行插入排序,则列表排序完成。
希尔排序是基于插入排序进行优化的排序算法。在插入排序中,如果数据几乎已经排好序时,效率是很高的(想一下抓牌和插牌),时间复杂度为 O(n) 。但数据的初始状态并不一定是“几乎已经排好序”的,用插入排序每步只能将待插入数据往前移动一位,而希尔排序将数据分组后,每次可以往前移动di位,在di>1时进行的分组和组内排序可以将数据变成“几乎排好序”的状态,此时再进行最后一次插入排序,提高效率。
希尔排序的原理如下:
-
选择小于待排序列表长度 n 的正整数序列 d1,d2,...,di,其中 n>d1, d(i-1)>di, di=1 ,作为数据的间隔距离对列表进行分组。这里对 di 的取值和个数没有要求,只要是整数,d1<n,依次变小即可。
-
依次用 d1, ..., di 作为数据的距离对列表进行分组和组内插入排序,一共需要进行 i 轮排序。
-
在最后一轮排序前,列表中的数据达到了“几乎排好序”的状态,此时进行最后一轮插入排序。
以列表 [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21] 进