[python] Top ten sorting algorithms

1. Sorting algorithm

This article introduces the ten most common sorting algorithms: selection sort, bubble sort, insertion sort, merge sort, bucket sort, counting sort, radix sort, (random) quick sort, Hill sort, and heap sort algorithms.

1.1 Selection sorting

In each cycle, the smallest one is selected from the remaining queue and placed at the front of the remaining queue (or the largest one is selected from the remaining queue and placed at the end of the remaining queue, which will not be described in detail below):

# 选择排序
def SelectionSort(l: list):
    for i in range(len(l) - 1):
        mini = i
        for j in range(i + 1, len(l)):
            if l[j] < l[mini]:
                mini = j
        if mini != i:
            l[i], l[mini] = l[mini], l[i]

1.2 Bubble sort

In each round of loop, compare the unsorted sequence with the next number one by one, and put the larger number at the end:

# 冒泡排序
def BubbleSort(L: list):
    for i in range(len(L) - 1):
        for j in range(len(L) - 1 - i):
            if L[j] > L[j + 1]:
                L[j], L[j + 1] = L[j + 1], L[j]

1.3 Insertion sort

The insertion sort algorithm can be modified directly on the original list and move the numbers backward in the sorted sequence until the newly added data can be stored:

# 插入排序
def InsertionSort(L: list):
    for i in range(1, len(L)):
        if L[i] < L[i - 1]:
            j = i - 1
            tmp = L[i]
            while j >= 0:
                if L[j] > tmp:
                    L[j + 1] = L[j]
                    j -= 1
                else:
                    break
            L[j + 1] = tmp

1.4 Merge sort

In merge sort, we use two sub-functions MergeRecursion and Merge.
MergeRecursion is used to recursively split the array into two columns until each column has only one element (at this point the array can be considered ordered), and then call Merge to merge the two ordered lists into one ordered list.

# 归并排序
# 直接调用 MergeRecursion 函数,传入列表的首尾序列
def MergeSort(L: list):
    MergeRecursion(L, 0, len(L) - 1)


# 对列表进行二分拆分成有序的原子序列,然后调用 Merge 函数进行合并
def MergeRecursion(L: list, start, end):
    if start == end:
        return
    mid = (start + end) // 2
    MergeRecursion(L, start, mid)
    MergeRecursion(L, mid + 1, end)
    Merge(L, start, mid, end)


# 将两个有序的列表 L[start:mid] 和 L[mid+1:end] 融合成一个有序列表
def Merge(L: list, start, mid, end):
    new = []
    l = start
    r = mid + 1
    while l <= mid and r <= end:
        if L[l] <= L[r]:
            new.append(L[l])
            l += 1
        else:
            new.append(L[r])
            r += 1
    if l == mid + 1:
        new.extend(L[r:end + 1])
    else:
        new.extend(L[l:mid + 1])
    L[start:end + 1] = new[:]

1.5 Bucket sorting

Bucket sorting is to store data into different buckets first. The number of buckets, bucket_count, can be set by yourself. In-bucket sorting requires calling other sorting algorithms (such as selection sorting SelectionSort) to implement.

# 桶排序排序
def BucketSort(L:list):
    bucket_count = 3
    Buckets = [[] for i in range(bucket_count)]
    mini = min(L)
    maxi = max(L)
    length = (maxi - mini + bucket_count) // bucket_count

    for num in L:
        index = (num - mini) // length
        Buckets[int(index)].append(num)

    for bucket in Buckets:
        SelectionSort(bucket)

    sorted_buckets = [i for bucket in Buckets for i in bucket]
    L[:] = sorted_buckets[:]

The algorithm uses generative expressions to simplify the code.

1.6 Counting sort

Counting sorting uses a new list to record the number of times each number appears in the interval from the minimum value mini to the maximum value maxi, and then restores it to an ordered sequence by counting.
Obviously, this type of method is suitable for sorting integer, densely distributed data.

# 计数排序
def CountingSort(L: list):
    mini = min(L)
    maxi = max(L)
    new = [0 for i in range(mini, maxi + 1)]
    for num in L:
        new[num - mini] += 1
    # index = 0
    # for i in range(len(new)):
    #     while new[i] > 0:
    #         L[index] = mini + i
    #         index += 1
    #         new[i] -= 1
    L[:] = [mini + i for i in range(len(new)) for j in range(new[i])]

