写在前面
常见排序算法可以分为两大类:
-
非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。
-
线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。
排序复杂度
类别 | 名称 | 时间复杂度 | 稳定性 |
---|---|---|---|
插入排序 | 插入排序(insertion sort) | O(n2) | 稳定 |
插入排序 | 希尔排序 (shell sort) | O(nlogn) | 不稳定 |
选择排序 | 选择排序(selection sort) | O(n2) | 不稳定 |
选择排序 | 堆排序 (heapsort) | O(nlogn) | 不稳定 |
交换排序 | 冒泡排序(bubble sort) | O(n2) | 稳定 |
交换排序 | 快速排序(quicksort) | O(nlogn) | 不稳定 |
归并排序 | 归并排序 (merge sort) | O(nlogn) | 稳定 |
基数排序 | 基数排序(radix sort) | O(n+k) | 稳定 |
冒泡排序
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
def bubbleSort(nums):
for i in range(len(nums) - 1):
for j in range(len(nums) - i - 1):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
return nums
nums = [2, 1, 34, 4, 6, 3, 6]
result = bubbleSort(nums)
print(result)
[1, 2, 3, 4, 6, 6, 34]
选择排序
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。
def selectSort(nums):
for i in range(len(nums) - 1):
index = i
for j in range(i + 1, len(nums)):
if nums[j] < nums[index]:
index = j
if index != i:
nums[i], nums[index] = nums[index], nums[i]
return nums
nums = [2, 1, 34, 4, 6, 3, 6]
result = selectSort(nums)
print(result)
[1, 2, 3, 4, 6, 6, 34]
插入排序
每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
时间复杂度:O(n^2).
def insertSort1(nums):
for i in range(1, len(nums)):
index = nums[i]
j = i - 1
while j >= 0 and nums[j] > index:
nums[j+1] = nums[j]
j-=1
nums[j+1] = index
return nums
nums = [2, 4, 1 ,0, 4, 3, 2, 5]
result = insertSort1(nums)
print(result)
[0, 1, 2, 2, 3, 4, 4, 5]
下面方法会遍历到nums[-1],如果nums[-1] > index则进行交换,但是循环结束,nums[0]仍会赋值为index
def insertSort(nums):
for i in range(1, len(nums)):
index = nums[i]
for j in range(i, -1, -1):
if index < nums[j - 1]: #该方法会遍历到nums[-1],如果nums[-1] > index则进行交换,但是循环结束,nums[0]仍会赋值为index
nums[j]= nums[j - 1]
else:
break
nums[j] = index
return nums
nums = [2, 4, 1 ,0, 4, 3, 2, 5]
result = insertSort(nums)
print(result)
[0, 1, 2, 2, 3, 4, 4, 5]
快速排序
快速排序原理是首先要找到一个中枢,把小于中枢的值放到他前面,
大于中枢的值放到他的右边,然后再以此方法对这两部分数据分别
进行快速排序。先看一下代码
时间复杂度:O(nlgn)
def quickSort(nums,start,end):
#判断low是否小于high,如果为false,直接返回
if start < end:
i,j = start,end
#设置基准数
base = nums[i]
while i < j:
#如果列表后边的数,比基准数大或相等,则前移一位直到有比基准数小的数出现
while (i < j) and (nums[j] >= base):
j = j - 1
#如找到,则把第j个元素赋值给第个元素i,此时表中i,j个元素相等
nums[i] = nums[j]
#同样的方式比较前半区
while (i < j) and (nums[i] <= base):
i = i + 1
nums[j] = nums[i]
#做完第一轮比较之后,列表被分成了两个半区,并且i=j,需要将这个数设置回base
nums[i] = base
#递归前后半区
quickSort(nums, start, i - 1)
quickSort(nums, j + 1, end)
return nums
nums = [49,38,65,97,76,13,27,49]
print("Quick Sort: ")
quickSort(nums,0,len(nums)-1)
print(nums)