冒泡排序
第一种
"""排序思路:列表可乱序,从第一个数开始往后查找,每次查找把左右两个数比较后交换,
一次排序后出现一个最大值还活着最小值在最后或者最前,需要进行n-1趟,但是可以使用标记的方式,当当前这一趟列表"""
def bubble_sort(li):
for i in range(len(li)-1):
flag=False
for j in range(len(li)-1-i): #从已经排好序的找前面的数
if li[j]>li[j+1]: #如果都找不到后面的大于前面的,flag=False
li[j],li[j+1]=li[j+1],li[j]
flag=True
if not flag:
#当进入循环,发生交换,说明还没结束,循环继续,当not flag =True,说明flag=False,说明进入第二层循环后没有交换
break
return li
li=[96,3,4,6984,13,468]
print(bubble_sort(li))
选择排序
第一种
#排序思路:新建列表,每次从旧列表中找到最小值加入新列表,删除旧列表最小的值,反复
def choose_sort_simple(li):
list=[]
for i in range(len(li)):
min_val=min(li)
list.append(min_val) #O(n)
li.remove(min_val) #O(n)
return list
print(choose_sort_simple([96,3,4,6984,13,468]))
缺点:min和remove都是不仅仅是O(n),使用新列表,不是原地排序
第二种
#排序思路:把第一当作最小的,与后面的对比,小于它就交换,循环n-1趟
def choose_sort(li):
"""由于傻瓜式选择排序花费大量时间复杂度,所以此次使用交换方法
默认第一个为最小值,无序区不断变小直至为0,有序区不断变大,直至有序"""
for i in range(len(li)-1):
min_val=i
for j in range(i+1,len(li)):
if li[j]<li[min_val]:
min_val=j
li[i],li[min_val]=li[min_val],li[i]
return li
print(choose_sort([96, 3, 4, 6984, 13, 468]))
插入排序
"""排序思路:1打牌思路,手中本身仅有一张牌,总共的牌位有13位,把第二张牌当作摸到的第一张插入到手中,和手中的牌按顺序依次比较
使用列表来叙述如下:例如一个长度为10的列表,第一张牌作为手中的已知牌,从摸到的第一张牌也是就要排序的第一张牌开始,
依次与前面的作比较,查找插入的位置,如果摸到的牌小于手中的牌,手中的牌往后移既赋值,摸到的牌继续往前寻找插入位置,
循环满足手中牌的下标大于0并且手中的牌最大位置上的值比摸到的大"""
def insert_sort(li):
for i in range(1,len(li)): #i表示摸到的牌的下标
tmp=li[i]
j=i-1 #j表示当前手中的牌的下标
#如果j这张牌比摸到的小,插到右边,第二种j=0这张牌比手里的牌要小
while j>=0 and li[j] >tmp:
li[j+1]=li[j]
j-=1
li[j+1]=tmp
return li
print(insert_sort([3,2,5,84,89,46,1,5]))
!!!注释介绍
快速排序
#排序思路:默认第一为最小,右小默认移左边,左小默认移右边,最后默认放回,不断操作为最快
def quick_sort(li,left,right):
while left<right:
tmp=li[left] #把第一位数当作对比的数
while left<right and li[right]>=tmp: #从右边最后一个数开始,小于对比数放左边
right-=1 #指针往左移
li[left]=li[right] #移动
while left<right and li[left]<=tmp: #同理,左边的往右移动
left+=1
li[right]=li[left]
li[left]=tmp #把中间那个数放回它该放的位置,即左边小于它,右边大于它
return left
def _quick_sort(li,left,right):
if left<right:
mid = quick_sort(li,left,right)
_quick_sort(li,left,mid-1)
_quick_sort(li,mid+1,right)
li=[random.randint(0,100) for _ in range(10)]
_quick_sort(li,0,len(li)-1)
print(li)
全在图里
![在这里插入图片描述](https://img-blog.csdnimg.cn/bc983519fe1c493a874fe27e4041d521.jpeg#pic_center
堆排序
"""
排序思路:堆排序拿大根堆为例,是一个不断建初堆,调整堆的过程
建初堆:大根堆就是将树变成父亲节点永远大于左右孩子节点的堆
调整堆:大根堆把堆顶输出,最后一个元素移到堆顶,从新建堆
"""
def sift(li,low,high):
"""
:param li:
:param low: 堆的根节点位置
:param high: 堆的最后一个元素的位置
:return:
"""
i=low #i是最开始指向的节点位置
j=2*i+1 #先看左孩子
tmp= li[low] # 把堆顶存起来
while j<=high: #只要堆顶下面的左孩子有数,说明一致没结束
if j+1<=high and li[j+1]>li[j]: #右孩子有并且比较大
j=j+1 #j指向右孩子
if li[j]>tmp: #孩子的值比堆顶大
li[i]=li[j] #孩子的值移上去
i=j #i指向刚刚j的位置
j=2*i+1 #j变成了它现在i的左孩子
else: #否则堆顶更大,tmp放在i的位置上
li[i]=tmp #原先的值就较大,直接把tmp放到某一级大于其左右孩子的值上
break
else:
li[i]=tmp #tmp放到叶子节点上
def heap_sort(li):
n=len(li)
for i in range((n-2)//2,-1,-1): #从0到最后一个节点的父节点
#i表示建堆的时候调整堆的下标
sift(li,i,n-1) #n-1表示最后一个元素的下标
#建堆完成
#进入排序阶段
for i in range(n-1,-1,-1):
# i 指向当前堆的最后一个元素
li[0],li[i]=li[i],li[0] #把最后一个元素移到堆顶,堆顶元素存起来
sift(li,0,i-1) #i-1是新的high(新的最后一个元素的位置)
li=[8,2,5,6,1,4]
import random
#random.shuffle(li)
heap_sort(li)
print(li)
归并排序
"""
sort()中使用的就是这种排序,将排序两两分组
例如16个数,先 8 8分,8再分4 4 4再分2 2 ,此时2开始排序,再2 2 合并到4 ,然后4 4 排序,最后归并
"""
def merch_sort(li,low,mid,high):
i=low #合并后排序位置中最左边的
j=mid+1 #合并后,后面列表中的第一个位置
ltmp=[] #新建一个列表,所以空间复杂度与其他排序有所不同 O(n)
while i<=mid and j<=high:
if li[i]<=li[j]: #左边的第一个小于右边的第一个
ltmp.append(li[i])
i+=1
else:
ltmp.append(li[j])
j+=1
#由于总有一边的序列先排序完成,所以要独自对后面的数进行排序
while i<=mid:
ltmp.append(li[i])
i+=1
while j<=high:
ltmp.append(li[j])
j+=1
#最后把列表放会原列表中
li[low:high+1]=ltmp
return li
def mergesort(li,low,high):
if low<high:
mid=(low+high)//2
mergesort(li,low,mid)
mergesort(li,mid+1,high)
merch_sort(li,low,mid,high)
# li=[2,3,5,7,1,4,8,9]
# print(merch_sort(li,0,3,7))
li=[1,6486,46,1651,65,165,15,132148,746,43,135,1,53]
print(mergesort(li,0,len(li)-1))
print(li)