一.冒泡排序
思路(稳定):
算法时间复杂度:O(n²)
算法空间复杂度:O(1)
第一轮:从第一个数和第二个数开始,将较大的那个放在后面,再到第二个和第三个数,一直到最后一个数。就会把最大的数放在数列的最后。第二轮:从第一个数和第二个数开始,将较大的那个放在后面,再到第二个和第三个数,一直到倒数第个数。就会把第二大的数放在数列的倒数第二位。一直到每个数都排列好。
def maopao_sort(list):
if not list or len(list) <= 1:
return
list_len = len(list)
for i in range(list_len - 1):
swap_flag = True
for j in range(0, list_len - 1 - i):
if list[j] > list[j + 1]:
tmp = list[j]
list[j] = list[j + 1]
list[j + 1] = tmp
swap_flag = False
if swap_flag:
return list
二.选择排序
思路(不稳定(当列表有重复数会出错)):
稳定(是相对位置稳定,比如552,用选择排序最终结果是第一个5和2位置交换,两个5的相对位置发生改变,所以不稳定)
算法复杂度:O(n²)
算法空间复杂度:O(1)
第一轮:从第一个开始遍历一遍列表,然后和最小的交换位置。第二轮:从第二个数开始遍历列表,然后和最下的交换位置。一直到最后剩下最大的那个。
def xuanze_sort(list):
if not list or len(list) <= 1:
return
list_len = len(list)
for i in range(list_len - 1):
j_tmp = i
min = list[i]
for j in range(i + 1, list_len):
if list[j] < min:
j_tmp = j
min = list[j]
if i != j_tmp:
tmp = list[i]
list[i] = list[j_tmp]
list[j_tmp] = tmp
return list
三.插入排序
算法复杂度:O(n²)
算法空间复杂度:O(1)
算法稳定性:稳定
思想:
第n轮将list的第n+1个数与第n个,第n-1、、、第一个数进行比较,只要小于比较的数就换位置。
def charu_sort(list):
if not list or len(list) <= 1:
return
list_len = len(list)
for i in range(1, list_len):
for j in range(0, i + 1):
if list[i] < list[j]:
break
if j <= i:
tmp_i = i
x = list[i]
while tmp_i > j:
list[tmp_i] = list[tmp_i - 1]
list[tmp_i - 1] = x
tmp_i -= 1
list[j] = x
return list
四.快速排序
算法复杂度:O(nlgn)
算法空间复杂度:O(1)
算法稳定性:不稳定(很多交换的)
思想:
将list的第一个数作为比较的点,将数列分为左右两部分,左边小于等于比较点,右边大于等于比较点。再将左右两个list分别重复这样的操作,直到分不下去。
def kuaisu_sort(list, start=0, end=0):
if not list or len(list) <= 1 or start > end:
return
if start == 0 and end == 0:
end = len(list) - 1
start_tmp = start
end_tmp = end
x = list[start_tmp]
while start_tmp < end_tmp:
while start_tmp < end_tmp and list[end_tmp] >= x:
end_tmp -= 1
if start_tmp < end_tmp:
list[start_tmp] = list[end_tmp]
start_tmp += 1
while start_tmp < end_tmp and list[start_tmp] <= x:
start_tmp += 1
if start_tmp < end_tmp:
list[end_tmp] = list[start_tmp]
end_tmp -= 1
list[start_tmp] = x
kuaisu_sort(list, start, start_tmp - 1)
kuaisu_sort(list, start_tmp + 1, end)
return list
五.归并排序
算法复杂度:O(nlgn)
算法空间复杂度:O(n)
算法稳定性:稳定
思想:
将list均分成左右两个list,再对每个list均分。分到最小以后对所有小list中的两个数排序,再做list间的排序,先比两个list的第一个数,小的放第一位,再比剩下的那个第一个数,和另一个list的第二个。一直这样排序,直到排序完成。最后将左右两个list进行排序就可以了
代码`
def merge(a, b):
c = []
h = j = 0
while j < len(a) and h < len(b):
if a[j] < b[h]:
c.append(a[j])
j += 1
else:
c.append(b[h])
h += 1
if j == len(a):
for i in b[h:]:
c.append(i)
else:
for i in a[j:]:
c.append(i)
return c
def guibin_sort(lists):
if len(lists) <= 1:
return lists
middle = len(lists)//2
left = guibin_sort(lists[:middle])
right = guibin_sort(lists[middle:])
return merge(left, right)
六.堆排序
七.计数排序
算法时间复杂度:O(n+m)
算法空间复杂度:O(m)
算法稳定性:稳定
思想:
计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有17个元素的值小于x的值,则x可以直接存放在输出序列的第18个位置上。
代码:
def jishu_sort(input_list):
length = len(input_list)
if length < 2:
return input_list
max_num = max(input_list)
count = [0] * (max_num + 1)
for element in input_list:
count[element] += 1
output_list = []
for i in range(max_num + 1):
for j in range(count[i]): # count[i]表示元素i出现的次数,如果有多次,通过循环重复追加
output_list.append(i)
return output_list