Python - 八大排序算法

一、序言

本文使用Python實現了一些經常使用的排序方法。文章結構以下:node

1.直接插入排序python

2.希爾排序算法

3.冒泡排序shell

4.快速排序數組

5.簡單選擇排序數據結構

6.堆排序app

7.歸併排序dom

8.基數排序ide

上述全部的排序均寫在一個Python自定義類中,做爲成員函數。函數

二、排序方法詳細介紹

1.直接插入排序

直接插入排序(Straight Insertion Sort)是一種最簡單的排序方法,它的基本操做是一個值插入到已排好序的有序表中,從而獲得一個新的、記錄數增1的有序表。以下圖所示:

 

由上圖可知若最初始的有序表即爲數組的第一個元素。用Python實現以下:

def straight_insertion_sort(self, value_list):
    """
    直接插入排序
    :param value_list: 無序列表
    :return:
    """
    return self.__straight_insert(value_list)

@staticmethod
def __straight_insert(value_list):
    sorted_list = []
    sorted_list.append(value_list.pop(0))
    for i in range(0, len(value_list)):
        tail = True  # 是否在尾部插入
        insert_loc = 0
        for j in range(len(sorted_list)):
            if value_list[i] <= sorted_list[j]:
                tail = False
                insert_loc = j
                break
        sorted_list.append(value_list[i])  # 先將值插入尾部
        if not tail:
            # 移動值
            for j in range(len(sorted_list) - 1, insert_loc, -1):
                temp = sorted_list[j]
                sorted_list[j] = sorted_list[j - 1]
                sorted_list[j - 1] = temp
    return sorted_list

2.希爾排序

希爾排序(Shell’s Sort)又稱「縮小增量排序」(Diminishing Incerement Sort),它也是一種數插入排序的方法,但在時間效率上較前面的排序方法有較大的改進。它的基本思想是:先將整個待排記錄序列分割成若干個子序列分別進行直接插入排序,待整個序列中的記錄「基本有序」時,再對全體記錄進行一次直接插入排序。以下圖所示:

 

即根據增量將原序列分割成多個子序列進行直接插入排序。增量應不斷減少,且最後一個增量爲1。用Python實現以下:

def shells_sort(self, value_list):
    """
    希爾排序
    :param value_list: 待排序的無序列表
    :return: 排序後的列表
    """
    gap = len(value_list) // 2
    while gap >= 1:
        i = 0
        while(i + gap) < len(value_list):
            start = i
            gap_list = []
            while start < len(value_list):
                gap_list.append(value_list[start])
                start = start + gap
            gap_list = self.__straight_insert(gap_list)
            start = i
            while start < len(value_list):
                value_list[start] = gap_list.pop(0)
                start += gap
            i += 1
        gap //= 2
    sorted_list = value_list
    return sorted_list

3.冒泡排序

冒泡排序(Bubble Sort)的過程很簡單。首先將第一個記錄的關鍵字和第二個記錄的關鍵字進行比較,若逆序(與須要的順序相反),則將兩個記錄交換之,而後比較第二個記錄和第三個記錄的關鍵字,以此類推。爲第一趟冒泡結束,接着對前n-1個記錄繼續進行上述的過程。這樣重複的過程直至n-1=1結束。排序過程以下所示:

 

用Python實現以下:

@staticmethod
def bubble_sort(value_list):
    """
    冒泡排序
    :param value_list: 待排序的無序列表
    :return: 排序後的列表
    """
    for i in range(len(value_list) - 1):
        for j in range(i + 1, len(value_list)):
            if value_list[i] > value_list[j]:
                value_list[i], value_list[j] = value_list[j], value_list[i]
    sorted_list = value_list
    return sorted_list

4.快速排序

快速排序(Quick Sort)是對冒泡排序的一種改進。它的基本思想是,經過一趟排序將待排記錄分割成獨立的兩部分,其中一部分記錄的關鍵字均比另外一部分記錄的關鍵字小,則可分別對這兩部分記錄繼續進行排序,已達到整個序列有序。其排序思想以下:

