一、前言
之前用java實現堆結構,一直用的優先隊列,但是在實際的面試中,可能會要求用數組實現,所以還是用java老老實實的實現一遍堆結構吧。
二、概念
堆,有兩種形式,一種是大根堆,另一種是小根堆。堆,一般是二叉樹,這個概念當然也可以擴展到k叉樹。大根堆指的是根節點的值要大於左子樹和右子樹所有節點值,堆的子樹也是堆。小根堆的概念同理可知。
三、實現過程
堆的形式是一棵樹,但是我們可以用數組來實現它,父節點和孩子節點的父子關系通過數組下標來確定。
它的左右孩子節點和父節點的位置,如上圖所示。
在接下來的實現過程,我們使用第二種表示方式,也就是說節點的編號是從0開始。
(1)首先我們需要定義一個節點的左右孩子的位置和根節點的位置。
// find the index of left children public static int left(int i){ return (i+1)*2 -1; } // find the index of right children public static int right(int i){ return (i+1)*2; } // find the index of parent public static int parent(int i){ return (i-1)/2; }
(2)其次我們需要保持堆的結構。所謂保持堆結構,指的是:讓它的根節點始終比它的左右子樹大(大頂堆)或者小(小頂堆)。具體做法就是在根節點和左右子樹的根節點的值進行對比,如果根節點就是最大的話,就結束;否則就將根節點和最大值的位置互換,然后遞歸的變更最大值。
//keep the max heap structure public static void heapkeep(int[] a, int i, int heaplength){ int l = left(i); int r = right(i); int largest = i; if(l<heaplength&&a[i]<a[l]){ largest = l; } if(r<heaplength&&a[largest]<a[r]){ largest = r; } if(largest!=i){ int temp = a[largest]; a[largest] = a[i]; a[i] = temp; heapkeep(a, largest, heaplength); } }
(3)構建堆。構建堆的方法很簡單,就是自底向上的構建堆。
// create the heap public static int heapcreate(int[] a, int length){ if(a.length<length){ return -1; }else{ int pr = parent(length-1); for(int i = pr;i>=0;i--){ heapkeep(a, i, length); } return 0; } }
上述實現過程,實現的大頂堆,如果想要實現小頂堆的話只需要修改一下heapkeep函數的判斷條件。