十大经典排序算法(python实现)(原创)

使用场景:

1,空间复杂度 越低越好、n值较大:

  堆排序  O(nlog2n)  O(1)

2,无空间复杂度要求、n值较大:

  桶排序  O(n+k)    O(n+k)

经典排序算法图解:

经典排序算法的复杂度:

大类一(比较排序法):

1、冒泡排序(Bubble Sort)【前后比较-交换】

python代码实现:

 1 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44]
2 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
3
4 while 1:
5 state = 0 # 假设本次循环没有改变
6 for i in range(len(d0) - 1):
7 if d0[i] > d0[i + 1]:
8 d0[i], d0[i + 1] = d0[i + 1], d0[i]
9 state = 1 # 有数值交换,那么状态值置1
10 if not state: # 如果没有数值交换,那么就跳出
11 break
12
13 print(d0)
14 print(d0_out)

2、选择排序(Selection Sort)【选择最小的数据放在前面】

python代码实现:

 1 def select_sort(data):
2 d1 = []
3 while len(data):
4 min = [0, data[0]]
5 for i in range(len(data)):
6 if min[1] > data[i]:
7 min = [i, data[i]]
8 del data[min[0]] # 找到剩余部分的最小值,并且从原数组中删除
9 d1.append(min[1]) # 在新数组中添加
10 return d1
11
12 if __name__ == "__main__":
13 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序
14 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
15 d1 = select_sort(d0)
16 print(d1)
17 print(d0_out)

3、插入排序(Insertion Sort)【逐个插入到前面的有序数中】

直接插入排序-python实现:

 1 def direct_insertion_sort(d):   # 直接插入排序,因为要用到后面的希尔排序,所以转成function
2 d1 = [d[0]]
3 for i in d[1:]:
4 state = 1
5 for j in range(len(d1) - 1, -1, -1):
6 if i >= d1[j]:
7 d1.insert(j + 1, i) # 将元素插入数组
8 state = 0
9 break
10 if state:
11 d1.insert(0, i)
12 return d1
13
14
15 if __name__ == "__main__":
16 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序
17 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
18 d1 = direct_insertion_sort(d0)
19 print(d1)
20 print(d0_out)

折半插入排序-python实现:

 1 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44]  # 原始乱序
2 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
3
4 d1 = [d0[0]]
5 del d0[0]
6
7 for i in d0:
8 index_now = [0, len(d1)]
9 while 1:
10 index = index_now[0] + int((index_now[1] - index_now[0]) / 2)
11 if i == d1[index]:
12 d1.insert(index+1,i)
13 break
14 elif index in index_now: # 如果更新的index值在index_now中存在(也有可能是边界),那么就表明无法继续更新
15 d1.insert(index+1,i)
16 break
17 elif i > d1[index]:
18 index_now[0] = index
19 elif i < d1[index]:
20 index_now[1] = index
21
22 print(d1)
23 print(d0_out)

4、希尔排序(Shell Sort)【从大范围到小范围进行比较-交换】类似冒泡和插入的联合

python代码实现:

 1 def direct_insertion_sort(d):  # 直接插入排序,因为要用到后面的希尔排序,所以转成function
2 d1 = [d[0]]
3 for i in d[1:]:
4 state = 1
5 for j in range(len(d1) - 1, -1, -1):
6 if i >= d1[j]:
7 d1.insert(j + 1, i) # 将元素插入数组
8 state = 0
9 break
10 if state:
11 d1.insert(0, i)
12 return d1
13
14
15 def shell_sort(d): # d 为乱序数组,l为初始增量,其中l<len(d),取为len(d)/2比较好操作。最后还是直接省略length输入
16 length = int(len(d) / 2) # 10
17 num = int(len(d) / length) # 2
18 while 1:
19
20 for i in range(length):
21 d_mid = []
22 for j in range(num):
23 d_mid.append(d[i + j * length])
24 d_mid = direct_insertion_sort(d_mid)
25 for j in range(num):
26 d[i + j * length] = d_mid[j]
27 # print(d)
28 length = int(length / 2)
29 if length == 0:
30 return d
31 break
32 # print('length:',length)
33 num = int(len(d) / length)
34
35
36 if __name__ == "__main__":
37 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序
38 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
39 d1 = shell_sort(d0)
40 print(d1)
41 print(d0_out)

5、归并排序(Merge Sort)【分治法-2-4-8插入排序】

