Python实现10种排序算法。通过Java版改写,可能有句法不那么Python的问题。另外,第10个还没写出来,有空再补上。

  • Bubble Sort 冒泡排序

比较相邻的元素,如果第一个比第二个大,就交换他们。对每一对相邻元素做相同的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数。针对所有的元素重复以上的步骤,除了最后一个重复以上步骤,直到排序完成.

def bubble_sort(arr):
    for i in range(len(arr) - 1):
        for j in range(len(arr) - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    print(arr)
    return

list1 = [1, 23, 43, 2, 3, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
bubble_sort(list1)
  • Selection Sort 选择排序

首先从未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后从剩余未排序元素中继续寻 找最小(大)元素,移动到已排序末尾。以此类推,直到所有元素均排序完毕

def selection_sort(arr):
    for i in range(len(arr) - 1):
        min_index = i
        for j in range(i + 1, len(arr)):
            if arr[j] < arr[min_index]:
                min_index = j
        arr[i], arr[min_index] = arr[min_index], arr[i]
    return arr

list1 = [1, 23, 43, 2, 3, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
print(selection_sort(list1))
  • Insertion Sort 插入排序

通过构建有序序列,对未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入

def insertion_sort(arr):
    for i in range(1, len(arr)):
        previous = i - 1
        current = arr[i]
        while previous >= 0 and arr[previous] > current:
            arr[previous + 1] = arr[previous]
            previous -= 1
        arr[previous+1] = current
    return arr

list1 = [1, 23, 43, 2, 3, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57,24, 723]
print(insertion_sort(list1))
  • Shell Sort 希尔排序

简单插入排序的改进版,它与插入排序不同之处在于,他会优先比较距离较远的元素希尔排序又叫“缩小增量排序”

def shell_sort(arr):
    gap = len(arr) // 2
    while gap > 0:
        for i in range(gap, len(arr)):
            while i - gap >= 0 and arr[i] < arr[i - gap]:
                arr[i], arr[i-gap] = arr[i - gap], arr[i]
                i -= gap
        gap = gap // 2
    return arr

list1 = [1, 23, 43, 2, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
print(shell_sort(list1))
  • Merge Sort 归并排序

将已有序的子序列合并,得到完整有序的序列;即先使每个子序列有序,再使子序列段间有序

def merge_sort(arr):
    if len(arr) < 2:
        return arr
    middle = len(arr) // 2
    left = merge_sort(arr[:middle])
    right = merge_sort(arr[middle:])
    return merge(left, right)

def merge(a, b):
    aux = []
    while len(a) > 0 and len(b) > 0:
        if a[0] <= b[0]:
            aux.append(a.pop(0))
        else:
            aux.append(b.pop(0))
    else:
        if len(a) == 0:
            aux += b
        else:
            aux += a
    return aux


list1 = [1, 23, 43, 2, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
print(merge_sort(list1))
  • Quick Sort 快速排序

在序列中选择一个基准点,然后分别从序列的两段扫描,设两个指示标志。从后半部分开始,如果有元素 比该基准点小,就交换两个指示标志位置的值,然后从前半部分开始扫描,发现有元素大于基准点的值,就交换两个指示标志位置的值,如此往复循环,直到俩指示标志的前者与后者相当或前者大于后者,交换 位置,一次排序完成了。以后采用递归的方式,分别对前半部分和后半部分排序

def quick_sort(arr):
    return q_sort(arr, 0, len(arr) - 1)

def q_sort(arr, lo, hi):
    if lo < hi:
        pivot = partition(arr, lo, hi)
        q_sort(arr, lo, pivot - 1)
        q_sort(arr, pivot + 1, hi)
    return arr

def partition(arr, lo, hi):
    pivot_value = arr[hi]
    i = lo - 1
    for j in range(lo, hi):
        if arr[j] <= pivot_value:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    arr[i + 1], arr[hi] = arr[hi], arr[i + 1]
    return i + 1

list1 = [1, 23, 43, 2, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
print(quick_sort(list1))
def quick_sort(arr, lo, hi):
    if lo > hi:
        return
    stack = []
    stack.append(lo)
    stack.append(hi)
    while stack:
        lo = stack.pop(0)
        hi = stack.pop(0)
        if hi - lo <= 0:
            continue
        pivot = arr[hi]
        i = lo - 1
        for j in range(lo, hi):
            if arr[j] <= pivot:
                i += 1
                arr[i], arr[j] = arr[j], arr[i]
        arr[i + 1], arr[hi] = arr[hi], arr[i + 1]
        stack.extend([lo, i, i + 2, hi])
  • Heap Sort 堆排序

堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或大于)它的父节点。
将初始待排序关键字序列(R1,R2,R3,...Rn)构成一顶堆,此堆为初始的无序区:将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,R3,...Rn-1)和新的有序区,且满足R[1,2,3,...,n-1] <= R[n];由于交换后的新的堆顶R[1]可能违反堆的性质,因为需要对当前无序区(R1,R2,R3,...,Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2,R3,...,Rn-2)和新的有序区(Rn-1,Rn)
不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成

def heapify(arr, i, k):
    # 构建堆的规则
    j = 2 * i
    while j <= k:
        if j < k and arr[j] < arr[j + 1]:
            j += 1
        if arr[i] >= arr[j]:
            break
        arr[i], arr[j] = arr[j], arr[i]
        i = j
        j *= 2

def heap_sort(arr):
    # 从最后一个有子节点的节点开始构建堆
    last = len(arr) // 2 - 1
    for i in range(last, -1, -1):
        heapify(arr, i, len(arr) - 1)

    # 将最大的数放在堆的最后一个位置,并将剩余部分重新构建堆
    for k in range(len(arr) - 1, 0, -1):
        arr[0], arr[k] = arr[k], arr[0]
        heapify(arr, 0, k - 1)

if __name__ == "__main__":
    arr = [1, 23, 43, 2, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
    heap_sort(arr)
    print(arr)

list1 = [1, 23, 43, 2, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
  • Counting Sort 计数排序

计数排序不是基于比较的排序算法,其核心在于将输入的数据 值转化为键存储在额外开辟的数组空间中。
作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数,找出待排序的数组中最大和最小的元素;统计数组中每个值为i的元素出现的个数,存入数组C的第i项;对所有的计数累加,反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

def counting_sort(arr, largest):
    bucket = [0]*(largest + 1)
        sorted_index = 0

    for i in range(len(arr)):
        bucket[arr[i]] = arr.count(arr[i])

    for j in range(len(bucket)):
        while bucket[j] > 0:
            arr[sorted_index] = j
            sorted_index += 1
            bucket[j] -= 1
   return arr

list1 = [1, 23, 43, 2, 24, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
print(counting_sort(list1, 4452))
  • Bucket Sort 桶排序

桶排序是计数排序的升级版。它利用函数的映射关系,高效与否的关键在于这个映射函数的确定,假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶分别排序。每个桶里的排序,有可能再使用比的排序算法,或是以递归方式继续使用桶排序

  • 设置一个定量的数组当做空桶
  • 遍历输入数据,并且把数据一个一个放到对应的桶里
  • 对每个不是空的桶进行排序
  • 从不是空的桶里把排好序的数据拼接起来
def bucket_sort(arr, bucket_size):
    if len(arr) == 0:
        return arr

    min_value = arr[0]
    max_value = arr[0]
    for i in range(len(arr)):
        if arr[i] < min_value:
            min_value = arr[i]
        if arr[i] > max_value:
            max_value = arr[i]

    # bucket_size = 5
    bucket_count = (max_value - min_value) // bucket_size + 1
    buckets = [[]*i for i in range(bucket_count)]

    for i in range(len(arr)):
        buckets[(arr[i] - min_value) // bucket_size].append(arr[i])
    # print(buckets)

    arr = []
    for i in range(len(buckets)):
        insertion_sort(buckets[i])
        for j in range(len(buckets[i])):
            arr.append(buckets[i][j])

    # print(buckets)

    return arr


list1 = [1, 23, 43, 2, 24, 54, 6, 34, 81, 99, 342, 3, 4452, 344, 234, 44, 55, 67, 57, 24, 723]
print(bucket_sort(list1, 50))
  • TBC