京公网安备 11010802034615号
经营许可证编号:京B2-20210330
Python八大常见排序算法定义、实现及时间消耗效率分析
本文实例讲述了Python八大常见排序算法定义、实现及时间消耗效率分析。分享给大家供大家参考,具体如下:
昨晚上开始总结了一下常见的几种排序算法,由于之前我已经写了好几篇排序的算法的相关博文了现在总结一下的话可以说是很方便的,这里的目的是为了更加完整详尽的总结一下这些排序算法,为了复习基础的东西,从冒泡排序、直接插入排序、选择排序、归并排序、希尔排序、桶排序、堆排序。快速排序入手来分析和实现,在最后也给出来了简单的时间统计,重在原理、算法基础,其他的次之,这些东西的熟练掌握不算是对之后的工作或者接下来的准备面试都是很有帮助的,算法重在理解内在含义和理论基础,在实现的时候才能避开陷阱少出错误,这不是说练习的时候有错误不好而是说,有些不该出现的错误尽量还是少出现的好,毕竟好的编程习惯是离不开严格的约束的,好了,这里就不多说了,复习一下基础知识,共同学习吧,下面是具体实现,注释应该都很详细,就不解释了:
#!usr/bin/env python
#encoding:utf-8
'''''
__Author__:沂水寒城
功能:八大排序算法
'''
import time
import random
time_dict={}
def time_deco(sort_func):
'''''
时间计算的装饰器函数,可用于计算函数执行时间
'''
def wrapper(num_list):
start_time=time.time()
res=sort_func(num_list)
end_time=time.time()
time_dict[str(sort_func)]=(end_time-start_time)*1000
print '耗时为:',(end_time-start_time)*1000
print '结果为:', res
return wrapper
def random_nums_generator(max_value=1000, total_nums=20):
'''''
随机数列表生成器
一些常用函数:
random随机数生成
random.random()用于生成一个0到1之间的随机数:0 <= n < 1.0;
random.uniform(a, b),用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限。min(a,b) <= n <= max(a,b);
randdom.randint(a, b), 用于生成一个指定范围内的整数,其中a是下限,b是上限: a<= n <= b;
random.randrange(start, stop, step), 从指定范围内,按指定基数递增的集合获取一个随机数;
random.choice(sequence), 从序列中获取一个随机元素;
random.shuffle(x), 用于将一个列表中的元素打乱;
random.sample(sequence, k), 从指定序列中随机获取指定长度的片断;
'''
num_list=[]
for i in range(total_nums):
num_list.append(random.randint(0,max_value))
return num_list
#@time_deco
def Bubble_sort(num_list):
'''''
冒泡排序,时间复杂度O(n^2),空间复杂度O(1),是稳定排序
'''
for i in range(len(num_list)):
for j in range(i,len(num_list)):
if num_list[i]>num_list[j]: #这里是升序排序
num_list[i], num_list[j]=num_list[j], num_list[i]
return num_list
#@time_deco
def Insert_sort(num_list):
'''''
直接插入排序,时间复杂度O(n^2),空间复杂度O(1),是稳定排序
'''
for i in range(len(num_list)):
for j in range(0,i):
if num_list[i]<num_list[j]: #这里是升序排序,跟冒泡排序差别在于,冒泡是向后遍历,这个是向前遍历
num_list[i], num_list[j]=num_list[j], num_list[i]
return num_list
#@time_deco
def Select_sort(num_list):
'''''
选择排序,时间复杂度O(n^2),空间复杂度O(1),不是稳定排序
'''
for i in range(len(num_list)):
min_value_index=i
for j in range(i, len(num_list)):
if num_list[j]<num_list[min_value_index]:
min_value_index=j #乍一看,感觉冒泡,选择,插入都很像,选择跟冒泡的区别在于:冒泡是发现大
#小数目顺序不对就交换,而选择排序是一轮遍历结束后选出最小值才交换,效率更高
num_list[i], num_list[min_value_index]=num_list[min_value_index], num_list[i]
return num_list
#@time_deco
def Merge_sort(num_list):
'''''
归并排序,时间复杂度O(nlog₂n),空间复杂度:O(1),是稳定排序
'''
if len(num_list)==1:
return num_list
length=len(num_list)/2
list1=num_list[:length]
list2=num_list[length:]
result_list=[]
while len(list1) and len(list2):
if list1[0]<=list2[0]:
result_list.append(list1[0])
del list1[0] #这里需要删除列表中已经被加入到加过列表中的元素,否则最后比较完后列表
else: #中剩余元素无法添加
result_list.append(list2[0])
del list1[0]
if len(list1): #遍历比较完毕后列表中剩余元素的添加
result_list+=list1
else:
result_list+=list2
return result_list
#@time_deco
def Shell_sort(num_list):
'''''
希尔排序,时间复杂度:O(n),空间复杂度:O(n^2),不是稳定排序算法
'''
new_list = []
for one_num in num_list:
new_list.append(one_num)
count=len(new_list)
step=count/2;
while step>0:
i=0
while i<count:
j=i+step
while j<count:
t=new_list.pop(j)
k=j-step
while k>=0:
if t>=new_list[k]:
new_list.insert(k+1, t)
break
k=k-step
if k<0:
new_list.insert(0, t)
#print '---------本轮结果为:--------'
#print new_list
j=j+step
#print j
i=i+1
#print i
step=step/2 #希尔排序是一个更新步长的算法
return new_list
#@time_deco
def Tong_sort(num_list):
'''''
桶排序,时间复杂度O(1),空间复杂度与最大数字有关,可以认为是O(n),典型的空间换时间的做法
'''
original_list = []
total_num=max(num_list) #获取桶的个数
for i in range(total_num+1): #要注意这里需要的数组元素个数总数比total_num数多一个因为下标从0开始
original_list.append(0)
for num in num_list:
original_list[num] += 1
result_list = []
for j in range(len(original_list)):
if original_list[j] != 0:
for h in range(0,original_list[j]):
result_list.append(j)
return result_list
def Quick_sort(num_list):
'''''
快速排序,时间复杂度:O(nlog₂n),空间复杂度:O(nlog₂n),不是稳定排序
'''
if len(num_list)<2:
return num_list
left_list = [] #存放比基准结点小的元素
right_list = [] #存放比基准元素大的元素
base_node = num_list.pop(0) #在这里采用pop()方法的原因就是需要移除这个基准结点,并且赋值给base_node这个变量
#在这里不能使用del()方法,因为删除之后无法再赋值给其他变量使用,导致最终数据缺失
#快排每轮可以确定一个元素的位置,之后递归地对两边的元素进行排序
for one_num in num_list:
if one_num < base_node:
left_list.append(one_num)
else:
right_list.append(one_num)
return Quick_sort(left_list) + [base_node] + Quick_sort(right_list)
def Heap_adjust(num_list, i, size):
left_child = 2*i+1
right_child = 2*i+2
max_temp = i
#print left_child, right_child, max_temp
if left_child<size and num_list[left_child]>num_list[max_temp]:
max_temp = left_child
if right_child<size and num_list[right_child]>num_list[max_temp]:
max_temp = right_child
if max_temp != i:
num_list[i], num_list[max_temp] = num_list[max_temp], num_list[i]
Heap_adjust(num_list, max_temp, size) #避免调整之后以max为父节点的子树不是堆
def Create_heap(num_list, size):
a = size/2-1
for i in range(a, -1, -1):
#print '**********', i
Heap_adjust(num_list, i, size)
#@time_deco
def Heap_sort(num_list):
'''''
堆排序,时间复杂度:O(nlog₂n),空间复杂度:O(1),不是稳定排序
'''
size=len(num_list)
Create_heap(num_list, size)
i = size-1
while i > 0:
num_list[0], num_list[i] = num_list[i], num_list[0]
size -= 1
i -= 1
Heap_adjust(num_list, 0, size)
return num_list
if __name__ == '__main__':
num_list=random_nums_generator(max_value=100, total_nums=50)
print 'Bubble_sort', Bubble_sort(num_list)
print 'Insert_sort', Insert_sort(num_list)
print 'Select_sort', Select_sort(num_list)
print 'Merge_sort', Merge_sort(num_list)
print 'Shell_sort', Shell_sort(num_list)
print 'Tong_sort', Tong_sort(num_list)
print 'Heap_sort', Heap_sort(num_list)
print 'Quick_sort', Quick_sort(num_list)
# print '-----------------------------------------------------------------------------'
# for k,v in time_dict.items():
# print k, v
结果如下:
Bubble_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Insert_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Select_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Merge_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Shell_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Tong_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Heap_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
Quick_sort [34, 49, 63, 67, 71, 72, 75, 120, 128, 181, 185, 191, 202, 217, 241, 257, 259, 260, 289, 293, 295, 304, 311, 326, 362, 396, 401, 419, 423, 456, 525, 570, 618, 651, 701, 711, 717, 718, 752, 774, 813, 816, 845, 885, 894, 900, 918, 954, 976, 998]
这里没有使用到装饰器,主要自己对这个装饰器不太了解,在快速排序的时候报错了,也没有去解决,这里简单贴一下一个测试样例使用装饰器的结果吧:
Bubble_sort 耗时为: 0.0290870666504
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Insert_sort 耗时为: 0.0209808349609
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Select_sort 耗时为: 0.0259876251221
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Merge_sort 耗时为: 0.0138282775879
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Shell_sort 耗时为: 0.113964080811
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Tong_sort 耗时为: 0.0460147857666
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Heap_sort 耗时为: 0.046968460083
结果为: [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
None
Quick_sort [5, 45, 46, 63, 81, 83, 89, 89, 89, 90]
-----------------------------------------------------------------------------
<function Shell_sort at 0x7f8ab9d34410> 0.113964080811
<function Select_sort at 0x7f8ab9d34230> 0.0259876251221
<function Insert_sort at 0x7f8ab9d34140> 0.0209808349609
<function Heap_sort at 0x7f8ab9d34758> 0.046968460083
<function Merge_sort at 0x7f8ab9d34320> 0.0138282775879
<function Tong_sort at 0x7f8ab9d34500> 0.0460147857666
<function Bubble_sort at 0x7f8ab9d34050> 0.0290870666504
接下来有时间的话我想学一下装饰器的东西,感觉对于模式化的东西装饰器简直就是一个神器,但是得明白会用会写才行哈!
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
一、问题:为什么 ID 会"断号" 很多刚接触 MySQL 的同学都会有一个困惑:表里的主键 ID 是自增的,删了中间几行数据之后,ID 变 ...
2026-10-22一、问题场景:为什么会重复 JOIN 同一个子查询 在写复杂 SQL 时,经常遇到这种需求:同一张表或同一个聚合子查询,要和主表关联 ...
2026-10-22人力资源专员是HR体系的执行入口。招聘信息发布、简历初筛、面试安排、考勤汇总、入离职手续、劳动合同与档案管理,大多由这个岗 ...
2026-10-22人力资源经理问“必学技巧”,真正要解决的不是知识清单不够长,而是时间有限、业务催得紧,学完却用不上。更有效的路径是:先用 ...
2026-10-22内容营销岗位的核心任务,不是“把文案写得更漂亮”,而是围绕目标受众,用持续的内容供给影响认知、推动转化并沉淀复购。它至少 ...
2026-10-22理财经理培训课程很多,难的是判断“先学什么、后学什么、学完能做什么”。与其按课程名称罗列,不如先看岗位任务:客户分层与维 ...
2026-10-22理财经理的知识结构,可以先用一句话概括:合规与产品知识决定“不出错”,客户经营与资产配置决定“够不够专业”,市场研判与数 ...
2026-10-22经济学背景做数据分析,优势不在工具,而在问题意识:供需如何相互作用、成本与收益如何权衡、变量之间是相关还是因果。真正的缺 ...
2026-10-22需要,但要把“需要”理解准确。经济学本身就在处理数据:GDP、物价、就业、企业营收、问卷调研,都是经济分析的原料。真正的区 ...
2026-10-22经济学分析能力不是单一技能,它至少由三层构成:把现实问题转成可检验假设的理论框架能力、用数据与统计方法验证假设的工具能力 ...
2026-10-22金融分析师的知识提升,先补的不是更多模型,而是让结论可复核的底层能力。按任务顺序,大致是四层:财务与业务理解、指标口径管 ...
2026-10-22金融分析师的“通用技能”,指换到不同机构、不同行业组仍用得上的底层能力,而非某家公司内部系统的操作经验。按任务拆,日常要 ...
2026-10-22先给结论:数据分析证书不是金融分析师的准入条件,招聘方也不会因为一张证书就直接判断你能做分析。要不要考,取决于你当前任务 ...
2026-10-22金融分析师的核心技能,不是“会看K线”或“会讲宏观”,而是能把一家公司、一个行业或一类资产,转化为可核查的数据判断与书面 ...
2026-10-22产品经理的知识提升,不是把需求文档、原型、SQL、数据分析、项目管理都学一遍,而是先对准目标岗位的真实任务,找出自己最缺的 ...
2026-10-22产品专员提升工作知识,最有效的方式不是先囤课程,而是围绕日常交付的四件事来补:需求调研与优先级判断、原型与PRD表达、竞品 ...
2026-10-22产品运营专员提升个人能力,常见误区是先把Excel、SQL、Python列成一张学习清单,然后从第一个工具开始学。更有效的做法是先回答 ...
2026-10-22产品运营的能力提升,最怕从“课程目录”出发:今天学增长模型,明天背SQL语法,学完却说不清自己负责的功能为什么激活率低。更 ...
2026-10-22产品经理的技能和影响力不是两条分开的赛道。技能决定你能不能把问题分析清楚、把方案设计对;影响力决定你的判断能否被团队接受 ...
2026-10-22产品经理要学的数据分析能力,不是“会写SQL”或“会用BI工具”这么简单。更准确地说,是围绕需求评估、功能迭代、指标监控、实 ...
2026-10-22