首先任意選取一個記錄(一般可選第一個記錄)做爲樞軸,而後按下述原則從新排列記錄:將全部關鍵字較它小的記錄都安置在它的位置以前,將全部關鍵字較它大的記錄都安置在它的位置以後。一趟快速排序的具體作法是:設兩個指針low和high,他們的初值分別爲最低位置的下一個位置和最高位,設最低位置樞軸的關鍵字爲pivotkey,則首先從high所指位置起向前搜索找到第一個關鍵字小於pivotkey的記錄的樞軸記錄互相交換。發生了交換後才從low所指向的位置起向後搜索,找到第一個關鍵字大於pivotkey的記錄和樞軸記錄互相交換。重複這兩步直至low=how爲止

以下圖所示:

特別要注意換方向的時機是發生了交換後,用Python實現以下:

def quick_sort(self, value_list):
    """
    快速排序
    :param value_list: 待排序的無序列表
    :return: 排序後的列表
    """
    low = 0
    high = len(value_list) - 1
    self.__qsort(value_list, low, high)
    sorted_list = value_list
    return sorted_list

def __qsort(self, val_list, low, high):
    """
    快速排序輔助函數
    :param val_list: 無序列表
    :param low: 低位
    :param high: 高位
    :return:
    """
    if low >= high:
        return
    pivot_key = low
    temp_low = pivot_key
    temp_high = high
    while low < high:
        # 分紅一邊比軸(pivot)大,一邊比軸(pivot)小的順序
        while low < high:
            if val_list[high] < val_list[pivot_key]:
                temp = val_list[high]
                val_list[high] = val_list[pivot_key]
                val_list[pivot_key] = temp
                pivot_key = high
                break  # 發生交換後,就換方向
            else:
                high -= 1
        while low < high:
            if val_list[low] > val_list[pivot_key]:
                temp = val_list[low]
                val_list[low] = val_list[pivot_key]
                val_list[pivot_key] = temp
                pivot_key = low
                break  # 發生交換後,就換方向
            else:
                low += 1
    self.__qsort(val_list, temp_low, pivot_key - 1)
    self.__qsort(val_list, pivot_key + 1, temp_high)

5.簡單選擇排序

選擇排序(Selection Sort)是一種簡單直觀的排序算法。它的基本思想是:每一趟在n-i+1(i=1,2,...,n-1)個記錄中選取關鍵字最小的記錄做爲有序序列中第i個記錄。簡單選擇排序:經過n-1次關鍵字的比較,從n-i+1個記錄中選出關鍵字最小的記錄,並和第i(1≤i≤n)個記錄交換之。以下圖所示:

 

用Python實現以下:

@staticmethod
def simple_selection_sort(value_list):
    """
    簡單選擇排序
    :param value_list: 待排序的無序列表
    :return: 排序後的列表
    """
    for i in range(len(value_list)):
        min_val = 9999999
        for j in range(i, len(value_list)):
            if min_val > value_list[j]:
                min_val = value_list[j]
        count = 0  # 若是有多個相同的最小值
        for j in range(i, len(value_list)):
            if min_val == value_list[j]:
                value_list[j], value_list[i + count] = value_list[i + count], value_list[j]
    sorted_list = value_list
    return sorted_list

6.堆排序

堆排序(Heap Sort)是指利用堆這種數據結構所設計的一種排序算法。堆的定義以下:

n個元素的序列{k1,k2,...,kn}當且僅當知足一下關係時,稱之爲堆。

 

若將序列當作是一個徹底二叉樹,則堆的含義代表,徹底二叉樹中全部非終端節點均不大於(或不小於)其左、右孩子節點的值。由此,若序列是堆,則堆頂元素必爲序列中的最小值(或最大值)。以下圖所示:

 

