堆排序的最好,最坏的时间复杂度都为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