Generative expressions are used again to simplify the annotation part.

1.7 Radix sort

Radix sorting is essentially a bucket sorting, which is divided into ten buckets from 0 to 9 according to the number of digits, and then sorted according to the digits of tens, hundreds, millions, and millions.
This method is suitable for sorting integer data.
When there are negative numbers, you can sort by subtracting the smallest negative number uniformly, and then add it back uniformly afterwards.

# 基数排序
def RadixSort(L: list):
    base = 1
    maxi = max(L)
    while base < maxi:
        Buckets = [[] for i in range(10)]
        for num in L:
            index = num // base % 10
            Buckets[index].append(num)
        # i = 0
        # for bucket in Buckets:
        #     for num in bucket:
        #         L[i] = num
        #         i += 1
        L[:] = [num for bucket in Buckets for num in bucket]
        base *= 10

Generative expressions are used here again .

1.8 Quick sort

quicksort algorithmUse the first number in the sequence as the pivot pivot, and place the numbers greater than it and the numbers smaller than it on both sides of it; then recursively use the above operations on the arrays on both sides until each number has been pivoted.
Similar to merge sort, QuickSort passes in the to-be-processed list; QuickRecursion implements recursive splitting; QuickSortPivot implements how to split the data in each step and returns the position where the benchmark number should be (for recursive splitting).

# 快速排序算法
def QuickSort(L: list):
    QuickRecursion(L, 0, len(L) - 1)


def QuickRecursion(L: list, start, end):
    if start >= end:
        return
    pivot = QuickSortPivot(L, start, end)
    QuickRecursion(L, start, pivot - 1)
    QuickRecursion(L, pivot + 1, end)


def QuickSortPivot(L: list, start, end):
    pivot = start
    j = start + 1
    for i in range(start + 1, end + 1):
        if L[i] < L[pivot]:
            L[i], L[j] = L[j], L[i]
            j += 1
    L[pivot], L[j - 1] = L[j - 1], L[pivot]
    pivot = j - 1
    return pivot

Random quick sort algorithmIt is roughly similar to the quick sort algorithm. The difference is that compared with the QuickSortPivot function, the RandomQuickSortPivot function adds random numbers in the first two lines, so that the selected benchmark is random each time.

# 随机快速排序
def RandomQuickSort(L: list):
    RandomQuickRecursion(L, 0, len(L) - 1)


def RandomQuickRecursion(L: list, start, end):
    if start >= end:
        return
    pivot = RandomQuickSortPivot(L, start, end)
    RandomQuickRecursion(L, start, pivot - 1)
    RandomQuickRecursion(L, pivot + 1, end)


def RandomQuickSortPivot(L: list, start, end):
    import random
    randIndex = random.randint(start, end)
    L[start], L[randIndex] = L[randIndex], L[start]
    pivot = start
    j = start + 1
    for i in range(start + 1, end + 1):
        if L[i] < L[pivot]:
            L[i], L[j] = L[j], L[i]
            j += 1
    L[pivot], L[j - 1] = L[j - 1], L[pivot]
    pivot = j - 1
    return pivot

1.9 Hill sorting

Hill sort is an improved insertion sort.
Hill sorting divides the data into n/2 groups, and the data interval within the group is n/2, and then performs insertion sorting on these groups respectively; then the data is
divided into n/4 groups, and the data interval within the group is n/4. The same as above, these groups are divided into n/2 groups. The groups are inserted and sorted separately;
repeat the above steps until the data interval within the group is less than 1, and only one group is left.

# 希尔排序
def ShellSort(L:list):
    n = len(L)
    gap = n // 2
    while gap > 0:
        for i in range(gap,n):
            tmp = L[i]
            j = i
            while j >= gap:
                if tmp < L[j-gap]:
                    L[j] = L[j - gap]
                else:
                    break
                j -= gap
            L[j] = tmp
        gap //= 2

1.10 Heap sort

