- 冒泡排序
- 选择排序
- 直接插入排序
- 快速排序
- 堆排序
- 归并排序
- 希尔排序
- 总结
- 作业
一、冒泡排序
思路:n个数需要进行n-1趟排序,每一趟排序就是两个相邻的数组比较,交换位置。第i趟排序需要交换n-i-1次
代码:
#Author:Yueru Sun
def bubble_sort(data):
for i in range(0,len(data)-1):
for j in range(0,len(data)-i-1):
if data[j]>data[j+1]:
data[j],data[j+1]=data[j+1],data[j]
return data
print(bubble_sort([1,3,4,21,10]))
###################################################
#时间复杂度o(n*n)
优化的代码:(最好的情况:针对原来排序的序列本来就是有序的,时间复杂的变为0(n))
就是如果出现某一趟排序未交换位置,那么就可以直接break不进行下一趟排序了
def bubble_sort(data):
for i in range(0,len(data)-1):
flag=False#表示未交换
for j in range(0,len(data)-i-1):
if data[j]>data[j+1]:
data[j], data[j + 1] = data[j + 1], data[j]
flag=True
if flag=='False':
break
return data
print(bubble_sort([1,3,4,21,10]))
二、选择排序
原理:n个元素需要进行n-1趟排序,每一趟都会选出最小(大)的那个数组放到正确的位置,下一趟就遍历表中的剩下的元素,继续。。。
代码:
def select_sort(data):
for i in range(0,len(data)-1):
min_num=i#最小元素的下标,默认是每一趟的第一个数字
for j in range(i+1,len(data)):#每一趟需要在data[i+1]~data[len(data)-1]中找到最小(大)的那个数字的位置
if data[j]<data[min_num]:
min_num=j#把最小元素的下标修改未j
#for语句执行结束后就表示在这趟循环中找到了 在data[i+1]~data[len(data)-1]中找到最小(大)的那个数字 的位置
if min_num!=i:#如果最初假定的i不是
data[i],data[min_num]=data[min_num],data[i]
return data
print(select_sort([5,3,2,1,10]))
时间复杂度:o(n*n)
三、直接插入排序
原理:列表被分为有序区和无序区,默认最初的有序区是第一个元素。每次从无序区中选择一个元素,插入到有序区位空置,直到无序区变
代码:
def insert_sort(data):
for i in range(0,len(data)):
key=data[i]
j=i-1#有序序列的最后一个元素
while j>=0:#当有序序列不为空
if data[j]>key:
data[j+1]=data[j]#j之后的元素后移
data[j]=key#把key放到第j个位置
j=j-1#往前移动
return data
时间复杂度:o(n*n)
四、快速排序
原理:每一趟循环使得一个元素归位,同时列表被分成两部分,左边的都比归位元素小,右边的都比归位元素大
代码:
def quick_sort(data,left,right):
if left<right:
#分割成两部分
mid=partion(data,left,right)
#递归实现
quick_sort(data,left,mid-1)
quick_sort(data,mid,right)
def partion(data,left,right):
temp=data[left]
while left<right:
while left<right and temp<=data[right]:
right-=1
data[left]=data[right]
while left<right and temp>=data[left]:
left-=1
data[right]=data[left]
data[left]=temp#或者写data[right]=temp,因为此时left和right相遇了,相遇的位置就是temp存放的位置
return left
平均时间复杂度:o(n*logn)
最坏的情况:o(n*n)
五、堆排序
原理:
建立堆
得到堆顶元素,为最大元素
去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。
堆顶元素为第二大元素。
重复步骤3,直到堆变空。
可以参考:https://www.cnblogs.com/chengxiao/p/6129630.html
https://blog.csdn.net/sxhelijian/article/details/50295637
代码:
def heap_sort(data):
n=len(data)
for i in range(n//2-1,-1,-1):#建立堆,只需要调整堆中的父节点
sift(data,i,n-1)
for i in range(n-1,-1,-1):#从堆的最后一个元素开始调整
data[0],data[i]=data[i],data[0]
sift(data,0,i-1)
def sift(data,low,high):#low是需要调整的堆的堆顶序号,high是需要调整的堆的最后一个元素的序号
i=low
j=2*i+1
tmp=data[i]
while j<=high:
if j<=high and data[j]<data[j+1]:
j+=1
if tmp<data[j]:
data[i]=data[j]
i=j
j=2*i+1
else:
break
data[i]=tmp
时间复杂度:o(n*logn)
六、归并排序
原理:分治的思想。www.cnblogs.com/chengxiao/p/6194356.html
代码:
#归并
def merge(data,low,mid,high):
i=low
j=mid+1
ltmp=[]
while i<mid and j<high:
if data[i]<data[j]:
ltmp.append(data[i])
i+=1
else:
ltmp.append(data[j])
j+=1
while j<=mid:
ltmp.append(data[i])
i+=1
while j<=high:
ltmp.append(data[j])
j+=1
data[low:high+1]=ltmp
def mergesort(data,low,high):
if low<high:
mid=(low+high)//2
mergesort(data,low,mid)
mergesort(data,mid+1,high)
merge(data,low,mid,high)
时间复杂度:O(nlogn)
空间复杂度:O(n)
七、希尔排序
原理:
希尔排序是一种分组插入排序算法。
首先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;
取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。
希尔排序的最后一趟就是直接插入排序
代码:
#希尔排序
def sheel_sort(data):
gap=len(data)//2
while gap>0:
for i in range(gap,len(data)):
key=data[i]
j=i-gap
while j>=0:
if key<data[j]:
data[j+gap]=data[j]
data[j + gap] = key
j-=gap
gap/=2
时间复杂度:时间复杂度: O((1+τ)n)