至此,咱們能夠給出堆排序的過程:若在輸出堆頂的最小值後,使得剩餘n-1個元素的序列又建成一個堆,則獲得n個元素中的次小值。如此反覆執行,便能獲得一個有序序列。

故整個堆排序能夠大體分爲兩個過程:

·將無序序列建成堆。

·輸出堆頂元素後,用相似建堆的方法調整堆。

以下兩個圖所示:

 

 

根據堆排序的特色總結出兩點注意事項:

1.利用把堆當作徹底二叉樹的特色,用徹底二叉樹的性質解決算法問題。

2.建堆的過程是從樹種的最後一個非終端節點逆序開始調整的。

3.每調整一次須要檢查先後是否依然保持堆的特徵

本文利用了二叉樹的孩子兄弟表示法來生成二叉樹(堆)的。代碼以下:

class CldSibNode(object):
    """
    私有內部類:孩子兄弟二叉鏈表節點
    """

    def __init__(self, val):
        self.value = val
        self.child = None
        self.sibling = None

def heap_sort(self, value_list):
    """
    堆排序
    :param value_list: 待排序的無序列表
    :return: 排序後的列表
    """
    sorted_list = []
    root_node = self.CldSibNode(None)
    self.__child_sibling(root_node, value_list, 0)
    for ct in range(1, len(value_list) // 2 + 1):  # 建堆
        self.__adjust_heap(root_node, len(value_list) // 2 + 1 - ct, 1)
    for i in range(1, len(value_list) + 1):  # 堆排序
        sorted_list.append(root_node.value)  # 輸出堆頂元素
        head = root_node
        self.__shrink_heap(root_node, len(value_list) + 1 - i, 1, head)
        self.__adjust_heap(root_node, 1, 1)  # 調整堆

    return sorted_list

def __child_sibling(self, node, value_list, ind):
    """
    建立徹底二叉樹的左孩子右兄弟二叉鏈表
    :param node: 當前節點
    :param value_list: 待排序的無序列表
    :param ind:
    :return:
    """
    if ind >= len(value_list):
        return
    node.value = value_list[ind]
    if ind * 2 + 1 < len(value_list):
        node.child = self.CldSibNode(None)  # 孩子
        self.__child_sibling(node.child, value_list, ind * 2 + 1)
    if ind * 2 + 2 < len(value_list):
        node.child.sibling = self.CldSibNode(None)  # 兄弟
        self.__child_sibling(node.child.sibling, value_list, ind * 2 + 2)

def __adjust_heap(self, root_node, last_ind, now_ind):
    if not root_node or not root_node.child:  # 不爲空且有孩子
        return
    if now_ind == last_ind:
        # 須要調整的非終端節點
        temp = root_node
        cg = False
        while temp.child:
            if temp.value > temp.child.value:
                temp.value, temp.child.value = temp.child.value, temp.value
                cg = True  # 發生交換
            if temp.child.sibling:
                if temp.value > temp.child.sibling.value:
                    if cg:
                        # 若是發生過交換
                        temp.value, temp.child.value = temp.child.value, temp.value
                    temp.value, temp.child.sibling.value = temp.child.sibling.value, temp.value
                    temp = temp.child.sibling
                    continue
                else:
                    if cg:
                        # 若是發生過交換
                        temp = temp.child
                        continue
            break
    # 遞歸
    self.__adjust_heap(root_node.child, last_ind, now_ind * 2)
    if root_node.child.sibling:
        self.__adjust_heap(root_node.child.sibling, last_ind, now_ind * 2 + 1)

def __shrink_heap(self, root_node, last_ind, now_ind, head):
    if not root_node or now_ind * 2 > last_ind:
        # 爲空
        return
    if last_ind == now_ind * 2 + 1:
        head.value = root_node.child.sibling.value
        root_node.child.sibling = None
        return True
    if last_ind == now_ind * 2:
        head.value = root_node.child.value
        root_node.child = None
        return True
    if root_node.child:
        self.__shrink_heap(root_node.child, last_ind, now_ind * 2, head)
        self.__shrink_heap(root_node.child.sibling, last_ind, now_ind * 2 + 1, head)

7.歸併排序

歸併排序(Merging Sort),「歸併」的含義是將兩個或兩個以上的有序表組合成一個新的有序表。假設初始序列有n個記錄,則可當作是n個有序的子序列,每一個子序列的長度爲1,而後兩兩歸併,獲得[n/2]個長度爲2或1的有序子序列;再兩兩歸併,……,如此重複,直至獲得一個長度爲n的有序序列爲止,這種排序方法爲2-路歸併排序。算法的基本思想以下圖所示:

 

其中兩個子序列的合併大有學問,基本思想就是:分別在兩個序列頭設置指針,比較兩個序列指針所指的值的大小,將知足要求的值提取出來造成新列表,並將指針右移。當其中一個指針指向結尾以後時,表示其中一個列表已取盡,接着直接在新列表尾部鏈接另外一個列表。以下圖所示:

 

用Python實現以下:

@staticmethod
def merging_sort(self, value_list):
    """
    歸併排序
    :param value_list: 待排序的無序列表
    :return: 排序後的新列表
    """
    i = 0
    while np.power(2, i) < len(value_list):
        count = np.power(2, i)
        start = 0
        outer_temp = []
        while start < len(value_list):
            # 定位另外一邊
            other = start + count
            temp = []
            if other >= len(value_list):
                # 另外一邊不存在:直接合並
                outer_temp.extend(value_list[start: start + count])
                break
            left, right = 0, 0
            while left < count or right < count:
                if other + right >= len(value_list):
                    # 右邊提早結束
                    temp.extend(value_list[start + left: start + count])
                    break
                elif value_list[start + left] < value_list[other + right]:
                    # 左邊更小
                    temp.append(value_list[start + left])
                    left += 1
                    if left == count:
                        # 左邊遍歷結束
                        temp.extend(value_list[other + right: other + count])
                        break
                else:
                    # 右邊更小
                    temp.append(value_list[other + right])
                    right += 1
                    if right == count:
                        # 右邊遍歷結束
                        temp.extend(value_list[start + left: start + count])
                        break
            outer_temp.extend(temp)
            start += count * 2
        value_list = outer_temp
        i += 1
    sorted_list = value_list
    return sorted_list

8.基數排序

基數排序(Radix Sort)是一種非比較整數排序算法,其原理是將整數按位數切割成不一樣的數字,而後按每一個位數分別比較。因爲整數也能夠表達字符串(好比名字或日期)和特定格式的浮點數,因此基數排序也不是隻能使用於整數。

 

排序時有兩點須要注意:

1.每完成一趟排序,要清空隊列。

2.隊列的鏈接要找到第一個不爲空的隊列做爲頭,和繞開全部空隊列。

用Python實現以下:

@staticmethod
def radix_sort(value_list):
    """
    基數排序
    :param value_list: 待排序的無序列表
    :return: 排序後的新列表
    """
    i = 0
    max_num = max(value_list)
    n = len(str(max_num))
    while i < n:
        # 初始化桶數組
        bucket_list = [[] for _ in range(10)]
        for x in value_list:
            # 找到位置放入桶數組
            bucket_list[int(x / (10 ** i)) % 10].append(x)
        value_list.clear()
        for x in bucket_list:
            # 放回原序列
            for y in x:
                value_list.append(y)
        i += 1
    sorted_list = value_list
    return sorted_list

測試代碼:

編寫測試代碼運行結果以下:

if __name__ == '__main__':
    li = list(np.random.randint(1, 1000, 30))
    my_sort = MySort()
    print("original sequence:", li)
    print("*" * 100)
    print("1.straight_insertion_sort:", my_sort.straight_insertion_sort(li.copy()))
    print("2.shells_sort:", my_sort.shells_sort(li.copy()))
    print("3.bubble_sort:", my_sort.bubble_sort(li.copy()))
    print("4.quick_sort:", my_sort.quick_sort(li.copy()))
    print("5.simple_selection_sort:", my_sort.simple_selection_sort(li.copy()))
    print("6.heap_sort:", my_sort.heap_sort(li.copy()))
    print("7.merging_sort:", my_sort.merging_sort(li.copy()))
    print("8.radix_sort:", my_sort.radix_sort(li.copy()))

測試運行結果:

original sequence: [424, 381, 234, 405, 554, 742, 527, 876, 27, 904, 169, 566, 854, 448, 65, 508, 226, 477, 12, 670, 408, 520, 774, 99, 159, 565, 393, 288, 149, 711]
****************************************************************************************************
1.straight_insertion_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
2.shells_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
3.bubble_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
4.quick_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
5.simple_selection_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
6.heap_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
7.merging_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]
8.radix_sort: [12, 27, 65, 99, 149, 159, 169, 226, 234, 288, 381, 393, 405, 408, 424, 448, 477, 508, 520, 527, 554, 565, 566, 670, 711, 742, 774, 854, 876, 904]

總結

各個排序效率見下圖:

 

能夠得出如下幾個結論:

1.從平均時間性能而言,快速排序最佳。

2.堆排序適用於n較大的數據。

3.基數排序是穩定的,時間複雜度較大的簡單排序方法也是穩定的。

4.穩定性是由方法自己決定的。

5.沒有最好的排序方法,視狀況而定。

#! /usr/bin/env python3
# -*- coding:utf-8 -*-

# Author   : MaYi
# Blog     : http://www.cnblogs.com/mayi0312/
# Date     : 2020-01-06
# Name     : mySort
# Software : PyCharm
# Note     : 八大排序算法
import numpy as np


class MySort(object):
    """
    自定義一個排序的類
    """

    def straight_insertion_sort(self, value_list):
        """
        直接插入排序
        :param value_list: 待排序的無序列表
        :return: 排序後的列表
        """
        return self.__straight_insert(value_list)

    @staticmethod
    def __straight_insert(value_list):
        sorted_list = []
        sorted_list.append(value_list.pop(0))
        for i in range(0, len(value_list)):
            tail = True  # 是否在尾部插入
            insert_loc = 0
            for j in range(len(sorted_list)):
                if value_list[i] <= sorted_list[j]:
                    tail = False
                    insert_loc = j
                    break
            sorted_list.append(value_list[i])  # 先將值插入尾部
            if not tail:
                # 移動值
                for j in range(len(sorted_list) - 1, insert_loc, -1):
                    sorted_list[j], sorted_list[j - 1] = sorted_list[j - 1], sorted_list[j]
        return sorted_list

    def shells_sort(self, value_list):
        """
        希爾排序
        :param value_list: 待排序的無序列表
        :return: 排序後的列表
        """
        gap = len(value_list) // 2
        while gap >= 1:
            i = 0
            while(i + gap) < len(value_list):
                start = i
                gap_list = []
                while start < len(value_list):
                    gap_list.append(value_list[start])
                    start = start + gap
                gap_list = self.__straight_insert(gap_list)
                start = i
                while start < len(value_list):
                    value_list[start] = gap_list.pop(0)
                    start += gap
                i += 1
            gap //= 2
        sorted_list = value_list
        return sorted_list

    @staticmethod
    def bubble_sort(value_list):
        """
        冒泡排序
        :param value_list: 待排序的無序列表
        :return: 排序後的列表
        """
        for i in range(len(value_list) - 1):
            for j in range(i + 1, len(value_list)):
                if value_list[i] > value_list[j]:
                    value_list[i], value_list[j] = value_list[j], value_list[i]
        sorted_list = value_list
        return sorted_list

    def quick_sort(self, value_list):
        """
        快速排序
        :param value_list: 待排序的無序列表
        :return: 排序後的列表
        """
        low = 0
        high = len(value_list) - 1
        self.__qsort(value_list, low, high)
        sorted_list = value_list
        return sorted_list

    def __qsort(self, val_list, low, high):
        """
        快速排序輔助函數
        :param val_list: 無序列表
        :param low: 低位
        :param high: 高位
        :return:
        """
        if low >= high:
            return
        pivot_key = low
        temp_low = pivot_key
        temp_high = high
        while low < high:
            # 分紅一邊比軸(pivot)大,一邊比軸(pivot)小的順序
            while low < high:
                if val_list[high] < val_list[pivot_key]:
                    temp = val_list[high]
                    val_list[high] = val_list[pivot_key]
                    val_list[pivot_key] = temp
                    pivot_key = high
                    break  # 發生交換後,就換方向
                else:
                    high -= 1
            while low < high:
                if val_list[low] > val_list[pivot_key]:
                    temp = val_list[low]
                    val_list[low] = val_list[pivot_key]
                    val_list[pivot_key] = temp
                    pivot_key = low
                    break  # 發生交換後,就換方向
                else:
                    low += 1
        self.__qsort(val_list, temp_low, pivot_key - 1)
        self.__qsort(val_list, pivot_key + 1, temp_high)

    @staticmethod
    def simple_selection_sort(value_list):
        """
        簡單選擇排序
        :param value_list: 待排序的無序列表
        :return: 排序後的列表
        """
        for i in range(len(value_list)):
            min_val = 9999999
            for j in range(i, len(value_list)):
                if min_val > value_list[j]:
                    min_val = value_list[j]
            count = 0  # 若是有多個相同的最小值
            for j in range(i, len(value_list)):
                if min_val == value_list[j]:
                    value_list[j], value_list[i + count] = value_list[i + count], value_list[j]
        sorted_list = value_list
        return sorted_list

    class CldSibNode(object):
        """
        私有內部類:孩子兄弟二叉鏈表節點
        """

        def __init__(self, val):
            self.value = val
            self.child = None
            self.sibling = None

    def heap_sort(self, value_list):
        """
        堆排序
        :param value_list: 待排序的無序列表
        :return: 排序後的列表
        """
        sorted_list = []
        root_node = self.CldSibNode(None)
        self.__child_sibling(root_node, value_list, 0)
        for ct in range(1, len(value_list) // 2 + 1):  # 建堆
            self.__adjust_heap(root_node, len(value_list) // 2 + 1 - ct, 1)
        for i in range(1, len(value_list) + 1):  # 堆排序
            sorted_list.append(root_node.value)  # 輸出堆頂元素
            head = root_node
            self.__shrink_heap(root_node, len(value_list) + 1 - i, 1, head)
            self.__adjust_heap(root_node, 1, 1)  # 調整堆

        return sorted_list

    def __child_sibling(self, node, value_list, ind):
        """
        建立徹底二叉樹的左孩子右兄弟二叉鏈表
        :param node: 當前節點
        :param value_list: 待排序的無序列表
        :param ind:
        :return:
        """
        if ind >= len(value_list):
            return
        node.value = value_list[ind]
        if ind * 2 + 1 < len(value_list):
            node.child = self.CldSibNode(None)  # 孩子
            self.__child_sibling(node.child, value_list, ind * 2 + 1)
        if ind * 2 + 2 < len(value_list):
            node.child.sibling = self.CldSibNode(None)  # 兄弟
            self.__child_sibling(node.child.sibling, value_list, ind * 2 + 2)

    def __adjust_heap(self, root_node, last_ind, now_ind):
        if not root_node or not root_node.child:  # 不爲空且有孩子
            return
        if now_ind == last_ind:
            # 須要調整的非終端節點
            temp = root_node
            cg = False
            while temp.child:
                if temp.value > temp.child.value:
                    temp.value, temp.child.value = temp.child.value, temp.value
                    cg = True  # 發生交換
                if temp.child.sibling:
                    if temp.value > temp.child.sibling.value:
                        if cg:
                            # 若是發生過交換
                            temp.value, temp.child.value = temp.child.value, temp.value
                        temp.value, temp.child.sibling.value = temp.child.sibling.value, temp.value
                        temp = temp.child.sibling
                        continue
                    else:
                        if cg:
                            # 若是發生過交換
                            temp = temp.child
                            continue
                break
        # 遞歸
        self.__adjust_heap(root_node.child, last_ind, now_ind * 2)
        if root_node.child.sibling:
            self.__adjust_heap(root_node.child.sibling, last_ind, now_ind * 2 + 1)

    def __shrink_heap(self, root_node, last_ind, now_ind, head):
        if not root_node or now_ind * 2 > last_ind:
            # 爲空
            return
        if last_ind == now_ind * 2 + 1:
            head.value = root_node.child.sibling.value
            root_node.child.sibling = None
            return True
        if last_ind == now_ind * 2:
            head.value = root_node.child.value
            root_node.child = None
            return True
        if root_node.child:
            self.__shrink_heap(root_node.child, last_ind, now_ind * 2, head)
            self.__shrink_heap(root_node.child.sibling, last_ind, now_ind * 2 + 1, head)

    @staticmethod
    def merging_sort(value_list):
        """
        歸併排序
        :param value_list: 待排序的無序列表
        :return: 排序後的新列表
        """
        i = 0
        while np.power(2, i) < len(value_list):
            count = np.power(2, i)
            start = 0
            outer_temp = []
            while start < len(value_list):
                # 定位另外一邊
                other = start + count
                temp = []
                if other >= len(value_list):
                    # 另外一邊不存在:直接合並
                    outer_temp.extend(value_list[start: start + count])
                    break
                left, right = 0, 0
                while left < count or right < count:
                    if other + right >= len(value_list):
                        # 右邊提早結束
                        temp.extend(value_list[start + left: start + count])
                        break
                    elif value_list[start + left] < value_list[other + right]:
                        # 左邊更小
                        temp.append(value_list[start + left])
                        left += 1
                        if left == count:
                            # 左邊遍歷結束
                            temp.extend(value_list[other + right: other + count])
                            break
                    else:
                        # 右邊更小
                        temp.append(value_list[other + right])
                        right += 1
                        if right == count:
                            # 右邊遍歷結束
                            temp.extend(value_list[start + left: start + count])
                            break
                outer_temp.extend(temp)
                start += count * 2
            value_list = outer_temp
            i += 1
        sorted_list = value_list
        return sorted_list

    @staticmethod
    def radix_sort(value_list):
        """
        基數排序
        :param value_list: 待排序的無序列表
        :return: 排序後的新列表
        """
        i = 0
        max_num = max(value_list)
        n = len(str(max_num))
        while i < n:
            # 初始化桶數組
            bucket_list = [[] for _ in range(10)]
            for x in value_list:
                # 找到位置放入桶數組
                bucket_list[int(x / (10 ** i)) % 10].append(x)
            value_list.clear()
            for x in bucket_list:
                # 放回原序列
                for y in x:
                    value_list.append(y)
            i += 1
        sorted_list = value_list
        return sorted_list


if __name__ == '__main__':
    li = list(np.random.randint(1, 1000, 30))
    my_sort = MySort()
    print("original sequence:", li)
    print("*" * 100)
    print("1.straight_insertion_sort:", my_sort.straight_insertion_sort(li.copy()))
    print("2.shells_sort:", my_sort.shells_sort(li.copy()))
    print("3.bubble_sort:", my_sort.bubble_sort(li.copy()))
    print("4.quick_sort:", my_sort.quick_sort(li.copy()))
    print("5.simple_selection_sort:", my_sort.simple_selection_sort(li.copy()))
    print("6.heap_sort:", my_sort.heap_sort(li.copy()))
    print("7.merging_sort:", my_sort.merging_sort(li.copy()))
    print("8.radix_sort:", my_sort.radix_sort(li.copy()))
完整代碼
相關文章
相關標籤/搜索