python代码实现(这个地方是由大往小进行递归):

 1 # 归并排序,还有些问题。其中有些细节需要重新理解
2 # 也是递归问题
3 def merge_sort(data): # 分治发的典型应用,大问题拆分成小问题,逐个击破,之后将结果合并
4 half_index = int(len(data) / 2) # 将数组拆分
5
6 d0 = data[:half_index]
7 d1 = data[half_index:]
8
9 if len(d0) > 1:
10 d0 = merge_sort(d0)
11
12 if len(d1) > 1:
13 d1 = merge_sort(d1)
14
15 index = 0
16 for i in range(len(d1)):
17 state = 1
18 for j in range(index, len(d0)):
19 if d1[i] < d0[j]:
20 state = 0
21 index = j + 1
22 d0.insert(j, d1[i])
23 break
24 if state == 1: # 如果大于d0这个队列的所有值,那么直接extend所有数据
25 d0.extend(d1[i:])
26 break
27 return d0
28
29
30 if __name__ == "__main__":
31 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序
32 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
33 d1 = merge_sort(d0)
34 print(d1)
35 print(d0_out)
python代码实现(由小扩展到大的子序列):
 1
2 def list_sort(d0, d1): # 基元组往大扩展
3 index = 0
4 for i in range(len(d1)): # 遍历d1数组
5 state = 1
6 for j in range(index, len(d0)): # 遍历d0数组
7 if d0[j] > d1[i]:
8 state = 0
9 index = j + 1
10 d0.insert(j, d1[i])
11 break
12 if state == 1: # 如果大于d0这个队列的所有值,那么直接extend所有数据
13 d0.extend(d1[i:])
14 break
15 return d0
16
17
18 def merge_sort(data):
19 d0 = [[x] for x in data]
20 while len(d0) != 1: # 循环条件
21 length = len(d0)
22 half = int(length/2) # 除2的整数部分
23 quo = length%2 # 除2的商
24 d0_mid = []
25 for i in range(half):
26 d0_mid.append(list_sort(d0[i*2], d0[i*2+1]))
27 if quo:
28 d0_mid.append(d0[-1])
29 d0 = d0_mid
30
31 return d0[0]
32
33
34
35 if __name__ == "__main__":
36 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序
37 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
38 d1 = merge_sort(d0)
39 print(d1)
40 print(d0_out)

6、快速排序(Quick Sort)【选取一个基准值,小数在左大数在在右】

python代码实现:

 1 # import sys
2 # sys.setrecursionlimit(1000000)
3
4 def quick_sort(data):
5 d = [[], [], []]
6 d_pivot = data[-1] # 因为是乱序数组,所以第几个都是可以的,理论上是一样的
7 for i in data:
8 if i < d_pivot: # 小于基准值的放在前
9 d[0].append(i)
10 elif i > d_pivot: # 大于基准值的放在后
11 d[2].append(i)
12 else: # 等于基准值的放在中间
13 d[1].append(i)
14
15 # print(d[0], d[1], d[2])
16 if len(d[0]) > 1: # 大于基准值的子数组,递归
17 d[0] = quick_sort(d[0])
18
19 if len(d[2]) > 1: # 小于基准值的子数组,递归
20 d[2] = quick_sort(d[2])
21
22 d[0].extend(d[1])
23 d[0].extend(d[2])
24 return d[0]
25
26
27 if __name__ == "__main__":
28 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序
29 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序
30 d1 = quick_sort(d0)
31 print(d1)
32 print(d0_out)

7、堆排序(Heap Sort)【利用最大堆和最小堆的特性】

python代码实现:

 1 d0 = [99, 5, 36, 7, 22, 17, 46, 12, 2, 19, 25, 28, 1, 92]
