1. 程式人生 > 實用技巧 >常用排序演算法總結

常用排序演算法總結

實現稍微難點的三個演算法:快排、歸併、堆排序

快速排序

以下是一種寫法(演算法導論上是另一種寫法,待補充)

def quickSort(data, start, end):
    i = start
    j = end
    # i與j重合,一次排序結束
    if i >= j:
        return
    # 設定最左邊的數為基準值
    flag = data[start]
    while i < j:
        while i < j and data[j] >= flag:
            j -= 1
        # 找到右邊第一個小於基準的數賦值給左邊i(此時左邊i被記錄在flag中)
        data[i] = data[j]
        while i < j and data[i] <= flag:
            i += 1
        # 找到左邊第一個大於基準的數賦值給右邊的j
        data[j] = data[i]
    # 迴圈完後把flag值放到i所在位置
    data[i] = flag
    # print(data)
    # 除去i之外兩段遞迴
    quickSort(data, start, i - 1)
    quickSort(data, i + 1, end)

if __name__ == "__main__":
    data = [6, 5, 8, 2, 3, 1]
    print(data)
    quickSort(data, 0, len(data) - 1)
    print(data)

氣泡排序

def bubbleSort(alist):
    n = len(alist)
    exchange = False
    for i in range(n-1, 0, -1):
        for j in range(0, i):
            if alist[j] > alist[j+1]:
                alist[j], alist[j+1] = alist[j+1], alist[j]
                exchange = True
        # 如果發現整個排序過程中沒有交換,提前結束
        if not exchange:
            break
    return alist

選擇排序

  • 選擇排序是在氣泡排序的基礎上優化的,提高了氣泡排序的效能
def selectionSort(alist):
    n = len(alist)

    for i in range(n - 1):
        # 尋找[i,n]區間裡的最小值
        min_index = i
        for j in range(i+1, n):
            if alist[j] < alist[min_index]:
                min_index = j
        alist[i], alist[min_index] = alist[min_index], alist[i]
    return alist

插入排序

def insertionSort(blist):
    n = len(blist)
    for i in range(1, n):
    # 尋找a[i]合適的插入位置
        temp = blist[i]
        for j in range(i, 0, -1):
            if temp < blist[j-1]:
                blist[j] = blist[j-1]
            else:
                break
            blist[j-1] = temp
    print(blist)
    return blist

希爾排序

  • 希爾排序是在插入排序的基礎上優化的,提高了插入排序的效能
def shell1Sort(data):
    step = len(data) // 2
    while step >= 1:
        print("當前增量是:", step)
        for i in range(step, len(data)):
            for j in range(i-step, -step, -step):
                if data[j] > data[j+step]:
                    data[j], data[j+step] = data[j+step], data[j]
        step = int(step/2)

歸併排序

def merge_sort(nums):
    if len(nums) <= 1:
        return nums
    middle = len(nums) // 2
    left_num = nums[:middle]
    right_num = nums[middle:]
    return merge(merge_sort(left_num), merge_sort(right_num))

def merge(left_num, right_num):
    len_left = len(left_num)
    len_right = len(right_num)
    i = j = 0
    result = []
    # 比較left_num和left_right中的元素,按序新增到result中
    while i < len_left and j < len_right:
        if left_num[i] > right_num[j]:
            result.append(right_num[j])
            j += 1
        else:
            result.append(left_num[i])
            i += 1
    # 將j中的剩餘元素新增到result中
    if i == len_left and j < len_right:
        for m in right_num[j:]:
            result.append(m)
    # 將i中的剩餘元素新增到result中
    if j == len_right and i < len_left:
        for m in left_num[i:]:
            result.append(m)
    return result

堆排序(個人感覺演算法很贊)

from collections import deque
# python中交換兩個元素的位置
def swap(nums, i, j):
    nums[i], nums[j] = nums[j], nums[i]
    return nums

# 構造最大堆
def heap_adjust(nums, start, end):
    temp = nums[start]
    i = start
    j = start * 2
    while j <= end:
        if j < end and nums[j] < nums[j + 1]:
            j += 1
        if temp < nums[j]:
            nums[i] = nums[j]
            i = j
            j = i * 2
        else:
            break
    nums[i] = temp

# 堆排序
def heap_sort(nums):
    len_heap = len(nums) - 1
    len_mid_heap = len_heap // 2

    # 將序列調整為一個最大堆
    for i in range(len_mid_heap):
        heap_adjust(nums, len_mid_heap-i, len_heap)
    print(nums)

    # 將堆頂元素和堆末尾元素交換,將剩下元素調整為一個最大對
    for i in range(len_heap-1):
        swap(nums, len_heap-i, 1)
        heap_adjust(nums, 1, len_heap-i-1)

    print(nums)
    return list(nums)[1:]


def main():
    L = deque([50, 16, 30, 10, 60, 90, 2, 80, 70])
    L.appendleft(0)
    print(heap_sort(L))

參考資料