创建堆的方式有两种,一种是一边插入结点,一边调用堆的插入方法调整堆,这样的时间复杂度就是
O(NlogN),而第二种方式就把时间复杂度缩减到了O(N),它是采用先把结点插入好了,然后再来调整堆,并不是一边插入一边调整。
但是从代码层面来看,可能会误以为第二种方式的时间复杂度也是O(NlogN),但第二种方式是从下往上建立堆。举个例子,如下所示,假设堆中存在了N个节点(满足堆的性质),采用第一种方式,再创建N个结点,那么插入第一个数时,就调用了时间复杂度为logN的插入方法,插入N个数后,时间复杂度为logN。
让我们看看第二种方式会如何?
先把N个结点创建到树中,把这N个结点具体化,我们看到在调整树时,第一次是以倒数第二层的结点作为根节点,然后来调整这棵子树,也就是它的时间复杂度不再是logN了,因为远远没到N个结点,远远没到整颗树的高度,它的时间复杂度应该如下判断,在最坏情况下,树中每个结点,会一直向下查找,一直到底,假设树高为h,则倒数第二层会向下查找1次,倒数第三层会向下查找2次…
倒数第二层结点数为2(h-2),倒数第三层2h-3…
JAVA代码实现
import java.util.ArrayList;
import java.util.Arrays;//必须传入一个Comparable的实现类,因为后续会用到类的内部比较器
public class Heap<E extends Comparable> {Comparable<? super E>[] list;//堆--存储Comparable的实现类int size; //堆长度int capacity;//堆容量public Heap(int capacity){this.capacity=capacity;size=0;list=new Comparable[capacity+1];}//初始化public void Init(E value,int index){if(index>0){ list[index]= value;size++;}elsenew RuntimeException("下标越界");}//创建堆public void Build_Max_Heap(){for(int i=size/2;i>0;i--){int child=0;int parent = i;Comparable par_X= (E) list[i];for(;parent*2 <= size;parent=child){child=parent*2;if(child+1<=size && list[child].compareTo((E) list[child+1]) ==-1)child++;if(par_X.compareTo((E) list[child])==1)break;list[parent]=list[child];}list[parent]=(E) par_X;}}//插入堆public void Insert(E node){list[++size]=node;for(int i=size;i/2>=0;i=i/2){if(i==1 || list[i/2].compareTo((E)node)==1){list[i]=node;break;}else{list[i]=list[i/2];}}}//删除堆public E Delete(){Comparable DeleteX=list[1];Comparable X=list[size--];int child=1;int parent=1;for(;parent*2<=size;parent=child){child=parent*2;if(child+1<=size && list[child].compareTo((E)list[child+1])==-1 )child++;if(X.compareTo((E)list[child])==-1)list[parent]=list[child];elsebreak;}list[parent]=X;return (E)DeleteX;}//测试数据public static void main(String[] args) {Heap<SSS> heap = new Heap<>(10);heap.Init(new SSS(1),1);heap.Init(new SSS(2),2);heap.Init(new SSS(3),3);heap.Init(new SSS(4),4);heap.Init(new SSS(5),5);heap.Insert(new SSS(6));heap.Build_Max_Heap();heap.Delete();for(int i=1;i<=heap.size;i++)System.out.println(heap.list[i]);}
}
class SSS implements Comparable {int X;@Overridepublic int compareTo(Object o) {SSS s2=(SSS) o;if(X>s2.X)return 1;if(X<s2.X)return -1;else return 0;}public SSS(int X){this.X=X;}@Overridepublic String toString() {return "SSS{" +"X=" + X +'}';}
}