2
3
4 def sort_max(data): # 直接冒泡一下吧,小到大
5 for i in range(len(data) - 1):
6 for j in range(len(data) - 1):
7 if data[j] > data[j + 1]:
8 data[j], data[j + 1] = data[j + 1], data[j]
9 return data
10
11 def heap_min(data,type):
12 index = 0
13 if not type:
14 for i in range(len(data[1:])):
15 if data[index] > data[i+1]:
16 index = i+1
17 data[0],data[index] = data[index],data[0]
18 return data
19 else:
20 for i in range(len(data[1:])):
21 if data[index] < data[i+1]:
22 index = i+1
23 data[0],data[index] = data[index],data[0]
24 return data
25
26
27 # d0 = [3,2,1,10,3]
28 # print(heap_min(d0,1))
29 # print(heap_min(d0,0))
30
31 import numpy as np
32
33
34 def heap_adj(data, type): # data 原始堆,type=1最大堆,type=0最小堆
35 length = len(data)
36 floor = int(np.log2(length))
37 for i in range(floor, 0, -1): # 3(7 6 5 4)-2(3 2)-1(1)
38 for j in range(2 ** floor - 1, 2 ** (floor - i) - 1, -1):
39 # print(i,j) # j-1 为当前父节点
40 d_mid = [data[j - 1]] # j = 7,j-1 =6 index
41 if j * 2 <= length: # 14
42 d_mid.append(data[j * 2 - 1])
43 if j * 2 + 1 <= length:
44 d_mid.append(data[j * 2])
45
46 d_mid = heap_min(d_mid, type)
47
48 if len(d_mid) == 2:
49 data[j - 1], data[j * 2 - 1] = d_mid[0], d_mid[1]
50 elif len(d_mid) == 3:
51 data[j - 1], data[j * 2 - 1], data[j * 2] = d_mid[0], d_mid[1], d_mid[2]
52 return data
53
54 d1 = []
55 for i in range(len(d0)):
56 data = heap_adj(d0, 0)
57 d1.append(d0[0])
58 del d0[0]
59
60
61 print(d1)

大类二(非比较排序法):

8、计数排序(Counting Sort)【字典计数-还原】

python代码实现:

 1 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44]
2 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64]
3
4 d_max = 0
5 d_min = 0
6 for i in d0:
7 if d_max<i:
8 d_max = i
9 if d_min>i:
10 d_min = i
11
12 d1 = {}
13 for i in d0:
14 if i in d1.keys():
15 d1[i] += 1
16 else:
17 d1[i] = 1
18
19 d2 = []
20 for i in range(d_min,d_max+1):
21 if i in d1.keys():
22 for j in range(d1[i]):
23 d2.append(i)
24
25 print(d2)

9、桶排序(Bucket Sort)【链表】

python代码实现:

 1 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44]
2
3 d1 = [[] for x in range(10)]
4 for i in d0:
5 d1[int(i/10)].append(i)
6
7 # print(d1)
8
9
10 for i in range(len(d1)):
11 if d1[i] != []:
12 d2 = [[] for x in range(10)]
13 for j in d1[i]:
14 d2[j%10].append(j)
15 d1[i] = d2
16
17 # print(d1)
18
19 d3 = []
20 for i in d1:
21 if i:
22 for j in i:
23 if j:
24 for k in j:
25 if k:
26 d3.append(k)
27 print(d3)

10、基数排序(Radix Sort)

python代码实现:

 1 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44]
2
3 d1 = [[] for x in range(10)]
4
5 # 第一次 最小位次排序
6 for i in d0:
7 d1[i % 10].append(i)
8
9 print(d1)
10
11 d0_1 = []
12 for i in d1:
13 if i:
14 for j in i:
15 d0_1.append(j)
16 print(d0_1)
17
18 # 第二次 次低位排序
19 d2 = [[] for x in range(10)]
20 for i in d0_1:
21 d2[int(i/10)].append(i)
22 print(d2)
23
24 d0_2 = []
25 for i in d2:
26 if i:
27 for j in i:
28 d0_2.append(j)
29 print(d0_2)

出自 https://www.cnblogs.com/Mufasa/p/10527387.html

