【小笔记】8种排序算法的Python实现
1、插入排序
def insertSort(self, array_list):
'''
插入排序
1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。
(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
:param array_list:
:return:
'''
for i in range(1, len(array_list)):
for j in range(i, 0, -1):
if array_list[j] < array_list[j - 1]:
array_list[j], array_list[j - 1] = array_list[j - 1], array_list[j]
else:
break
return array_list
2、希尔排序
def shellSort(self, array_list):
'''
希尔排序,缩小增量排序
:param array_list:
:return:
'''
gap = len(array_list) // 2
while gap >= 1:
for i in range(gap, len(array_list)):
j = i
while j - gap >= 0:
if array_list[j] < array_list[j - gap]:
array_list[j], array_list[j - gap] = array_list[j - gap], array_list[j]
j -= gap
else:
break
gap //= 2
return array_list
3、选择排序
def selectSort(self, array_list):
'''
选择排序
1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
2)再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
3)重复第二步,直到所有元素均排序完毕。
:param array_list:
:return:
'''
for i in range(len(array_list)):
tmp_min_index = i
for j in range(i + 1, len(array_list)):
if array_list[j] < array_list[tmp_min_index]:
tmp_min_index = j
array_list[i], array_list[tmp_min_index] = array_list[tmp_min_index], array_list[i]
return array_list
4、冒泡排序
def bubbleSort(self, array_list):
'''
冒泡排序
1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
3)针对所有的元素重复以上的步骤,除了最后一个。
4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
:param array_list:
:return:
'''
length = len(array_list)
while length:
for i in range(1, length):
if array_list[i] < array_list[i - 1]:
array_list[i - 1], array_list[i] = array_list[i], array_list[i - 1]
length -= 1
return array_list
5、归并排序
def mergeSort(self, sorted_list1, sorted_list2):
'''
归并排序
1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4. 重复步骤3直到某一指针达到序列尾
5. 将另一序列剩下的所有元素直接复制到合并序列尾
:param1 sorted_list1:
:param2 sorted_list2:
:return:
'''
merge_list = []
i, j = 0, 0
while True:
if sorted_list1[i] >= sorted_list2[j]:
merge_list.append(sorted_list2[j])
j += 1
else:
merge_list.append(sorted_list1[i])
i += 1
if i == len(sorted_list1) and j < len(sorted_list2):
merge_list.extend(sorted_list2[j:])
break
elif i < len(sorted_list1) and j == len(sorted_list2):
merge_list.extend(sorted_list1[i:])
break
elif i == len(sorted_list1) and j == len(sorted_list2):
break
return merge_list
6、快速排序
def quickSort(self, begin, end):
'''
快速排序
1 从数列中挑出一个元素,称为 “基准”(pivot),
2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。
虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
def __init__(self):
self.array_list = [10,9,8,7,6,5,4,3,2,1,0]
:param array_list:
:return:
'''
if begin < end:
key = self.array_list[begin]
i, j = begin, end
while i < j:
while i < j and self.array_list[j] > key:
j -= 1
while i < j and self.array_list[i] < key:
i += 1
if i < j:
self.array_list[i], self.array_list[j] = self.array_list[j], self.array_list[i]
key = self.array_list[i]
self.quickSort(begin, i - 1)
self.quickSort(i + 1, end)
return self.array_list
7、堆排序
def heapSort(self, L):
'''
堆排序
1)创建一个堆H[0..n-1]
2)把堆首(最大值)和堆尾互换
3)把堆的尺寸缩小1
4)重复步骤2,直到堆的尺寸为1
'''
from collections import deque
def swap_param(L, i, j):
L[i], L[j] = L[j], L[i]
return L
def heap_adjust(L, start, end):
temp = L[start]
i = start
j = 2 * i
while j <= end:
if (j < end) and (L[j] < L[j + 1]):
j += 1
if temp < L[j]:
L[i] = L[j]
i = j
j = 2 * i
else:
break
L[i] = temp
L_length = len(L) - 1
first_sort_count = L_length // 2
for i in range(first_sort_count):
heap_adjust(L, first_sort_count - i, L_length)
for i in range(L_length - 1):
L = swap_param(L, 1, L_length - i)
heap_adjust(L, 1, L_length - i - 1)
return [L[i] for i in range(1, len(L))]
8、基数排序
def radixSort(self, array_list):
'''
基数排序,是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。
由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的在进行排序。
例如要对大小为[1..1000]范围内的n个整数A[1..n]排序
首先,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[1..10]的整数,集合B[2]存储(10..20]的整数,……集合B[i]存储((i-1)*10,i*10]的整数,i=1,2,...100。总共有100个桶。
然后,对A[1..n]从头到尾扫描一遍,把每个A[i]放入对应的桶B[j]中。再对这100个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任何排序法都可以。
依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这样就得到所有数字排好序的结果。
:param array_list:
:return:
'''
i = 0 # 记录当前正在排拿一位,最低位为1
max_num = max(array_list) # 最大值
j = len(str(max_num)) # 记录最大值的位数
while i < j:
bucket_list = [[] for _ in range(10)] # 初始化桶数组
for x in array_list:
bucket_list[int(x / (10 ** i)) % 10].append(x) # 找到位置放入桶数组
array_list.clear()
for x in bucket_list: # 放回原序列
for y in x:
array_list.append(y)
i += 1
return array_list
最后,附上一个排序算法的比较表,以备查看。