zoukankan      html  css  js  c++  java
  • 十大经典排序算法(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/onepixel/

    参考文档出处:

    十大经典排序算法(动图演示) https://www.cnblogs.com/onepixel/articles/7674659.html

    分治算法 https://www.cnblogs.com/chentingk/p/5671808.html

    堆 https://www.cnblogs.com/chenweichu/articles/5710567.html

  • 相关阅读:
    搜集整理一些Cron表达式例子
    正确处理下载文件时HTTP头的编码问题(Content-Disposition)
    SpringMVC之RequestContextHolder分析
    协变、逆变与不变:数组、泛型、与返回类型
    用java实现一个简单的单用户登陆功能的思路
    为什么要进行URL编码
    spring mvc&mybatis搭配使用心得
    css(二)
    css(一)
    html
  • 原文地址:https://www.cnblogs.com/Mufasa/p/10527387.html
Copyright © 2011-2022 走看看