[Python]7种基础排序算法-Python实现

Basic 7 Algorithms in Python

Bubble Sort(冒泡排序)

Main Idea: use two loops to iterate data array, find the maximum, and throw it to the end.
(两次循环,每次选大的放在后面,重复,直到没有数据)

Feature: Stable O(n^2)

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

Alternative: add a flag into outter loop, reducing the # of comparison.
(通过在外循环设置标志位,可以减少比较的次数,但意义不大)

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

Test Code Link

Selection Sort(选择排序)

Main Idea: use two loops to iterate data array, find the minimum, and insert it at the beginning.
(两次循环,每次选小的放在前面,重复,直到没有数据)

Feature: Unstable O(n^2)

    def selection_sort(arr):
        for i in range(len(arr)):
            for j in range(i, len(arr)):
                if arr[i] > arr[j]:
                    arr[i], arr[j] = arr[j], arr[i]
        return arr

Alternative: store the current index, reducing the # of switching.
(通过在外循环存储的索引, 减少数据交换的次数)

    def selection_sort(arr):
        for i in range(len(arr)):
            min_idx = i
            for j in range(i, len(arr)):
                if arr[min_idx] > arr[j]:
                    min_idx = j
            if i != min_idx:
                arr[i], arr[min_idx] = arr[min_idx], arr[i]
        return arr

Test Code Link

Insertion Sort(插入排序)

Main Idea: use two loops to iterate data array simultaneously, insert a new data item into sorted results at an appropriate location. and push the rest data behind this location as a whole.
(两次循环,将无序数据插入到已经有序的结果中,在插入位置,将后面的数据整体后移,重复,直到没有数据)

Feature: Stable O(n^2)

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

Alternative1: use binary search to find the location where the new element should insert.
(用二分查找,找到需要插入的位置)

    def insertion_sort(arr):
        for i in range(len(arr)):
            current = arr[i]
            low, high = 0, i - 1
            while low <= high:
                mid = int((low + high) / 2)
                if current < arr[mid]:
                    high = mid - 1
                else:
                    low = mid + 1
            for j in range(i, low, -1):
                arr[j] = arr[j - 1]
            arr[low] = current
        return arr

Alternative2: use a descreasing number as a gap, to accelerate seaching process.
(用一个递减的数值,作为间隔,每轮中,比较每个间隔对应的值,结合直接插入排序。 还有另外一个名字-希尔排序)

    def insertion_sort(arr):
        gap = len(arr) // 2
        while gap >= 1:
            for i in range(gap, len(arr)):
                end_val = arr[i]
                front_idx = i - gap
                while front_idx >= 0 and arr[front_idx] > end_val:
                    arr[front_idx + gap] = arr[front_idx]
                    front_idx -= gap
                arr[front_idx + gap] = end_val
            gap //= 2
        return arr

Feature: Unstable O(nlogn)

Test Code Link

Merge Sort(归并排序)

Main Idea: a classic sorting solution using divide-and-conquer. split data into pieces, and sort those small data and combine all of them.
(递归地把当前序列平均分成两半, 分到只剩一个元素的时候, 停止切分开始进行两两排序,当解决完N个小问题之后,就可以把结果再拼装起来)

Feature: Stable O(nlogn)

    def merge(left, right):
        res = []
        while left and right:
            min_val = left.pop(0) if left[0] < right[0] else right.pop(0)
            res.append(min_val)
        res += left if left else right
        return res

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

Alternative: instead, use a recursion method to write this algorithm, we can also use an iteration way.
(除了使用递归方式去实现归并排序,也可以使用迭代的思路去实现)

    def merge(arr, low, mid, high):
        left = arr[low: mid]
        right = arr[mid: high]
        res = []
        while left and right:
            min_val = left.pop(0) if left[0] < right[0] else right.pop(0)
            res.append(min_val)
        res += left if left else right
        arr[low: high] = res

    def merge_sort(arr):
        sub_length = 1
        while sub_length < len(arr):
            low = 0
            while low < len(arr):
                mid = low + sub_length
                high = min(low + 2 * sub_length, len(arr))
                if mid < high:
                    merge(arr, low, mid, high)
                low += 2 * sub_length
            sub_length *= 2
        return arr