十大经典算法 Python实现的更多相关文章

  1. JS的十大经典算法排序

    引子 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements JavaScript. 当年,想凭借抱Java大腿火一把而不惜把自己名字给改了的JavaScript(原名LiveScript ...

  2. 数据挖掘十大经典算法(5) 最大期望(EM)算法

    在统计计算中,最大期望(EM,Expectation–Maximization)算法是在概率(probabilistic)模型中寻找参数最大似然估计的算法,其中概率模型依赖于无法观测的隐藏变量(Lat ...

  3. ICDM评选:数据挖掘十大经典算法

    原文地址:http://blog.csdn.net/aladdina/article/details/4141177 国际权威的学术组织the IEEE International Conferenc ...

  4. 数据挖掘领域十大经典算法之—C4.5算法(超详细附代码)

    https://blog.csdn.net/fuqiuai/article/details/79456971 相关文章: 数据挖掘领域十大经典算法之—K-Means算法(超详细附代码)        ...

  5. JS的十大经典算法

    冒泡排序(Bubble Sort) 冒泡排序须知: 作为最简单的排序算法之一,冒泡排序给我的感觉就像Abandon在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉...冒泡排序还有一种优化算 ...

  6. 数据挖掘十大经典算法[0]-K-Means算法

    K-Means算法的输入N,K和一个size为N的向量组vector.输出K个两两互不相交的向量组.其本质是将给定的向量组划分成K个类别,使得同类别的向量相似度比较大,而不同类别的向量之间的相似度较小 ...

  7. 数据挖掘十大经典算法(9) 朴素贝叶斯分类器 Naive Bayes

    贝叶斯分类器 贝叶斯分类器的分类原理是通过某对象的先验概率,利用贝叶斯公式计算出其后验概率,即该对象属于某一类的概率,选择具有最大后验概率的类作为该对象所属的类.眼下研究较多的贝叶斯分类器主要有四种, ...

  8. 数据挖掘十大经典算法--CART: 分类与回归树

    一.决策树的类型  在数据挖掘中,决策树主要有两种类型: 分类树 的输出是样本的类标. 回归树 的输出是一个实数 (比如房子的价格,病人呆在医院的时间等). 术语分类和回归树 (CART) 包括了上述 ...

  9. 数据挖掘领域十大经典算法之—SVM算法(超详细附代码)

    https://blog.csdn.net/fuqiuai/article/details/79483057

随机推荐

  1. D-【乐】k进制数(同余)

    题目 https://ac.nowcoder.com/acm/contest/907/D 做法 \((x)_k\)定义编号,如果\(a+b\)加到一起能进一位,\(a+b\rightarrow 1+( ...

  2. Tkinter 之Frame标签

    一.参数说明 语法 作用 width 设置 Frame 的宽度默认值是 0 height 设置 Frame 的高度默认值是 0 background(bg) 设置 Frame 组件的背景颜色 bord ...

  3. ES索引文件和数据文件大小对比——splunk索引文件大小远小于ES,数据文件的压缩比也较ES更低,有趣的现象:ES数据文件zip压缩后大小和splunk的数据文件相当!词典文件tim/tip+倒排doc/pos和cfs文件是索引的大头

    和splunk对比: ES中各个倒排索引文件的分布: 测试说明:ES2.41版本,数据使用500次批量插入,每批数据都不同,大小500条,每条数据50个字段,对应的字符串使用长度为1-10个单词随机生 ...

  4. 异步任务神器 和定时任务Celery

    异步任务神器 Celery Celery 在程序的运行过程中,我们经常会碰到一些耗时耗资源的操作,为了避免它们阻塞主程序的运行,我们经常会采用多线程或异步任务.比如,在 Web 开发中,对新用户的注册 ...

  5. 2018-2019-2 20165209 《网络对抗技术》Exp8: Web基础

    2018-2019-2 20165209 <网络对抗技术>Exp8: Web基础 1 基础问题回答和实验内容 1.1基础问题回答 (1)什么是表单 表单在网页中主要负责数据采集功能.一个表 ...

  6. Android 查看和修改网络mtu

    CPU:RK3288 系统:Android 5.1 MTU:通信术语 最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以 ...

  7. 使用docker运行mysql

    以前开发的时候都是用本地的sqlite开发,但是极少数情况下,sqlite支持的语法发布到服务器上链接mysql会报错. 为了避免这种现象,还是链接本地mysql开发还是更稳定的, 可是开发的项目多了 ...

  8. Ionic4.x 新增底部 tabs 页面

    1.创建 tab4 模块 ionic g page tab4 2.修改根目录里 app-routing.module.ts 文件里面的路由配置,去掉默认增加的路由 3.tabs.router.modu ...

  9. 阶段5 3.微服务项目【学成在线】_day18 用户授权_11-前端集成认证授权-身份校验

    把下面赋值到nginx中 前端的服务需要配置一下 重启nginx 启动教学管理的前端 没有登陆直接就进来教学管理的后端了 下面我们要做的就是这两件事 1.前端页面校验用户的身份,如果用户没有登录则跳转 ...

  10. Spring走向注解驱动编程

    SpringFramework的两大核心,IOC(Inversion of control)控制反转和DI(Dependency Inject)依赖注入,其推崇的理念是应用系统不应以java代码的方式 ...