算法3-高級排序
阿新 • • 發佈:2018-02-13
元素 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-高級排序