排序算法的稳定性
稳定排序算法会让原有相等键值的记录维持相对次序
例如:
(4,1) (3,1) (3,7) (5,6)
排序后
(3,1) (3,7) (4,1) (5,6)-------稳定排序
(3,7) (3,1) (4,1) (5,6)------非稳定排序
冒泡排序
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
算法实现:
def bubble_sort(alist):
n = len(alist)
for i in range(n-1):
count = 0
for j in range(n-1-i):
if alist[j]>alist[j+1]:
alist[j],alist[j+1] = alist[j+1],alist[j]
count += 1
if 0 == count:
return
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
bubble_sort(li)
print(li)
时间复杂度:
最坏时间复杂度:O(n^2)
最优时间复杂度:O(n)
稳定性:
-稳定
选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
def select_sort(alist):
n = len(alist)
for j in range(0, n-2):
min_index = j
for i in range(j+1,n):
if alist[min_index] > alist[i]:
min_index = i
alist[j], alist[min_index] = alist[min_index], alist[j]
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
select_sort(li)
print(li)
时间复杂度:
最坏时间复杂度:O(n^2)
最优时间复杂度:O(n^2)
稳定性
不稳定,举例([5,8,5,2,9])。即使比较的时候换成>=,也是不稳定的,举例([5,8,2,2,9])
插入排序
插入排序(Insertion sort)是一种简单直观且稳定的排序算法。插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。
def insert_sort(alist):
n = len(alist)
for j in range(1,n):
i = j
while i > 0:
if alist[i] < alist[i-1]:
alist[i], alist[i-1] = alist[i-1], alist[i]
i -= 1
else:
break
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
insert_sort(li)
print(li)
时间复杂度:
最坏时间复杂度:O(n^2)
最优时间复杂度:O(n)
稳定性:
稳定
希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
def shell_sort(alist):
n = len(alist)
gap = n // 2
while gap >= 1:
for j in range(gap,n):
i = j
while i > 0:
if alist[i] < alist[i-gap]:
alist[i], alist[i-gap] = alist[i-gap], alist[i]
i -= gap
else:
break
gap //= 2
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
shell_sort(li)
print(li)
时间复杂度:
最坏时间复杂度:O(n^2)
最优时间复杂度:视具体情况的步长而定
稳定性:
不稳定
快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
def quick_sort(alist, head, tail):
if head >= tail:
return
mid_value = alist[head]
low = head
high = tail
while low < high:
while low < high and alist[high] >= mid_value:
high -= 1
alist[low] = alist[high]
while low < high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
alist[low] = mid_value
quick_sort(alist, head, low-1) #不能传入alist[:low-1],这样传入的是一个新列表
quick_sort(alist, high+1, tail)
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
n = len(li)
quick_sort(li, 0, n-1)
print(li)
时间复杂度:
最坏时间复杂度:O(n^2)
最优时间复杂度:O(nlogn)—每次拆分执行n次,拆分logn次
稳定性:
不稳定