1. 程式人生 > >算法3-高級排序

算法3-高級排序

元素 pre gif range set ltmp shuffle 現在 hid

快速排序:快
快排思路:
取一個元素p(第一個元素),使元素p歸位;
列表被p分成兩部分,左邊都比p小,右邊都比p大;
遞歸完成排序。
技術分享圖片
import random
from timewrap import *
import copy
import sys


sys.setrecursionlimit(100000)

def partition(li, left, right):
    # ri = random.randint(left, right)
    # li[left], li[ri] = li[ri], li[left]
    tmp = li[left]
    while
left < right: while left < right and li[right] >= tmp: right -= 1 li[left] = li[right] while left < right and li[left] <= tmp: left += 1 li[right] = li[left] li[left] = tmp return left def _quick_sort(li, left, right):
if left < right: # 至少有兩個元素 mid = partition(li, left, right) _quick_sort(li, left, mid-1) _quick_sort(li, mid+1, right) @cal_time def quick_sort(li): return _quick_sort(li, 0, len(li)-1) @cal_time def sys_sort(li): li.sort() li = list(range(10000)) random.shuffle(li)
#sys_sort(li1) quick_sort(li)
快排示例代碼

堆排序

建立堆
得到堆頂元素,為最大元素
去掉堆頂,將堆最後一個元素放到堆頂,此時可通過一次調整重新使堆有序。
堆頂元素為第二大元素。
重復步驟3,直到堆變空。
技術分享圖片
from timewrap import *
import random

def _sift(li, low, high):
    """
    :param li:
    :param low: 堆根節點的位置
    :param high: 堆最有一個節點的位置
    :return:
    """
    i = low  # 父親的位置
    j = 2 * i + 1  # 孩子的位置
    tmp = li[low]  # 原省長
    while j <= high:
        if j + 1 <= high and li[j + 1] > li[j]:  # 如果右孩子存在並且右孩子更大
            j += 1
        if tmp < li[j]:  # 如果原省長比孩子小
            li[i] = li[j]  # 把孩子向上移動一層
            i = j
            j = 2 * i + 1
        else:
            li[i] = tmp  # 省長放到對應的位置上(幹部)
            break
    else:
        li[i] = tmp  # 省長放到對應的位置上(村民/葉子節點)


def sift(li, low, high):
    """
    :param li:
    :param low: 堆根節點的位置
    :param high: 堆最有一個節點的位置
    :return:
    """
    i = low         # 父親的位置
    j = 2 * i + 1   # 孩子的位置
    tmp = li[low]   # 原省長
    while j <= high:
        if j + 1 <= high and li[j+1] > li[j]: # 如果右孩子存在並且右孩子更大
            j += 1
        if tmp < li[j]: # 如果原省長比孩子小
            li[i] = li[j]  # 把孩子向上移動一層
            i = j
            j = 2 * i + 1
        else:
            break
    li[i] = tmp


@cal_time
def heap_sort(li):
    n = len(li)
    # 1. 建堆
    for i in range(n//2-1, -1, -1):
        sift(li, i, n-1)
    # 2. 挨個出數
    for j in range(n-1, -1, -1):    # j表示堆最後一個元素的位置
        li[0], li[j] = li[j], li[0]
        # 堆的大小少了一個元素 (j-1)
        sift(li, 0, j-1)


li = list(range(10000))
random.shuffle(li)
heap_sort(li)
print(li)

# li=[2,9,7,8,5,0,1,6,4,3]
# sift(li, 0, len(li)-1)
# print(li)
示例代碼

歸並排序

假設現在的列表分兩段有序,如何將其合成為一個有序列表
這種操作稱為一次歸並。
分解:將列表越分越小,直至分成一個元素。
終止條件:一個元素是有序的。
合並:將兩個有序列表歸並,列表越來越大。
技術分享圖片
import random
from timewrap import *
import copy
import sys


def merge(li, low, mid, high):
    i = low
    j = mid + 1
    ltmp = []
    while i <= mid and j <= high:
        if li[i] < li[j]:
            ltmp.append(li[i])
            i += 1
        else:
            ltmp.append(li[j])
            j += 1
    while i <= mid:
        ltmp.append(li[i])
        i += 1
    while j <= high:
        ltmp.append(li[j])
        j += 1
    li[low:high+1] = ltmp


def _merge_sort(li, low, high):
    if low < high:  # 至少兩個元素
        mid = (low + high) // 2
        _merge_sort(li, low, mid)
        _merge_sort(li, mid+1, high)
        merge(li, low, mid, high)
        print(li[low:high+1])


def merge_sort(li):
    return _merge_sort(li, 0, len(li)-1)


li = list(range(16))
random.shuffle(li)
print(li)
merge_sort(li)

print(li)
示例代碼

算法3-高級排序