名称 | 时间复杂度 | 是否原地排序 | 稳定性 |
---|---|---|---|
冒泡排序 | O(n^2) | 是 | 是 |
插入排序 | O(n^2) | 是 | 是 |
选择排序 | O(n^2) | 是 | 否 |
归并排序 | O(nlogn) | 是 | 是 |
快速排序 | O(nlogn) | 是 | 否 |
计数排序 | O(n+k) k是数据范围 | 否 | 是 |
基数排序 | O(dn) d是维度 | 否 | 是 |
冒泡排序
重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
def bubbleSort(array):
a = len(array)
# 如果该数组只有小于或等于一个元素,则直接返回原数组
if a <= 1:
return
for i in range(a - 1):
flag = False # 设置一个标志,作用是防止重复排序
for j in range(a - i - 1):
if array[j] > array[j + 1]: # 比较前一个元素与后一个元素的大小
array[j], array[j + 1] = array[j + 1], array[j] # 交换这两个元素
flag = True
if not flag:
break
return array
插入排序
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
def insertionsort(self, list):
if len(list) <= 1:
return list
for i in range(1, len(list)):
a = list[i]
j = i - 1
for j in range(i-1, -2, -1):
if list[j] > a:
list[j+1] = list[j]
else:
break
list[j+1] = a
return list
选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
def selectionsort(self, list):
if len(list) <= 1:
return list
for i in range(len(list)-1):
min = i
for j in range(i+1, len(list)):
if list[j] < list[min]:
min = j
if i != min:
list[i], list[min] = list[min], list[i]
return list
归并排序
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。
def mergesort(self, list):
if len(list) <= 1:
return list
mid = len(list) // 2
left, right = list[0:mid], list[mid:]
return self.merge(self.mergesort(left), self.mergesort(right))
def merge(self, left, right):
result = []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
while left:
result.append(left.pop(0))
while right:
result.append(right.pop(0))
return result
快速排序
从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
def partion(self, a, left, right):
p = a[right]
i = left
for j in range(left, right):
if a[j] < p:
a[i], a[j] = a[j], a[i]
i += 1
a[right], a[i] = a[i], a[right]
return i
def quickSort(self, a, left, right):
if left >= right:
return
q = self.partion(a, left, right)
self.quickSort(a, left, q-1)
self.quickSort(a, q+1, right)
return a
计数排序
找出待排序的数组中最大和最小的元素
统计数组中每个值为i的元素出现的次数,存入数组C的第i项
对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
def countingSort(self, n, m):
a = [0 for i in range(m)]
for i in n:
a[i] += 1
b = [0 for i in range(m)]
for i in range(len(a)):
b[i] = sum(a[:i+1])
c = [0 for i in range(len(n))]
for i in n:
c[b[i] - 1] = i
b[i] -= 1
return c
基数排序
将整数按位数切割成不同的数字,然后按每个位数分别比较。
将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
def radixSort(self, list, d):
for k in range(d):
s = [[] for i in range(10)]
for i in list:
s[int(i / (10 ** k) % 10)].append(i)
list = [j for i in s for j in i]
return list