排序
一、冒泡排序
冒泡排序:俩俩元素(i , i+1) 进行比较,每次选出一个小,(大),执行n-1次
# 稳定性:稳定排序
li=[23,-8,29,-12,6,18,33]
"""
思路:
1. 第一次循环,俩俩比较,左边元素>右边元素,交换位置
2. 比较的时候,不包含最后一个元素,因为交换的时候,
比较倒数第二个元素的时候,已经对最后一个元素进行了比较
3. 外循环0------n-1
"""
def sortbuble(li):
n=len(li)
for i in range(n-1):
for j in range(n-1-i):
if li[j]>li[j+1]:
li[j],li[j+1]=li[j+1],li[j]
print(li)
sortbuble(li)
# 时间复杂度:最佳是O(n)(已经排好序),最坏O(n^2)
# 稳定性:稳定
二、 选择排序
# 每次都会选择一个最小或者最大的元素,放在前面,排好序。
"""
思路:
1. 最小元素索引 min_index=0,从第一个元素开始比较,一直比较到最后
如果li[min_index]>元素li[j]:将min_index索引值=j
一直找,一定能找到真正的min_index
2. 把li[min_index]跟假定的最初的最小元素(i)进行互换。
"""
li=[3,-2,5,10,-9,11,7,-1]
def sortchoose(li):
n=len(li)
# 先拿第i个元素
for i in range(n-1):
# 假定第i个元素就是最小元素
min_index=i
for j in range(i+1,n):
if li[j]<li[min_index]:
min_index=j
li[i],li[min_index]=li[min_index],li[i]
print(li)
sortchoose(li)
# 时间复杂度:O(n^2)
# 稳定性:不稳定
三、 插入排序
# 从第二个元素开始,插入到“排好队”的数组中,每个元素保证插入之后都是有序的。
# 1. 先考虑第0个元素就是排好队的。
# 从第1个元素拿出来放到temp,跟排好队的元素比较
li=[3,-2,5,10,-9,11,7,-1]
def sortinsert(li):
n=len(li)
for i in range(1,n):
# i=1
temp=li[i]
# 拿0-2跟排好队的[3]里面元素比,从右往左比较。
# 如果-2<排好队的3,把排好队的元素向右串
j=i-1 # i-1之前都是排队的
while temp<li[j] and j>=0:
li[j+i]=li[j]
j-=1
li[j+1]=temp
print(li)
sortinsert(li)
# 时间复杂度:最佳是O(n)(已经排好序),最坏O(n^2)
# 稳定性:稳定
四、希尔排序
希尔排序:最小增量排序,根据一定的增量,将记录分组,然后对每一组数据进行插入排序
li=[3,-2,5,10,-9,11,7,-1]
# increment 增量参数 一定是列表,列表中是每一次的增量,大---小(1)
def shell(li,increment):
n=len(li)
for inc in increment:
for k in range(inc):
for i in range(k,n,inc):
# for i in range(inc,n):
temp=li[i]
# 拿-2根排好队的【3】里面元素比,从右往左比较。
# 如果-2<排好队的3,把排好队的元素向右串
j=i-inc # i-1之前都是排好队的
while temp<li[j] and j>0:
# li[i]=li[i-1]
li[j+inc]=li[j]
j-=inc
li[j+inc]=temp
print(li)
# shell(li,[3,2,1])
不稳定排序
五、快速排序
先在数组中找一个中心点pivot,使得中心点的左侧元素都<pivot,中心点右侧的元素都>pivot
"""
1. 定义一个方法,要有两个索引,一个left,一个right
left<right递归才有意义
2. 找中心点
3. 如果已经找到中心点,下一步,左半部分使用递归,右半部分也使用递归
左半部分:left,mid-1
右半部分:mid+1,right
"""
def quick(li,left,right):
if left<right:
mid=partition(li,left,right)
quick(li,left,mid-1)
quick(li,mid+1,right)
return li
找中心点方法
"""
1. 先设置好pivot=left
2. 可以右,左覆盖元素
右--> 左:元素<pivot小,覆盖
right-1
"""
def partition(li,left,right):
pivot=li[left]
while left<right:
# 一直找,找到比3小的元素,没找到就right-1,找到之后就覆盖
while left<right and pivot<li[right]:
right-=1
li[left]=li[right]
while left<right and pivot >li[left]:
left+=1
li[right]=li[left]
li[left]=pivot
return left
print(quick(li,0,len(li)-1))
稳定:不稳定
六、归并排序
归并排序:把两个有序的数据集合合并成一个有序的数据集
# 分久必合,合久必分
# 1. 先拆,拆到只有一个元素的时候,然后逐步合并
# 拆的时候,分一半一半的拆mid=(low+high)//2,继续拆,[low,mid],[mid+1,high]
# 2. low=high就不用拆了
# 3. 采用递归
def mergeSort(li,low,high):
if low<high:
mid=(low+high)//2
mergeSort(li,low,mid)
mergeSort(li,mid+1,high)
4. 合并
def _merge(li,low,mid,high):
# i 左边部分的第一个元素
# j 右边部分的第一个元素
i=low
j=mid+1
temp=[]
while i<=mid and i<=high:
if li[i]<=li[j]:
temp.append(li[i])
i+=1
else:
temp.append(li[j])
j+=1
while i<=mid:
temp.append(li[i])
i+=1
while j<=high:
temp.append(li[j])
j+=1
li[low:high+1]=temp
print(mergeSort(li,0,len(li)-1))
# 时间复杂度
# 拆log(n)
# 合并 nlog(n)
# 稳定性:稳定排序