|
| 1 | +# 十大经典排序算法(python实现)(原创) |
| 2 | +# https://www.cnblogs.com/Mufasa/p/10527387.html |
| 3 | + |
| 4 | +sample = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 1, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] |
| 5 | +sample_sorted = [1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序 |
| 6 | + |
| 7 | +print(sample) |
| 8 | +print(sample_sorted) |
| 9 | + |
| 10 | +def assert_list(actual, expected): |
| 11 | + len1 = len(actual) |
| 12 | + len2 = len(expected) |
| 13 | + if len1 == len2: |
| 14 | + for i in range(max(len1, len2)): |
| 15 | + if actual[i] != expected[i]: return actual |
| 16 | + return 'OK' |
| 17 | + return actual |
| 18 | + |
| 19 | +def bubble_sort(lst): |
| 20 | + while 1: |
| 21 | + touched = 0 # 假设本次循环没有改变 |
| 22 | + for i in range(len(lst) - 1): |
| 23 | + if lst[i] > lst[i + 1]: |
| 24 | + lst[i], lst[i + 1] = lst[i + 1], lst[i] |
| 25 | + touched = 1 # 有数值交换,那么状态值置1 |
| 26 | + if not touched: # 如果没有数值交换,那么就跳出 |
| 27 | + break |
| 28 | + |
| 29 | +dt = sample[:] |
| 30 | +bubble_sort(dt) |
| 31 | +print('bubble_sort: ' + str(assert_list(dt, sample_sorted))) |
| 32 | + |
| 33 | +def selection_sort(lst): |
| 34 | + d1 = [] |
| 35 | + while len(lst): |
| 36 | + min = [0, lst[0]] |
| 37 | + for i in range(len(lst)): |
| 38 | + if min[1] > lst[i]: |
| 39 | + min = [i, lst[i]] |
| 40 | + del lst[min[0]] # 找到剩余部分的最小值,并且从原数组中删除 |
| 41 | + d1.append(min[1]) # 在新数组中添加 |
| 42 | + return d1 |
| 43 | + |
| 44 | +dt = selection_sort(sample[:]) |
| 45 | +print('selection_sort: ' + str(assert_list(dt, sample_sorted))) |
| 46 | + |
| 47 | +def direct_insertion_sort(lst): # 直接插入排序,因为要用到后面的希尔排序,所以转成function |
| 48 | + d1 = [lst[0]] |
| 49 | + for i in lst[1:]: |
| 50 | + state = 1 |
| 51 | + for j in range(len(d1) - 1, -1, -1): |
| 52 | + if i >= d1[j]: |
| 53 | + d1.insert(j + 1, i) # 将元素插入数组 |
| 54 | + state = 0 |
| 55 | + break |
| 56 | + if state: |
| 57 | + d1.insert(0, i) |
| 58 | + return d1 |
| 59 | + |
| 60 | +dt = direct_insertion_sort(sample[:]) |
| 61 | +print('direct_insertion_sort: ' + str(assert_list(dt, sample_sorted))) |
| 62 | + |
| 63 | +def binary_insertion_sort(lst): # 基于 direct_insertion_sort |
| 64 | + d1 = [lst[0]] |
| 65 | + for i in lst[1:]: |
| 66 | + index_now = [-1, len(d1)] |
| 67 | + while 1: |
| 68 | + index = index_now[0] + int((index_now[1] - index_now[0]) / 2) |
| 69 | + if i == d1[index]: |
| 70 | + d1.insert(index+1, i) |
| 71 | + break |
| 72 | + elif index in index_now: # 如果更新的index值在index_now中存在(也有可能是边界),那么就表明无法继续更新 |
| 73 | + d1.insert(index+1, i) |
| 74 | + break |
| 75 | + elif i > d1[index]: |
| 76 | + index_now[0] = index |
| 77 | + elif i < d1[index]: |
| 78 | + index_now[1] = index |
| 79 | + return d1 |
| 80 | + |
| 81 | +dt = binary_insertion_sort(sample[:]) |
| 82 | +print('binary_insertion_sort: ' + str(assert_list(dt, sample_sorted))) |
| 83 | + |
| 84 | +def shell_sort(d): # d 为乱序数组,l为初始增量,其中l<len(d),取为len(d)/2比较好操作。最后还是直接省略length输入 |
| 85 | + length = int(len(d) / 2) # 10 |
| 86 | + num = int(len(d) / length) # 2 |
| 87 | + while 1: |
| 88 | + for i in range(length): |
| 89 | + d_mid = [] |
| 90 | + for j in range(num): |
| 91 | + d_mid.append(d[i + j * length]) |
| 92 | + d_mid = direct_insertion_sort(d_mid) |
| 93 | + for j in range(num): |
| 94 | + d[i + j * length] = d_mid[j] |
| 95 | + length = int(length / 2) |
| 96 | + if length == 0: |
| 97 | + return d |
| 98 | + break |
| 99 | + num = int(len(d) / length) |
| 100 | + |
| 101 | +dt = sample[:] |
| 102 | +shell_sort(dt) |
| 103 | +print('shell_sort: ' + str(assert_list(dt, sample_sorted))) |
| 104 | + |
| 105 | +def merge_sort(lst): # 分治发的典型应用,大问题拆分成小问题,逐个击破,之后将结果合并 |
| 106 | + half_index = int(len(lst) / 2) # 将数组拆分 |
| 107 | + d0 = lst[:half_index] |
| 108 | + d1 = lst[half_index:] |
| 109 | + |
| 110 | + if len(d0) > 1: |
| 111 | + d0 = merge_sort(d0) |
| 112 | + if len(d1) > 1: |
| 113 | + d1 = merge_sort(d1) |
| 114 | + |
| 115 | + index = 0 |
| 116 | + for i in range(len(d1)): |
| 117 | + state = 1 |
| 118 | + for j in range(index, len(d0)): |
| 119 | + if d1[i] < d0[j]: |
| 120 | + state = 0 |
| 121 | + index = j + 1 |
| 122 | + d0.insert(j, d1[i]) |
| 123 | + break |
| 124 | + if state == 1: # 如果大于d0这个队列的所有值,那么直接extend所有数据 |
| 125 | + d0.extend(d1[i:]) |
| 126 | + break |
| 127 | + return d0 |
| 128 | + |
| 129 | +dt = merge_sort(sample[:]) |
| 130 | +print('merge_sort: ' + str(assert_list(dt, sample_sorted))) |
| 131 | + |
| 132 | +def quick_sort(lst): |
| 133 | + d = [[], [], []] |
| 134 | + d_pivot = lst[-1] # 因为是乱序数组,所以第几个都是可以的,理论上是一样的 |
| 135 | + for i in lst: |
| 136 | + if i < d_pivot: # 小于基准值的放在前 |
| 137 | + d[0].append(i) |
| 138 | + elif i > d_pivot: # 大于基准值的放在后 |
| 139 | + d[2].append(i) |
| 140 | + else: # 等于基准值的放在中间 |
| 141 | + d[1].append(i) |
| 142 | + |
| 143 | + # print(d[0], d[1], d[2]) |
| 144 | + if len(d[0]) > 1: # 大于基准值的子数组,递归 |
| 145 | + d[0] = quick_sort(d[0]) |
| 146 | + if len(d[2]) > 1: # 小于基准值的子数组,递归 |
| 147 | + d[2] = quick_sort(d[2]) |
| 148 | + |
| 149 | + d[0].extend(d[1]) |
| 150 | + d[0].extend(d[2]) |
| 151 | + return d[0] |
| 152 | + |
| 153 | +dt = quick_sort(sample[:]) |
| 154 | +print('quick_sort: ' + str(assert_list(dt, sample_sorted))) |
| 155 | + |
| 156 | +def counting_sort(lst): |
| 157 | + d_max = 0 |
| 158 | + d_min = 0 |
| 159 | + for i in lst: |
| 160 | + if d_max<i: |
| 161 | + d_max = i |
| 162 | + if d_min>i: |
| 163 | + d_min = i |
| 164 | + |
| 165 | + d1 = {} |
| 166 | + for i in lst: |
| 167 | + if i in d1.keys(): |
| 168 | + d1[i] += 1 |
| 169 | + else: |
| 170 | + d1[i] = 1 |
| 171 | + |
| 172 | + d2 = [] |
| 173 | + for i in range(d_min,d_max+1): |
| 174 | + if i in d1.keys(): |
| 175 | + for j in range(d1[i]): |
| 176 | + d2.append(i) |
| 177 | + return d2 |
| 178 | + |
| 179 | +dt = counting_sort(sample[:]) |
| 180 | +print('counting_sort: ' + str(assert_list(dt, sample_sorted))) |
| 181 | + |
| 182 | +def bucket_sort(lst): |
| 183 | + d1 = [[] for x in range(10)] |
| 184 | + for i in lst: |
| 185 | + d1[int(i/10)].append(i) |
| 186 | + for i in range(len(d1)): |
| 187 | + if d1[i] != []: |
| 188 | + d2 = [[] for x in range(10)] |
| 189 | + for j in d1[i]: |
| 190 | + d2[j%10].append(j) |
| 191 | + d1[i] = d2 |
| 192 | + d3 = [] |
| 193 | + for i in d1: |
| 194 | + if i: |
| 195 | + for j in i: |
| 196 | + if j: |
| 197 | + for k in j: |
| 198 | + if k: |
| 199 | + d3.append(k) |
| 200 | + return d3 |
| 201 | + |
| 202 | +dt = bucket_sort(sample[:]) |
| 203 | +print('bucket_sort: ' + str(assert_list(dt, sample_sorted))) |
| 204 | + |
| 205 | +def radix_sort(lst): |
| 206 | + d1 = [[] for x in range(10)] |
| 207 | + |
| 208 | + # 第一次 最小位次排序 |
| 209 | + for i in lst: |
| 210 | + d1[i % 10].append(i) |
| 211 | + d0_1 = [] |
| 212 | + for i in d1: |
| 213 | + if i: |
| 214 | + for j in i: |
| 215 | + d0_1.append(j) |
| 216 | + |
| 217 | + # 第二次 次低位排序 |
| 218 | + d2 = [[] for x in range(10)] |
| 219 | + for i in d0_1: |
| 220 | + d2[int(i/10)].append(i) |
| 221 | + d0_2 = [] |
| 222 | + for i in d2: |
| 223 | + if i: |
| 224 | + for j in i: |
| 225 | + d0_2.append(j) |
| 226 | + return d0_2 |
| 227 | + |
| 228 | +dt = radix_sort(sample[:]) |
| 229 | +print('radix_sort: ' + str(assert_list(dt, sample_sorted))) |
| 230 | + |
| 231 | +# Python 堆排序 - 菜鸟教程 |
| 232 | +# https://www.runoob.com/python3/python-heap-sort.html |
| 233 | + |
| 234 | +def heapify(arr, n, i): |
| 235 | + largest = i |
| 236 | + l = 2 * i + 1 # left = 2*i + 1 |
| 237 | + r = 2 * i + 2 # right = 2*i + 2 |
| 238 | + if l < n and arr[i] < arr[l]: |
| 239 | + largest = l |
| 240 | + if r < n and arr[largest] < arr[r]: |
| 241 | + largest = r |
| 242 | + if largest != i: |
| 243 | + arr[i],arr[largest] = arr[largest],arr[i] # 交换 |
| 244 | + heapify(arr, n, largest) |
| 245 | + |
| 246 | +def heap_sort(arr): |
| 247 | + n = len(arr) |
| 248 | + # Build a maxheap. |
| 249 | + for i in range(n, -1, -1): |
| 250 | + heapify(arr, n, i) |
| 251 | + # 一个个交换元素 |
| 252 | + for i in range(n-1, 0, -1): |
| 253 | + arr[i], arr[0] = arr[0], arr[i] # 交换 |
| 254 | + heapify(arr, i, 0) |
| 255 | + |
| 256 | +dt = sample[:] |
| 257 | +heap_sort(dt) |
| 258 | +print('heap_sort: ' + str(assert_list(dt, sample_sorted))) |
0 commit comments