簡單快速排序

APOLLO_TS發表於2020-12-29

採用哨兵投石法理解簡單快速排序,這是理解雙軸排序的基礎,雙軸排序表面簡單,但根據java工業程式來看,發展歷次更迭,已經有些難以理解了,之後我又新增一些邏輯可能會導致邏輯判斷過多,失去演算法的本真。所以先採用最簡單的基準值選取思路,就是開頭結尾選基準值。

 

# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   開發人員:Edwin
   開發日期:
   開發工具:PyCharm
   功能描述:
   
-------------------------------------------------
"""
def quick_sort(alist: []) -> []:
    '''
    抓住了簡單快速排序的精要,也就是佔位,但有空間浪費,快速排序法的初衷是不開闢更多的空間。
    :param alist:
    :return: 排序後的陣列
    '''
    n = len(alist)
    if n <= 1:
        return alist
    pivot = alist[0]
    lesser = [item for item in alist[1:] if item <= pivot]
    greater = [item for item in alist[1:] if item > pivot]
    return quick_sort(lesser) + [pivot] + quick_sort(greater)

def quick_sort(alist: [], start, end) -> None:
    '''
    採用哨兵巡邏方式,A在開頭往後搜尋,B從結尾往前搜尋,A代表比基準值小的陣營,B代表比基準值大或者相等的陣營
    那誰來先丟石頭呢,我們給B,因為基準值取了第一個元素,這個元素留了一個坑。
    B發現小號的石頭,停下腳步,把這個小石頭丟給了A陣營,然後等待A陣營丟過來大石頭把小石頭留下的坑填平。
    A發現大號的石頭,停下腳步,把這個大石頭丟給了B陣營,然後等待B陣營丟過來小石頭把大石頭留下的坑填平。
    此時AB都停下了腳步,長官發現AB都沒碰面,喚醒AB繼續巡邏,直到他們碰面。
    當AB相遇就完成了一次巡邏,AB的位置就是基準值的位置,此時的基準值把序列分成左右兩個序列,然後分別對這兩個序列進行遞迴呼叫。
    :param alist: 待排序陣列
    :param start: 起始下標
    :param end: 結束下標
    :return: None
    '''
    if start >= end:
        return
    low, high, pivot = start, end, alist[start]
    while low < high:
        while low < high and alist[high] >= pivot:
            high -= 1
        alist[low] = alist[high]
        while low < high and alist[low] < pivot:
            low += 1
        alist[high] = alist[low]
    alist[low] = pivot
    quick_sort(alist, start, low - 1)
    quick_sort(alist, low + 1, end)

def ds_quick_sort(alist: []) -> None:
    '''
    士兵投石法
    :param alist:
    :return:
    '''
    quick_sort(alist, 0, len(alist) - 1)

def is_sorted(alist):
    prev = alist[0]
    for i in range(1, len(alist)):
        if prev > alist[i]:
            print('Sort ascending failed.')
            return False
        prev = alist[i]
    print('Sort ascending succeed.')
    return True

def test():
    import random
    alist = [random.randint(1, 1000000) for i in range(1000000)]
    # alist = [8, 8]
    # print('Before: ', alist)
    ds_quick_sort(alist)
    print('After: ', alist)
    is_sorted(alist)

if __name__ == '__main__':
    test()

 

相關文章