常见排序整合(python版)
1.冒泡排序
#bubble sort
#时间复杂度为o(n^2)
#升序和降序只需要改动其中的一个箭头方向即可
def bubble_sort(li):
count=1
for i in range(len(li)-2):
exchange=False
for j in range (len(li)-i-1):
if li[j]>li[j+1]:
li[j],li[j+1]=li[j+1],li[j]
exchange=True
print(f"排序第{count}趟的列表为{li}")
count=count+1
if not exchange:
return
import random
list1=[random.randint(0,100) for i in range(10)]
print(f"初始列表为{list1}")
bubble_sort(list1)
print(f"排序之后的结果为{list1}")
2.选择排序
#select sort
def select_sort_simple(li):#简单版
li_new=[]
for i in range(len(li)):
min_val=min(li)
li_new.append(min_val)
li.remove(min_val)
return li_new
def select_sort(li):
for i in range(len(li)-1):
min_loc=i
for j in range (i+1,len(li)):
if li[j]<li[min_loc]:
min_loc=j
li[i],li[min_loc]=li[min_loc],li[i]
print(f"第{i+1}次:{li}")
list1=[1,2,1,6,7,99,34,66,11]
select_sort_simple(list1)
print(list1)
3.插入排序
#insert sort
#时间复杂度o(n^2)
import random
def insert_sort(li):
for i in range(1,len(li)):# i表示摸到牌的下标
tmp=li[i]
j=i-1 #j是手里牌的下标
while li[j]>tmp and j>=0:
li[j+1]=li[j]
j-=1
li[j+1]=tmp
li=list(range(10000))
random.shuffle(li)
print(li)
insert_sort(li)
print(li)
4.快速排序
#quick sort
#快速排序的时间复杂度o(logn*n)
def partition(li,left,right):
tmp=li[left]
while left<right:
while left<right and li[right]>=tmp:#从右边找比tmp小的数
right -=1 #往左走一步
li[left]=li[right] #把左边数写到右边空位上
#print(li,'right')
while left<right and li[left]<=tmp:
left +=1
li[right]=li[left] #把左边的值写道右边空位上
#print(li,'left')
li[left]=tmp #把tmp归位
return left
def quick_sort(li,left,right):
if left<right: #至少两个元素
mid=partition(li,left,right)
quick_sort(li,left,mid-1)
quick_sort(li,mid+1,right)
li=[5,3,6,4,7,1,9,2,8]
print(li)
quick_sort(li,0,len(li)-1)
print(li)
5.归并排序
def merge(li,low,high,mid):
i=low
j=mid+1
ltmp=[]
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执行完,肯定有一部分没数了
while i<=mid:
ltmp.append(li[i])
i+=1
while j<=high:
ltmp.append(li[j])
j+=1
li[low:high+1]=ltmp
import random
li=list(range(1000))
random.shuffle(li)
print(li)
def merge_sort(li,low,high):
if low<high:#至少两个元素,递归
mid=(low+high)//2
merge_sort(li,low,mid)
merge_sort(li,mid+1,high)
merge(li,low,high,mid)
merge_sort(li,0,len(li)-1)
print(li)
#时间复杂度o(nlogn)
#空间复杂度o(n)
6.堆排序
#堆排序前传——二叉树
#父节点与左孩子节点的编号下标有什么关系 ?
#i->2i+1
#父节点和右孩子节点的编号下标有什么关系?
#i->2i+2
#heap sort 时间复杂度o(nlog(n))
def sift(li,low,high):
"""
:param li: 列表
:param low: 堆的根节点位置
:param high: 堆的最后一个元素的位置
:return:
"""
i=low
j=2*i+1 #j开始是左孩子
tmp=li[low] #将堆顶存起来
while j<=high:#只要j位置有数
if j+1<=high and li[j+1]>li[j]:#右孩子有且比较大
j=j+1 #j指向右孩子
if li[j]>tmp:
li[i]=li[j]
i=j
j=2*i+1
else: #tmp更大,把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):
# i 表示建堆的时候调整的部分的根的下标
sift(li,i,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=[i for i in range(100)]
import random
random.shuffle(li)
print(li)
heap_sort(li)
print(li)
7.堆排序内置模块
#堆排序的内置模块
import heapq #q->queue 优先队列
import random
li=list(range(100))
random.shuffle(li)
print(li)
heapq.heapify(li)#建堆
n=len(li)
for i in range(n):
print(heapq.heappop(li),end=',')
8.堆排序—topk问题
#现在有n个数,设计算法得到前k大的数
#解决思路:1.排序后切片 时间复杂度o(nlogn)2.排序lowb三人组 o(kn)3.堆排序 (nlogk)
def sift(li,low,high):
"""
:param li: 列表
:param low: 堆的根节点位置
:param high: 堆的最后一个元素的位置
:return:
"""
i=low
j=2*i+1 #j开始是左孩子
tmp=li[low] #将堆顶存起来
while j<=high:#只要j位置有数
if j+1<=high and li[j+1]<li[j]:#右孩子有且比较大
j=j+1 #j指向右孩子
if li[j]<tmp:
li[i]=li[j]
i=j
j=2*i+1
else: #tmp更大,把tmp放到i的位置上
li[i]=tmp #把tmp放到某一级领导位置
break
else:
li[i]=tmp #把tmp放在叶子结点上
def topk(li,k):
heap=li[0:k]
for i in range((k-2)//2,-1,-1):
sift(heap,i,k-1)
#1.建堆
for i in range(k,len(li)-1):
if li[i]>heap[0]:
heap[0]=li[i]
sift(heap,0,k-1)
#2.遍历
for i in range(k-1,-1,-1):
#i 指向当前堆的最后一个元素
heap[0],heap[i]=heap[i],heap[0]
sift(heap,0,i-1)#i-1是新的high
#3.出数
return heap
def heap_sort(li):
n=len(li)
for i in range((n-2)//2,-1,-1):
# i 表示建堆的时候调整的部分的根的下标
sift(li,i,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
import random
li=list(range(1000))
random.shuffle(li)
print(topk(li,10))
9.希尔排序
#时间复杂度情况复杂
import random
def insert_sort(li,gap):
for i in range(gap,len(li)):# i表示摸到牌的下标
tmp=li[i]
j=i-gap #j是手里牌的下标
while li[j]>tmp and j>=0:
li[j+gap]=li[j]
j-=gap
li[j+gap]=tmp
def shell_sort(li):
d=len(li)//2
while d>=1:
insert_sort(li,d)
d//=2
li=list(range(10000))
random.shuffle(li)
print(li)
shell_sort(li)
print(li)
10.计数排序
#时间复杂度o(n)
def count_sort(li,max_count):
count =[0 for _ in range(max_count+1)]
for val in li:
count[val]+=1
li.clear()
for ind,val in enumerate(count):
for i in range(val):
li.append(ind)
import random
li=[random.randint(0,100) for _ in range(1000)]
print(li)
count_sort(li,max(li))
print(li)
11.桶排序
#时间复杂度o(nk)
def bucket_sort(li,n=100,maxnum=100):
buckets=[[]for _ in range(n)]#创建桶
for var in li:
i=min(var//(maxnum//n),n-1)#i 表示var在几号桶里
buckets[i].append(var)#把var加到桶里
#保持桶里的顺序
for j in range(len(buckets[i])-1,0,-1):
if buckets[i][j]<buckets[i][j-1]:
buckets[i][j],buckets[i][j-1]=buckets[i][j-1],buckets[i][j]
else:
break
sorted_li=[]
for buc in buckets:
sorted_li.extend(buc)
return sorted_li
import random
li=[random.randint(0,10000) for i in range(10000)]
li=bucket_sort(li)
print(li)
12.基数排序
#基数排序
#时间复杂度o(kn)
def radix_sort(li):
max_num=max(li)#最大数99->2,888->3,10000->5
it=0
while 10**it<=max_num:
buckets=[[]for _ in range(10)]
for var in li:
digit=(var//10**it)%10
buckets[digit].append(var)
#分桶完毕
li.clear()
for buc in buckets:
li.extend(buc)
#把数据重新写回li
it+=1
import random
li=list(range(1000))
random.shuffle(li)
radix_sort(li)
print(li)
#快速排序的logn是log(2,n)
#基数排序的k是log(10,n)
目前的个人观点:先学一遍python的排序,为啥呢,因为python简单🤣,可以更好的掌握各个排序的意思。