Test Code Link1 | Test Code Link2

Quick Sort(快速排序)

Main Idea: another classic solution using divide-and-conquer. choose an item as pivot, split data into two part, one part is less than pivot, the rest will greater than pivot. continue doing this until no data.
(通过设置枢轴的方式,将原始数据分成两个部分,将两个小部分排序并把结果最后合起来,重复切分,直到没有数据)

Feature: Unstable O(nlogn)

    def quick_sort(arr, left, right):
        if left < right:
            pivot = arr[right]
            low, high = left, right
            while left< right:
                while left < right and arr[left] < pivot:
                    left += 1
                arr[right] = arr[left]

                while left < right and arr[right] > pivot:
                    right -= 1
                arr[left] = arr[right]

            arr[left] = pivot
            quick_sort(arr, low, left - 1)
            quick_sort(arr, left + 1, high)
        return arr

Alternative1: the most easy way to do quick sorting.
(我认为是最容易理解的一种实现方式)

    def quick_sort(arr):
        if arr:
            pivot = arr[0]
            less = [x for x in arr if x < pivot]
            great = [x for x in arr if x > pivot]
            return quick_sort(less) + [pivot] + quick_sort(great)
        else:
            return []

Alternative2: 1. return the index of pivot. 2. split the data.
(设置一个函数返回枢轴的位置,以此位置切分原始数据,一直迭代下去)

    def quick_sort(arr, left, right):
        if left < right:
            pivot_idx = split(arr, left, right)
            quick_sort(arr, left, pivot_idx - 1)
            quick_sort(arr, pivot_idx + 1, right)
        return arr

    def split(arr, left, right):
        pivot = arr[right]
        i = left - 1
        for j in range(left, right):
            if arr[j] <= pivot:
                i += 1
                arr[i], arr[j] = arr[j], arr[i]
        arr[i + 1], arr[right] = pivot, arr[i + 1]
        return i + 1

Test Code Link1 | Test Code Link2

Counting Sort(计数排序)

Main Idea: convert data item into key-value pair, the iterate the keys.
(将输入的数据值转化为键存储在额外开辟的桶空间中,然后遍历生成的桶,从小到大依次拿出来就是结果)

Feature: Stable O(n + k)

    def bucket_sort(arr):
        buckets = [0] * ((max(arr) - min(arr)) + 1)
        for i in range(len(arr)):
            buckets[arr[i] - min(arr)] += 1
        res = []
        for i in range(len(buckets)):
            if buckets[i] != 0:
                res += [i + min(arr)] * buckets[i]
        return res

Waning: to be honest, no one will use this to solve real-world problem. will waste lot of memory space.
(没什么人会用)

Test Code Link

Radix Sort(基数排序)

Main Idea: distribute the data into buckets based on their unit digit. and collect all of them, and then redistribute them based on their tens digit, continue doing this way.
(依次用原始数据各项的个十百等数位进行映射,每次映射后,再将桶里的数据依次提出来,覆盖表原来的数据,重复下去直到所有数位都用完)

Feature: Stable O(n*k)

    def radix_sort(arr):
        digit = 0
        max_digit = 1
        max_value = max(arr)

        while 10 ** max_digit < max_value:
            max_digit += 1

        while digit < max_digit:
            buckets = [[] for _ in range(10)]
            for i in arr:
                num = int((i / 10 ** digit) % 10)
                buckets[num].append(i)

            temp_result = []
            for bucket in buckets:
                temp_result.extend(bucket)

            arr = temp_result
            digit += 1
        return arr

Warning: What should I say, same as the counting sort, even though it has some improvement.
(跟计数排序一样,没人用)

Test Code Link

笔记完整代码Github: https://github.com/AaronYang2333/CSCI_570/wiki
持续更新!

原文地址:https://www.cnblogs.com/sight-tech/p/13111555.html