1
+ # -*- coding: utf-8 -*-
2
+
1
3
# 循环不变性的三个性质:初始化/保持/终止
2
4
# 分治方法-将原始问题划分成n个小规模,且结构与原问题相似的自问题-递归
3
5
# 排序算法一般不超过下面这11种情况
4
- #1 Simple sorts
6
+ # 1 Simple sorts
5
7
# 1.1 Insertion sort(插入排序)
6
8
# 1.2 Selection sort(选择排序)
7
9
#
8
- #2 Efficient sorts
10
+ # 2 Efficient sorts
9
11
# 2.1 Merge sort (归并排序)
10
12
# 2.2 Heapsort (堆排序)
11
13
# 2.3 Quicksort (快速排序)
12
14
#
13
- #3 Bubble sort and variants
15
+ # 3 Bubble sort and variants
14
16
# 3.1 Bubble sort (冒泡排序)
15
17
# 3.2 Shell sort (希尔排序)
16
18
# 3.3 Comb sort (梳排序)
17
19
#
18
- #4 Distribution sort
20
+ # 4 Distribution sort
19
21
# 4.1 Counting sort(计数排序)
20
22
# 4.2 Bucket sort(桶排序)
21
23
# 4.3 Radix sort(基数排序)
22
24
#########################################################################################
23
25
24
26
if __name__ == '__main__' :
27
+ from collections import defaultdict
28
+ import math
25
29
A = [4 , 9 , 1 , 13 , 34 , 26 , 10 , 7 , 4 ]
26
30
31
+
27
32
# 1.1,插入排序
28
33
# 算法流程:遍历把每个元素,按照这个元素前面的数组中,根据大小决定的位置,插入该元素
29
34
# 最好:已经排好顺序的集合,这样只需要线性时间即遍历一次集合,每次只需要比较当前元素与前一个元素的大小问题,时间复杂度O(n)
@@ -35,11 +40,13 @@ def insert_sort(array):
35
40
j = i
36
41
while j > 0 and array [j ] < array [j - 1 ]: # 升序
37
42
# print(array)
38
- tmp = array [j - 1 ]
39
- array [j - 1 ] = array [j ]
43
+ tmp = array [j - 1 ]
44
+ array [j - 1 ] = array [j ]
40
45
array [j ] = tmp
41
46
j -= 1
42
47
return array
48
+
49
+
43
50
# insert_sort(A)
44
51
45
52
@@ -48,22 +55,22 @@ def insert_sort(array):
48
55
# 算法流程:将数组分为两部分,一部分是已经排好顺序的,另一部分是未排序的。每次找数组后半部分中最小的一个元素排到前面的序列
49
56
# 选择排序最坏,最好,平均情况都是O(n^2).
50
57
58
+
59
+
51
60
def select_sort (array ):
52
- n = len (array )
61
+ n = len (array )
53
62
for i in range (n ):
54
- iMin = i
55
- for j in range (i + 1 , n ):
56
- if array [iMin ] > array [j ]: #不断替换最小的索引
57
- iMin = j
58
-
63
+ i_min = i
64
+ for j in range (i + 1 , n ):
65
+ if array [i_min ] > array [j ]: # 不断替换最小的索引
66
+ i_min = j
59
67
tmp = array [i ]
60
- array [i ] = array [iMin ]
61
- array [iMin ] = tmp
62
-
68
+ array [i ] = array [i_min ]
69
+ array [i_min ] = tmp
63
70
return array
64
71
65
72
66
- #select_sort(A)
73
+ # select_sort(A)
67
74
68
75
69
76
# 插入排序与选择排序的区别
@@ -82,26 +89,28 @@ def select_sort(array):
82
89
# 算法:是一种基于“分治”策略的一种算法。
83
90
# 归并排序算法是典型的分治算法,对于规模较大的问题,可以分解成若干容易求解的简单的问题,最后把解合并构成初始问题的解
84
91
92
+
93
+
85
94
def merge_sort (array ):
86
95
if len (array ) <= 1 :
87
96
return array
88
97
mid = int (len (array ) / 2 )
89
98
left = merge_sort (array [:mid ])
90
- right = merge_sort (array [mid :]) # 先拆分,直到最小单元
99
+ right = merge_sort (array [mid :]) # 先拆分,直到最小单元
91
100
result = []
92
-
93
101
while len (left ) > 0 and len (right ) > 0 :
94
102
if left [0 ] > right [0 ]:
95
103
result .append (right .pop (0 ))
96
104
else :
97
105
result .append (left .pop (0 ))
98
106
if len (left ) > 0 :
99
- result .extend (merge_sort (left )) # 剩下的列表全部添加到result中
107
+ result .extend (merge_sort (left )) # 剩下的列表全部添加到result中
100
108
else :
101
109
result .extend (merge_sort (right ))
102
110
return result
103
111
104
- #print(merge_sort(A))
112
+
113
+ # print(merge_sort(A))
105
114
106
115
# 2.2, 堆排序
107
116
# 算法:是数据结构-堆,堆排序是选择排序种类的一部分。它的提升是用到了对数时间优先队列(即堆)而不是线性时间搜索。
@@ -111,7 +120,7 @@ def merge_sort(array):
111
120
# 用根元素与最后一个元素交换位置,将根元素从堆中移除,堆大小减小1。
112
121
# 修复堆,回到上一步,直到堆中不剩元素。
113
122
114
- #def heap_sort(array):
123
+ # def heap_sort(array):
115
124
116
125
117
126
# 2.3, 快速排序
@@ -123,18 +132,21 @@ def merge_sort(array):
123
132
# 冒泡排序效率非常低,效率还不如插入排序。数据量大时效率低,对于顺序颠倒的序列效率最低。
124
133
# 算法流程:简单概括就是每次找到序列中最大或最小的元素排到最后面去,循环知道每个元素都处于正确位置。
125
134
135
+
136
+
126
137
def bubble_sort (array ):
127
- n = len (array )
138
+ n = len (array )
128
139
for i in range (n ):
129
- for j in range (n - 1 ):
130
- if array [j ] > array [j + 1 ]:
131
- tmp = array [j + 1 ]
132
- array [j + 1 ] = array [j ]
140
+ for j in range (n - 1 ):
141
+ if array [j ] > array [j + 1 ]:
142
+ tmp = array [j + 1 ]
143
+ array [j + 1 ] = array [j ]
133
144
array [j ] = tmp
134
145
135
- return array
146
+ return array
147
+
136
148
137
- #print(bubble_sort(A))
149
+ # print(bubble_sort(A))
138
150
139
151
# 3.2 希尔排序
140
152
# 希尔排序是in-place算法,但不是稳定的,其实质就是分组插入排序
@@ -145,15 +157,99 @@ def bubble_sort(array):
145
157
# 因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
146
158
147
159
160
+
148
161
def shell_sort (array ):
149
- gap = len (array )/ 2
162
+ n = len (array )
163
+ gap = n // 2
150
164
while gap > 0 :
165
+ for i in range (gap , n ):
166
+ j = i
167
+ while j >= gap and array [j ] < array [j - gap ]:
168
+ tmp = array [j - gap ]
169
+ array [j - gap ] = array [j ]
170
+ array [j ] = tmp
171
+ j -= gap
172
+ gap //= 2
173
+ return array
174
+
151
175
176
+ # print("shell:"+ str(shell_sort(A)))
152
177
153
178
179
+ # 3.3 梳排序
180
+ # 它是冒泡排序的一种变体,
181
+ # 就像希尔排序是利用一个间隔值来分组,然后对每个分组进行插入排序一样
182
+ # 梳排序是先分组,然后对每个分组进行冒泡排序,只不过梳排序每次取间隔为n/1.3
154
183
155
- gap /= 2
184
+
185
+ def comb_sort (array ):
186
+ gap = len (array )
187
+ swaps = True
188
+ while gap > 1 or swaps :
189
+ gap = max (1 , int (gap // 1.25 )) # or 1.3,控制着速率
190
+ swaps = False
191
+ for i in range (len (array ) - gap ):
192
+ j = i + gap
193
+ if array [i ] > array [j ]:
194
+ array [i ], array [j ] = array [j ], array [i ]
195
+ swaps = True
196
+ return array
197
+
198
+
199
+ # print("comb_sort:"+ str(comb_sort(A)))
200
+
201
+
202
+ # 4.1 计数排序
203
+ # 对数组A进行计数排序,需要知道其最大最小值以确定数组范围
204
+ # 并且需要一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数
205
+ # 然后根据数组C来将A中的元素排到正确的位置。
206
+
207
+
208
+ # from collections import defaultdict
209
+ def counting_sort (array , mn , mx ): # 入参需要排序的数组中的最小值和最大值
210
+ result = []
211
+ count = defaultdict (int )
212
+ for i in array :
213
+ count [i ] += 1
214
+ for j in range (mn , mx + 1 ):
215
+ result += [j ] * count [j ] # 返回 n个[j],如[3]*5 = [3,3,3,3,3], [3]*0 = []
216
+ return result
156
217
157
218
219
+ # print("counting_sort:" + str(counting_sort(A, 1, 26)))
158
220
159
221
222
+ # 4.2 桶排序
223
+ # 算法步骤:
224
+ # 桶排序假设待排序的一组数统一的分布在一个范围中,并将这一范围划分成几个子范围,也就是桶。
225
+ # 将待排序的一组数,分档规入这些子桶。并将桶中的数据进行排序。
226
+ # 将各个桶中的数据有序的合并起来。
227
+ # 所以,桶排序重点在于分组的映射函数
228
+
229
+
230
+
231
+ # 4.3 基数排序
232
+ # 算法步骤:
233
+ # 基数排序分为:最低位优先(Least Significant Digit first)法,简称LSD法,最高位优先(Most significant digital)法,简称MSD法;
234
+ # LSD就是先排个位,然后拍十位...; MSD即为反过来的逻辑但是解法不同
235
+
236
+ # 4.3.1 LSD
237
+
238
+ # import math
239
+
240
+
241
+
242
+ def radix_sort (array , radix = 10 ):
243
+ k = int (math .ceil (math .log (max (array ), radix ))) # radix为底的log(max(array)),来计算有几位数
244
+ bucket = [[] for i in range (radix )] # 分桶
245
+ for i in range (1 , k + 1 ):
246
+ for j in array :
247
+ bucket [int (j / (radix ** (i - 1 )) % (radix ** i ))].append (j ) # 结合计数排序,% 相当于 mod 求模
248
+ print (bucket )
249
+ del array [:]
250
+ for z in bucket :
251
+ array += z
252
+ del z [:]
253
+ return array
254
+
255
+ # print("radix_sort:" + str(radix_sort(A)))
0 commit comments