堆排序的最好,最壞的時間複雜度都爲nlogn。當我們需要對一個沒有順序的序列進行堆排序,首先需要將這批數據轉化成堆。一般來說,對序列進行降序排列一般使用大頂堆。大頂堆必須滿足:data[index] >= data[2*index + 1] 並且滿足data[index] >= data[2*index + 2]。前提是父節點有相應的子節點。按照定義,我們需要找到所有的非葉子節點,因爲按照堆的定義,我們只需要交換父節點和某個子節點的值,當它們之間的關係不滿足堆。
對於大頂堆。爲什麼要從下往上,從左往右呢?至於爲什麼要從左往右,想必大家都知道,這是沿着序列索引遞減的方向,我很容易的就能控制當前的索引,說白了就是爲了方便;從下往上,主要是按照順組建立大頂堆,這是個遞歸的過程。最後整棵樹中的每一個堆都是大頂堆。下面給出python編制的代碼:
import sys import math # 向上取整 class Solution: def __init__(self): pass def re_shape(self, data, final_index): tmp = final_index while True: cur_change = False if final_index == 0: parent_index = 0 else: parent_index = math.ceil(final_index / 2.0) - 1 # 第一個父節點 left_child = 2 * parent_index + 1 right_child = left_child + 1 # print([parent_index, left_child, right_child]) if left_child <= final_index: if right_child <= final_index: max_param = max([data[left_child], data[right_child]]) index = data.index(max_param) if max_param > data[parent_index]: data[parent_index], data[index] = data[index], data[parent_index] cur_change = True elif data[left_child] > data[parent_index]: data[parent_index], data[left_child] = data[left_child], data[parent_index] cur_change = True final_index = left_child - 1 # 新的起點 if cur_change and final_index <= 0: final_index = tmp if not final_index: return data else: return data def get_data(self): str_dig = sys.stdin.readline().split() try: data = list(map(lambda x: int(x), str_dig)) final_index = len(data) - 1 for cur_index in range(0, len(data), 1): data = self.re_shape(data, final_index) data[0], data[final_index] = data[final_index], data[0] final_index -= 1 return data except: assert 'Error' if __name__ == '__main__': so = Solution() sys.stdout.write(str(so.get_data()))
30 40 67 74 65 75 120 4 6 90 [4, 6, 30, 40, 65, 67, 74, 75, 90, 120] Process finished with exit code 0