1 算法的稳定性
具有相同关键字的记录经过排序后,相对位置保持不变,这样的算法是稳定算法。
2 排序
排序:使一串记录,按照其中的某个或某些关键字的大小递增递减
排序算法:使记录递增递减的方法
不稳定的排序算法:选择排序、快速排序、希尔排序、堆排序
稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序
3 冒泡排序O(n2)
每次把最大的泡泡筛选出来的过程,实现思路:相邻的元素,两两比较,直到循环结束,得到第一个最大值;依次类推,直到得出所有的最大值,完成排序。
外层循环控制排序的总轮数=>len(容器)-1
内层循环主要控制两两元素比较次数
# 冒泡排序
def bubble_sort(num_list):
n=len(num_list)
# 循环n-1次
for i in range(n-1,0,-1):
for j in range(i):
if num_list[j]>num_list[j+1]:
num_list[j],num_list[j+1]=num_list[j+1],num_list[j]
return num_list
if __name__=='__main__':
num_list=[4,1,3,1,5,2]
print(bubble_sort(num_list))
# 冒泡排序优化
def bubble_sort(num_list):
n=len(num_list)
for i in range(n-1,0,-1):
# 添加一个标记,代表是否有元素交换
flag=False
for j in range(i):
if num_list[j]>num_list[j+1]:
num_list[j],num_list[j+1]=num_list[j+1],num_list[j]
flag=True
# 如果flag为False,则表示排序完成,可退出循环
if not flag:
break
return num_list
if __name__=='__main__':
num_list=[4,1,3,1,5,2]
print(bubble_sort(num_list))
4 选择排序(n2)
# 选择排序
def selection_sort(num_list):
n = len(num_list)
for i in range(n - 1):
min_index = i
for j in range(i + 1, n):
if num_list[j] < num_list[min_index]:
min_index = j
if min_index != i:
num_list[i], num_list[min_index] = num_list[min_index], num_list[i]
return num_list
if __name__ == '__main__':
num_list = [4, 1, 3, 1, 5, 2]
print(selection_sort(num_list))
5 插入排序(n2)
排序算法:插入排序【图解+代码】_哔哩哔哩_bilibili
# 插入排序
def insert_sort(num_list):
n=len(num_list)
for i in range(1,n):
# 待插入的数
key=num_list[i]
# 从待插入数的前一个数开始比较
j=i-1
# 循环比较待插入数之前的数字,只要比待插入的数字大
while j>=0 and num_list[j]>key:
# 就向右移动,给待插入的数字让位
num_list[j+1]=num_list[j]
j-=1
# 找到前面没有比待插入的数大为止,把待插入的数放入数列
# 因为上一步j-1,所以待插入的下标为j+1
num_list[j+1]=key
return num_list
num_list = [6, 8, 4, 5, 1, 1, 5, 2, 6]
sorted_list = insert_sort(num_list)
print(sorted_list)
6 希尔排序O(n log n)
[算法]六分钟彻底弄懂希尔排序,简单易懂_哔哩哔哩_bilibili
# 希尔排序
def shell_sort(num_list):
# 初始间隔为列表长度的一半
gap = len(num_list) // 2
# 间隔为0作为循环结束条件
while gap > 0:
# 从gap开始,对每一个元素进行插入排序
for i in range(gap,len(num_list)):
# 待插入值
key=num_list[i]
j=i
# 循环比较待插入数之前的数字,只要比待插入的数字大
while j>=gap and num_list[j-gap]>key:
# 就向右移动,给待插入的数字让位
num_list[j]=num_list[j-gap]
j-=gap
# 找到合适的位置后,插入当前元素
num_list[j]=key
# 减小间隔
gap//=2
return num_list
num_list = [6, 8, 4, 5, 1, 1, 5, 2, 6]
sorted_list = shell_sort(num_list)
print(sorted_list)
7 归并排序O(n log n)
排序算法:归并排序【图解+代码】_哔哩哔哩_bilibili
# 归并排序
def merge_sort(num_list):
# 如果数组长度小于等于1,则直接返回
if len(num_list)<=1:
return num_list
# 找到数组的中间点
mid=len(num_list)//2
# 递归地对左边边进行归并排序
left_half=merge_sort(num_list[:mid])
# 递归地对右半边进行归并排序
right_half=merge_sort(num_list[mid:])
# 合并已排序的左右两部分
return merge(left_half,right_half)
def merge(left,right):
# 初始化结果数组
merged=[]
# 初始化两个指针,分别指向左半部分和右半部分起始位置
left_index=0
right_index=0
# 合并两个数组
while left_index<len(left) and right_index<len(right):
# 比较左半部分和右半部分当前元素
# 如果左半部分的元素小于等于右半部分的元素,添加左半部分的元素到结果组
if left[left_index]<=right[right_index]:
merged.append(left[left_index])
left_index+=1
else:
# 如果右半部分的元素小于等于左半部分的元素,添加右半部分的元素到结果组
merged.append(right[right_index])
right_index+=1
# 将剩余的元素添加到结果数组(如果有)
merged.extend(left[left_index:])
merged.extend(right[right_index:])
return merged
num_list = [6, 8, 4, 5, 1, 1, 5, 2, 6]
sorted_list = merge_sort(num_list)
print(sorted_list)
8 快速排序O(n log n)
不稳定
【快速排序之父】当哲学家决定去当程序员_哔哩哔哩_bilibili
全网最清晰快速排序,看完快排思想和代码全部通透,不通透你打我!_哔哩哔哩_bilibili
# 快速排序
def quick_sort(num_list):
# 如果数组长度小于等于1,直接返回
if len(num_list) <= 1:
return num_list
# 选择一个基准元素,通常选择第一个元素
pivot = num_list[0]
# 划分数组为三个部分:小于基准的部分、等于基准的部分、大于基准的部分
less = [i for i in num_list[1:] if i < pivot]
equal = [i for i in num_list if i == pivot]
greater = [i for i in num_list[1:] if i > pivot]
# 递归地对小于和大于部分进行快速排序,并将结果拼接起来
return quick_sort(less) + equal + quick_sort(greater)
num_list = [6, 8, 4, 5, 1, 1, 5, 2, 6]
sorted_list = quick_sort(num_list)
print(sorted_list)
9 堆排序O(n log n)
堆的特点:①完全二叉树②父节点大于子节点
10 计数排序O(n + k)
11 桶排序O(n + k)
12 基数排序O(n + k)