1. 程式人生 > 實用技巧 >python寫幾個排序演算法

python寫幾個排序演算法

def maopao(data: list):
    """
    兩兩比較
    :param data:
    :return:
    """
    length = len(data)
    for i in range(length - 1):
        flag = True
        for j in range(length - 1 - i):
            if data[j] > data[j + 1]:
                data[j], data[j + 1] = data[j + 1], data[j]
                flag = False
        print(i, data)
        if flag:
            break


def choice(data: list):
    """
    對未排序的元素中選出最小值替換到當前位置
    :param data:
    :return:
    """
    length = len(data)
    for i in range(length - 1):
        min_index = i
        for j in range(i + 1, length):
            if data[j] < data[min_index]:
                min_index = j

        data[i], data[min_index] = data[min_index], data[i]
        print(i, data)


def insert(data: list):
    """
    從第二個元素開始,跟左邊的所有元素比較,找到它比左邊元素小的地方,把它從原位置插入到這個地方
    :param data:
    :return:
    """
    length = len(data)
    for i in range(1, length):
        # 找到合適的位置
        for j in range(i):
            if data[i] < data[j]:
                data.insert(j, data.pop(i))
        print(i - 1, data)


def quick(data: list):
    """
    從陣列中選擇一個元素稱之為中軸元素,然後把陣列中所有小於中軸元素的元素放在其左邊,
    所有大於或等於中軸元素的元素放在其右邊,顯然,此時中軸元素所處的位置的是固定的,也就是說,我們無需再移動中軸元素的位置。
    從中軸元素那裡開始把大的陣列切割成兩個小的陣列(兩個陣列都不包含中軸元素),
    接著我們通過遞迴的方式,讓中軸元素左邊的陣列和右邊的陣列也重複同樣的操作,
    直到陣列的大小為1,此時每個元素都處於有序的位置。
    :param data:
    :return:
    """
    if not data:
        return []
    length = len(data)
    tmp = data[0]

    small = []
    big = []

    i = 0
    times = 0
    while times < length:
        if data[i] < tmp:
            small.append(data.pop(i))
        elif data[i] > tmp:
            big.append(data.pop(i))
        else:
            i += 1
        times += 1
    return quick(small) + data + quick(big)


def mergesort(seq: list):
    """
    先把一個序列從中間分開,然後把兩個序列再次分開,直到只有一個元素為止,
    然後兩兩排序合併,再四四排序合併,再八八排序合併...最後合併到一起
    """

    def merge(left, right):
        result = []  # 新的已排序好的列表
        i = 0  # 下標
        j = 0
        # 對兩個列表中的元素 兩兩對比。
        # 將最小的元素,放到result中,並對當前列表下標加1
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result += left[i:]
        result += right[j:]
        return result

    if len(seq) <= 1:
        return seq
    mid = len(seq) // 2  # 將列表分成更小的兩個列表
    # 分別對左右兩個列表進行處理,分別返回兩個排序好的列表
    left_list = mergesort(seq[:mid])
    right_list = mergesort(seq[mid:])
    # 對排序好的兩個列表合併,產生一個新的排序好的列表
    return merge(left_list, right_list)


def heapsort(seq: list):
    def make_heap(data: list):
        """
        把陣列變成一個大頂堆.
        :param data:
        :return:
        """
        length = len(data)

        # 遍歷所有的父結點位置,從後往前遍歷
        for parentNode in range(length // 2 - 1, -1, -1):
            while True:
                # 當前節點的左子節點
                sonNode = parentNode * 2 + 1
                if sonNode >= length:
                    break
                # sonNode+1 是右子節點
                # 若右子節點在最後一個節點之前,並且右子節點比左子節點大,把孩子指標移到右子節點上,這樣就可以交換更大的數
                if (sonNode + 1 <= length - 1) and (data[sonNode + 1] > data[sonNode]):
                    sonNode += 1
                if data[parentNode] < data[sonNode]:
                    data[sonNode], data[parentNode] = data[parentNode], data[sonNode]
                else:
                    break

    # 依次取出第0項,然後重建堆
    result = []
    length = len(seq)
    for end in range(length):
        make_heap(seq)
        result.append(seq.pop(0))
    return result


if __name__ == '__main__':
    import random

    source = [random.randint(0, i) for i in range(5, 999)]
    # source = [6, 5, 7, 2, 11, 4, 10, 2, 5, 3, 1, 9, 6, 4]
    print('-', source)

    # maopao(source)
    # choice(source)
    # insert(source)
    # print(mergesort(source))
    sorts = source.copy()
    sorts.sort(reverse=True)
    aa = heapsort(source)
    print(sorts == aa)