排序算法原理與實現[冒泡、選擇、插入、快速、哈希、計數](python版)

1. 冒泡排序:

  • 原理

冒泡排序算法的基本原理就是比較相鄰兩個數字的大小。將兩個數中比較大的那個數交換到靠後的位置,不斷交換下去就可以將最大的那兩個數放到隊列的尾部。然後重頭再次交換)(交換list.lenght-1次),直到將數列排成有序數列。

  • 代碼實現
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""

import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def bubbleSort(List):
    """
    冒泡排序
    :param List:
    :return:
    """
    if len(List) <= 1:
        return List
    for i in range(len(List)-1):  # 經過n-1輪排序
        for j in range(len(List)-1): # 比較前一個數和後一個數的大小關係
            if List[j] >= List[j+1]:
                List[j], List[j+1] = List[j+1], List[j] # 如果前一個數比後一個數大,則調換位置
    return List

if __name__ == '__main__':
    print(List)
    print(bubbleSort(List))
    runtime = timeit.timeit("bubbleSort(List)","from __main__ import bubbleSort, List",number=1000)
    print(runtime)

2. 選擇排序:

  • 原理

簡單來說,選擇排序只做了一件事件,那就是從數列中選擇最大(最小)的那個數,將這個數放到合適的位置。然後拋開這個數的子序列中找最大(最小)的那個數放到合適的位置。然後一直到子序列爲空。

  • 代碼實現
# -*- coding:utf-8 -*-

""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

"""
# 這個雖簡潔易懂,但有重複數字會有有Bug,原因爲相同數下標無法確定
def selectSort(List):
    if len(List) <= 1:  # 如果長度小於等於1,直接返回
        return List
    for i in range(0, len(List)-1):  # 遍歷數組
        if List[i] >= min(List[i+1:]): # 如果對應下標數的值大於剩餘部分的最小值,交換位置
            minIndex = List.index(min(List[i+1:])) # 求剩餘部分的最小值小標
            List[i], List[minIndex] = List[minIndex], List[i] #滿足條件, 交換位置
    return List
"""

def selectSort(List):
    if len(List) <= 1:   # 如果長度小於等於1,直接返回
        return List
    for i in range(len(List)-1):
        min_index = i
        for j in range(i+1,len(List)):
            if List[j] < List[min_index]:
                min_index = j
        List[i], List[min_index] = List[min_index], List[i]
    return List

if __name__ == '__main__':
    print(List)
    print(selectSort(List))
    print(timeit('selectSort(List)','from __main__ import selectSort, List',number=1000))

3. 插入排序:

  • 原理

插入排序首先將數列分爲兩部分,數列的第一數爲left,其餘數位right部分。然後將right部分中的數逐一取出,插入到left部分的適當位置。當right部分爲空時,left部分就成了一個有序的序列。

  • 代碼實現
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def insertSort(List):
    if len(List) <= 1:
        return List
    for right in range(1,len(List)):  # 遍歷右邊沒有排序的數組
        target = List[right]     # 需要排序的值
        for left in range(0, right):
            if target <= List[left]:
                List[left+1:right+1] = List[left:right]  # 將左邊已經排序好的數組整體右移一位
                List[left] = target # 將需排序的值到左邊已排序好數組的適當位置
                break  # 提高性能,如果比邊已排序好的最小數都小,一次則跳出循環
    return List
 
# 第二種思路,從左邊排序的列表最後邊向最左邊比較 
def insertSort2(List):
    if len(List) <= 1:
        return List
    for i in range(1,len(List)):
        j = i
        while j > 0:
            if List[j] < List[j-1]:
                List[j], List[j-1] = List[j-1], List[j]
                j -= 1
            else:
                break
    return List

if __name__ == '__main__':
    print(List)
    print(insertSort(List))
    print(timeit('insertSort(List)','from __main__ import insertSort, List',number=1000))

4. 快速排序:

  • 原理

以列表中任意一個數爲基準(一般選用列表的第一個數,因爲遞歸調用的最後每個列表只有一個數),將列表分爲左右兩個子列表:左邊子列表的數要比基準數小,右邊子序列表的數要比基準數打。然後繼續把左邊子列表和右邊子列表按照同樣的方法繼續分解、比較,一直到無法分解爲止。然後按照左邊子列表(比基準數小) + 基準數 + 右邊子列表(比基準數大)的方式連接起來。最後合成了一個有序數列。

  • 代碼實現
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""

from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def quickSort(List):
    """
    快速排序:優點:代碼簡潔,易於理解 缺點: 太過耗費空間
    :param List:
    :return:
    """
    if len(List) <= 1:
        return List
    left = []     # 左區,用來存放比基準數小的數
    right = []    # 右區,用來存放比基準數大的數
    for i in List[1:]:   # 遍歷除基準數以外的所有數
        if i <= List[0]:
            left.append(i)
        else:
            right.append(i)
    return quickSort(left) + [List[0]] + quickSort(right)  # 遞歸調用,無限拆分後合併各個有序數組

if __name__ == '__main__':
    print(List)
    print(quickSort(List))
    print(timeit('quickSort(List)','from __main__ import quickSort, List',number=1000))

5. 哈希排序

  • 原理

改進了得插入排序,將待排序的數組根據差量分成若干的的子數組,分別進行插入排序,通過不斷地修改組距,使得分組數逐漸減少,當組距爲1是,則就是一個插入排序

  • 代碼實現
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def shellSort(List):
    """
    希爾排序
    :param List:
    :return:
    """
    n = len(List)
    gap = n // 2
    # gap變化到0之前,插入算法執行的次數
    while gap > 0:
        # 插入算法,與普通的插入算法的區別就是gap步長
        for i in range(gap, n): # 外層循環控制的是所有子序列的所有元素(不包括每一組第一個數)
            j = i
            while j > 0:
                if List[j] < List[j - gap]: # 內層循環就是一個插入排序,比較與前一個數的大小關係
                    List[j], List[j - gap] = List[j - gap], List[j]
                    j -= gap
                else:
                    break
        # 縮短gap步長
        gap //= 2
    return List

if __name__ == '__main__':
    print(List)
    print(shellSort(List))
    print(timeit('shellSort(List)','from __main__ import shellSort, List',number=1000))

6. 計數排序

  • 原理

計數排序算法採用了一個巧妙的辦法,首先需要創建一個與原數列等長的新數列,選擇一個數爲計基數,然後統計整個數列中有多少個數比基數小。如果有n個數比基數小,那麼將基礎放到數列的n+1位置上(不過此方法的空間和時間複雜度都比較大)

  • 代碼實現
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""

from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def countingSort(List):
    """
    計數排序
    :param List:
    :return:
    """
    if len(List) <= 1:
        return List
    # 創建一個跟原數組長度相同的空數組
    rLen = len(List)
    rList = [None]*rLen
    for i in range(rLen): # 遍歷數組,選擇基數
        small = 0   # 記錄比基數小的個數
        same = 0   # 記錄跟基數相等的個數
        for j in range(rLen): # 找出比基數小或相等的數
            if List[j] < List[i]:
                small += 1
            elif List[j] == List[i]:
                same += 1
        for k in range(small,small+same):
            rList[k] = List[i]
    return rList

if __name__ == '__main__':
    print(List)
    print(countingSort(List))
    print(timeit('countingSort(List)','from __main__ import countingSort, List',number=1000))

如果有問題,歡迎在評論區交流喔,博主看到會第一時間回覆。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章