思路:
1.建立堆
2.得到堆頂元素,為最大元素
3.去掉堆頂,將堆最后一個元素放到堆頂,此時可通過一次調整重新使堆有序。
4.堆頂元素為第二大元素。
5.重復步驟3,直到堆變空。
動畫
代碼:
def sift(data, low, high): i = low # 父節點 j = 2 * i + 1 # 左子節點 tmp = data[i] # 父節點值 while j <= high: # 子節點在節點中 if j < high and data[j] > data[j + 1]: # 有右子節點且右節點比父節點值大 j += 1 if tmp > data[j]: data[i] = data[j] # 將父節點替換成新的子節點的值 i = j # 變成新的父節點 j = 2 * i + 1 # 新的子節點 else: break data[i] = tmp # 將替換的父節點值賦給最終的父節點 def heap_sort(data): n = len(data) # 創建堆 for i in range(n//2-1, -1, -1): sift(data, i, n-1) # 挨個出數 for i in range(n-1, -1, -1): # 從大到小 data[0], data[i] = data[i], data[0] # 將最后一個值與父節點交互位置 sift(data, 0, i-1) li = list(range(10)) random.shuffle(li) print(li) heap_sort(li) print(li)
實例:
將列表內的數據以id的值從小到大排序
def random_list(n): ''' 生成隨機數據 :param n: :return: ''' ret = [] a1 = ['趙', '錢', '孫', '李', '鄒', '吳', '鄭', '王', '周'] a2 = ['力', '好', '禮', '麗', '文', '建', '梅', '美', '高', ''] a3 = ['強', '文', '斌', '闊', '文', '瑩', '超', '雲', '龍', ''] ids = range(1001, 1001 + n) for i in range(n): name = random.choice(a1) + random.choice(a2) + random.choice(a3) age = random.randint(18, 60) dic = {'id': ids[i], 'name': name, 'age': age} ret.append(dic) return ret def sift(data, low, high): i = low # 父節點 j = 2 * i + 1 # 左子節點 tmp = data[i] # 父節點值 while j <= high: # 子節點在節點中 if j < high and data[j]['id'] < data[j + 1]['id']: # 有右子節點且右節點比父節點值大 j += 1 if tmp['id'] < data[j]['id']: data[i] = data[j] # 將父節點替換成新的子節點的值 i = j # 變成新的父節點 j = 2 * i + 1 # 新的子節點 else: break data[i] = tmp # 將替換的父節點值賦給最終的父節點 def heap_sort(data): n = len(data) # 創建堆 for i in range(n//2-1, -1, -1): sift(data, i, n-1) # 挨個出數 for i in range(n-1, -1, -1): # 從大到小 data[0], data[i] = data[i], data[0] # 將最后一個值與父節點交互位置 sift(data, 0, i-1) li = random_list(1000) # 生成數據 random.shuffle(li) # 將數據打亂 heap_sort(li) print(li)