8大算法:冒泡排序,选择排序,插入排序,快速排序,堆排序,归并排序,哈希排序,桶排序(未实现)
制造一个计数器和模拟个无序列表:
# 计时器:
import time
def cal_time(func):
def wapper(*args,**kwargs):
start_time = time.time()
result = func(*args,**kwargs)
end_time = time.time()
print("%s running time is %s s:" %(func.__name__,end_time-start_time))
return result
return wapper
# 造一个无序数列
import random
data = list(range(100))
random.shuffle(data)
print(data)
1、冒泡排序:
# 冒泡
@cal_time
def bubble_sort(li):
for i in range(len(li) - 1):
for j in range(len(li) - i - 1):
if li[j] > li [j+1]:
li[j],li[j+1] = li[j+1],li[j]
bubble_sort(data)
print(data)
冒泡优化:如果执行过程中执行一趟后,发现没有改变,则说明已经排好序了,无序在进行后面的排序,直接结束
@cal_time
def bubble_sort1(li):
for i in range(len(li)-1):
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
if not exchange:
break
bubble_sort1(data)
print(data)
2、选择排序:找出最小的和前面依次换
@cal_time
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]
select_sort(data)
print(data)
3、插入排序:在无序列表里依次取出在有序列表里插入
@cal_time
def insert_sort(li):
for i in range(1,len(li)):
tmp = li[i]
j = i-1
while j>=0 and li[j]> tmp :
li[j+1] = li[j]
j = j-1
li[j+1] = tmp
insert_sort(data)
print(data)
4、快速排序 :时间复杂度为O(nlogn),最坏情况为O(n^2)(就是反向排序,永远不会把列表分成两块)
思想:
① 取一个元素(第一个元素),使其归位;
② 列表被分成两半,左边的都比他小,右边的都比他大;
③ 递归完成排序
# 递归
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)
# 排序
def partition(li,left,right):
tmp = li[left]
while left < right:
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
@cal_time
def quick_sort_1(li):
return quick_sort(data,0,len(data)-1)
quick_sort_1(data)
print(data)
5、堆排序:
思想:
① 建立堆;
② 得到堆顶元素,为最大元素;
③ 去掉堆顶,将最后一个元素放到堆顶,通过一次调整使堆有序;
④ 堆顶元素为第二大元素;
⑤ 直到堆变空
知识点:
完全二叉树,满二叉树
父节点和左孩子节点:i~2*i+1
父节点和右孩子节点:i~2*i+2
最后一个父节点:n//2-1
# 堆排序调整过程:
def shift(li,top,last):
i = top # 父节点
tmp = li[i]
j = 2 * i + 1 # 左孩子节点
while j <= last :
if j < last and li[j] < li[j+1]: #如果存在右孩子节点,则进行右孩子节点的排序
j = j + 1
if li[j] > tmp : # 如果左孩子节点比父节点大,则换位置
li[i] = li[j] # 孩子节点的值放到父节点
i = j # 新的父节点
j = 2 * i + 1 # 新的孩子节点
else:
break
li[i] = tmp
# 取出堆顶排序:
@cal_time
def heap_sort(li):
n = len (li)
for i in range(n//2-1, -1 ,-1): # 从最后一个父节点开始
shift(li,i,n-1)
# 比较省内存的写法
for i in range(n-1, -1 ,-1): # 将堆顶最大元素和最后一个元素互换,继续排序
li[0],li[i] = li[i],li[0] # 将栈顶元素存到最后一个元素,最后一个元素不加入堆,为了节省内存
shift(li,0,i-1)
# # 占用一点内存的写法:使用一个空列表appe堆顶元素
# sult_list = []
# for i in range(n-1,-1,-1):
# sult_list.append(li[0])
# li[0] = li[i]
# shift(li,0,i-1)
# print(sult_list)
heap_sort(data)
print(data)
6、归并排序 : 时间复杂度 O(nlogn)
思想:
① 先分解:将一个列表分解成单个元素
② 比较,形成两个有序列表
③ 合并,将两个有序列表归并
# 合并,将两个有序的列表合并
def merge(li,low,mid,high):
i = low
j = mid + 1
tmp = []
while i <= mid and j <= high:
if li[i] < li[j]:
tmp.append(li[i])
i += 1
else:
tmp.append(li[j])
j += 1
while i <= mid:
tmp.append(li[i])
i += 1
while j <= high:
tmp.append(li[j])
j += 1
li[low:high+1] = tmp
# 测试merge():
'''
testList = [1,3,5,6,2,4,8,9]
merge(testList,0,3,7)
print(testList)
'''
# 分解合并成两个有序列表
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,mid,high) # 输出两个有序列表
@cal_time
def merge_sort_1(li):
merge_sort(data,0,len(data)-1)
merge_sort_1(data)
print(data)
7、希尔排序
思想:
① 将列表按len(list)//2,分成len(list)//2个列表
② 将每个列表进行排序
③ 将每个列表各取一个一个插入,整合成一个新的列表
④ 再将新的列表按 (len(list)//2)//2,再分,再合并
⑤ 最后分成一个列表,进行插入排序
@cal_time
def shell_sort(li):
gap = len(li) // 2
while gap > 0 :
for i in range(gap,len(li)):
tmp = li[i]
j = i - gap
while j >= 0 and li[j] > tmp:
li[j+gap] = li[j]
j -= gap
li[j+gap] = tmp
gap //= 2
shell_sort(data)
print(data)
8、桶排序:
桶排序也叫计数排序,
就是将数据集里面所有元素按顺序列举出来,然后统计元素出现的次数。最后按顺序输出数据集里面的元素。
本人觉得这个快是快,但是太耗内存,就没有实现。。。。