1. 自顶向下
一个结点一个结点的插入到堆的顶部,每次插入最多要进行h(树的已有高度)次调整,每一层结点数为2^h,那么每层总共时间复杂度通项为
k*2^k, k取0到h。h = logn(底数为2),所以对k从0-h层求积分(用分布积分,把底数2看成e)求得
nlogn - n = n(logn -1)
logn * n = o(nlogn).
其实上面这个是不对的,因为特殊的数据将导致堆不平衡,高度就不再是logn了,所以建议下面中各种方法。
2.自下向上
要排序的结点已经都存到数组里了,直接对数组进行调整使之成为堆
这里的自下向上的意思实际上是从子堆开始调整,子堆调整完成后就可以调整父堆了。每次调整子堆,也是每次把子堆自顶向下的进行调整,只不过不用插入
将数组下标看成对应树的结点编号。从有非叶节点的最高层那一层开始,由高层到低层逐层遍历结点的判断结点与左右儿子是否满足堆,不满足就交换o(1),并且递归判断其子树(因为交换后他们的的子树的根结点发生了变化,子树可能不再是堆)o(h-k)。然后一层结点判断完后就判断上一层。假设共h层,则第k层最多经历(h - k)次调整好它的左右子树,每层2^k个结点,所以每层总共时间通项为
2^k * (h-K);k从0 到h积分得到n - h -1;为o(n)