Heap sort takes advantage of the properties of binary trees. By exchanging node values, you can elect the largest element at the top of the heap and put it at the end of the list; then repeat the election and postposition to achieve sorting.
The maxHeapify function is used to elect the maximum value, and HeapSort is used to post-post the maximum value, and perform election and post-post operations on the remaining data in a loop.
The heap in the algorithm is actually implemented using lists. It should be noted that the starting index of the first element of the heap is 1, so an element needs to be filled in front of the list.

# 堆排序
def HeapSort(L: list):
    heap = [None] + L  # heap 从 1 开始遍历,list 从 0 开始遍历,通过填补实现对接
    root = 1
    for i in range(len(heap) // 2, root - 1, -1):
        maxHeapify(heap, i, len(heap) - 1)
    for i in range(len(heap) - 1, root, -1):
        heap[i], heap[root] = heap[root], heap[i]
        maxHeapify(heap, root, i - 1)
    L[:] = heap[root:]


def maxHeapify(heap: list, start, end):
    son = start * 2
    while son <= end:
        if son + 1 < end and heap[son + 1] > heap[son]:
            son += 1
        if heap[son] > heap[start]:
            heap[start], heap[son] = heap[son], heap[start]
            start, son = son, son * 2
        else:
            break

2. Complete code

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName  :sort_algorithms.py
# @Time      :2023/7/25 14:35
# @Author    :Carl.Zhang
# Function   :Eleven most used sort algorithms.

# 选择排序
def SelectionSort(L: list):
    for i in range(len(L) - 1):
        mini = i
        for j in range(i + 1, len(L)):
            if L[j] < L[mini]:
                mini = j
        if mini != i:
            L[i], L[mini] = L[mini], L[i]


# 冒泡排序
def BubbleSort(L: list):
    for i in range(len(L) - 1):
        for j in range(len(L) - 1 - i):
            if L[j] > L[j + 1]:
                L[j], L[j + 1] = L[j + 1], L[j]


# 插入排序
def InsertionSort(L: list):
    for i in range(1, len(L)):
        if L[i] < L[i - 1]:
            j = i - 1
            tmp = L[i]
            while j >= 0:
                if L[j] > tmp:
                    L[j + 1] = L[j]
                    j -= 1
                else:
                    break
            L[j + 1] = tmp


# 插入排序2
def InsertionSort2(L: list):
    for i in range(1, len(L)):
        if L[i] < L[i - 1]:
            for j in range(i):
                if L[i] < L[j]:
                    tmp = L[i]
                    for k in range(i, j, -1):
                        L[k] = L[k - 1]
                    L[j] = tmp
                    break


# 归并排序
# 直接调用 MergeRecursion 函数,传入列表的首尾序列
def MergeSort(L: list):
    MergeRecursion(L, 0, len(L) - 1)


# 对列表进行二分拆分成有序的原子序列,然后调用 Merge 函数进行合并
def MergeRecursion(L: list, start, end):
    if start == end:
        return
    mid = (start + end) // 2
    MergeRecursion(L, start, mid)
    MergeRecursion(L, mid + 1, end)
    Merge(L, start, mid, end)


# 将两个有序的列表 L[start:mid] 和 L[mid+1:end] 融合成一个有序列表
def Merge(L: list, start, mid, end):
    new = []
    l = start
    r = mid + 1
    while l <= mid and r <= end:
        if L[l] <= L[r]:
            new.append(L[l])
            l += 1
        else:
            new.append(L[r])
            r += 1
    if l == mid + 1:
        new.extend(L[r:end + 1])
    else:
        new.extend(L[l:mid + 1])
    L[start:end + 1] = new[:]


# 桶排序排序
def BucketSort(L: list):
    bucket_count = 3
    Buckets = [[] for i in range(bucket_count)]
    mini = min(L)
    maxi = max(L)
    length = (maxi - mini + bucket_count) // bucket_count

    for num in L:
        index = (num - mini) // length
        Buckets[int(index)].append(num)

    for bucket in Buckets:
        SelectionSort(bucket)

    sorted_buckets = [i for bucket in Buckets for i in bucket]
    L[:] = sorted_buckets[:]


# 计数排序
def CountingSort(L: list):
    mini = min(L)
    maxi = max(L)
    new = [0 for i in range(mini, maxi + 1)]
    for num in L:
        new[num - mini] += 1
    # index = 0
    # for i in range(len(new)):
    #     while new[i] > 0:
    #         L[index] = mini + i
    #         index += 1
    #         new[i] -= 1
    L[:] = [mini + i for i in range(len(new)) for j in range(new[i])]


# 基数排序
def RadixSort(L: list):
    base = 1
    maxi = max(L)
    while base < maxi:
        Buckets = [[] for i in range(10)]
        for num in L:
            index = num // base % 10
            Buckets[index].append(num)
        # i = 0
        # for bucket in Buckets:
        #     for num in bucket:
        #         L[i] = num
        #         i += 1
        L[:] = [num for bucket in Buckets for num in bucket]
        base *= 10


# 快速排序算法
def QuickSort(L: list):
    QuickRecursion(L, 0, len(L) - 1)


def QuickRecursion(L: list, start, end):
    if start >= end:
        return
    pivot = QuickSortPivot(L, start, end)
    QuickRecursion(L, start, pivot - 1)
    QuickRecursion(L, pivot + 1, end)


def QuickSortPivot(L: list, start, end):
    pivot = start
    j = start + 1
    for i in range(start + 1, end + 1):
        if L[i] < L[pivot]:
            L[i], L[j] = L[j], L[i]
            j += 1
    L[pivot], L[j - 1] = L[j - 1], L[pivot]
    pivot = j - 1
    return pivot


# 随机快速排序
def RandomQuickSort(L: list):
    RandomQuickRecursion(L, 0, len(L) - 1)


def RandomQuickRecursion(L: list, start, end):
    if start >= end:
        return
    pivot = RandomQuickSortPivot(L, start, end)
    RandomQuickRecursion(L, start, pivot - 1)
    RandomQuickRecursion(L, pivot + 1, end)


def RandomQuickSortPivot(L: list, start, end):
    import random
    randIndex = random.randint(start, end)
    L[start], L[randIndex] = L[randIndex], L[start]
    pivot = start
    j = start + 1
    for i in range(start + 1, end + 1):
        if L[i] < L[pivot]:
            L[i], L[j] = L[j], L[i]
            j += 1
    L[pivot], L[j - 1] = L[j - 1], L[pivot]
    pivot = j - 1
    return pivot


# 希尔排序
def ShellSort(L: list):
    n = len(L)
    gap = n // 2
    while gap > 0:
        for i in range(gap, n):
            tmp = L[i]
            j = i
            while j >= gap:
                if tmp < L[j - gap]:
                    L[j] = L[j - gap]
                else:
                    break
                j -= gap
            L[j] = tmp
        gap //= 2


# 堆排序
def HeapSort(L: list):
    heap = [None] + L  # heap 从 1 开始遍历,list 从 0 开始遍历,通过填补实现对接
    root = 1
    for i in range(len(heap) // 2, root - 1, -1):
        maxHeapify(heap, i, len(heap) - 1)
    for i in range(len(heap) - 1, root, -1):
        heap[i], heap[root] = heap[root], heap[i]
        maxHeapify(heap, root, i - 1)
    L[:] = heap[root:]


def maxHeapify(heap: list, start, end):
    son = start * 2
    while son <= end:
        if son + 1 < end and heap[son + 1] > heap[son]:
            son += 1
        if heap[son] > heap[start]:
            heap[start], heap[son] = heap[son], heap[start]
            start, son = son, son * 2
        else:
            break


if __name__ == "__main__":
    l = [34, 3, 16, 8, 2, 23, 12, 9, 21, 5]
    # SelectionSort(l)
    # BubbleSort(l)
    # InsertionSort2(l)
    # print(InsertionSort(l))
    # MergeSort(l)
    # BucketSort(l)
    # CountingSort(l)
    # RadixSort(l)
    # QuickSort(l)
    # RandomQuickSort(l)
    # ShellSort(l)
    HeapSort(l)
    print(l)

Reference: @ where is the hero coming out of the B station video
For more usage methods and applications of python, please pay attention to subsequent updates~

Guess you like

Origin blog.csdn.net/weixin_44844635/article/details/131917336