目录
堆实际就是在完全二叉树的基础之上进行了一些元素的调整。
如果有一个 关键码的集合 K = {k0 , k1 , k2 , … , kn-1} ,把它的所有元素 按完全二叉树的顺序存储方式存储 在一 个一维数组中 ,并满足: Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >=K2i+2) i = 0 , 1 , 2… ,则 称为小堆 ( 或大堆) 。(即双亲比孩子的数值小(大)——小(大)堆)将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
大根堆:每一个子树都是父节点的值最大。
小根堆:每一个子树都是父节点的值最小。
堆都是完全二叉树。

我这里是创建大根堆,进行向下调整
如下图:对于集合 {36,69,16,18,25,41,9,20,11,50} 中的数据,如果将其创建成堆呢?


就上图而言,两个方框内的子树,只需要把子树左右节点的值和父节点的只进行比较然后交换就好,但是,
我们根据二叉树的性质来倒推。
首先,最后一棵子树的最后一个孩子节点是数组 长度 - 1
确定了孩子节点再来确定父节点, 父节点下标 =(孩子节点的下标- 1)/ 2
总结:最后一棵子树的根节点下标 = (数组长度 - 1 - 1)/ 2
根节点 = 最后那棵子树根节点 - 1
其实主要就是在每一棵子树上去进行调整!
- public int[] elem;
- public int usedSize;//当前堆当中的有效的元素的数据个数
-
- public void intiArr(int[] arr) {
- this.elem = Arrays.copyOf(arr, arr.length);
- this.usedSize = elem.length;
- }
- public static void main(String[] args) {
- TestHeap testHeap = new TestHeap();
- int[] arr = {68,17,36,2,9,1,23,11,18};
- testHeap.intiArr(arr);
- }
parent是父节点
- /**
- * 创建大根堆
- * @param arr
- */
- public void createBigHeap(int[] arr) {
- for (int parent = (usedSize - 1 - 1) / 2; parent >= 0; parent--) {
- shiftDown(parent, usedSize);
- }
- }
将parent与较小的孩子child比较,如果:parent小于较小的孩子child,调整结束。否则:交换parent与较小的孩子child,交换完成之后,parent中大的元素向下移动,可能导致子树不满足对的性质,因此需要继续向下调整,即parent = child;child = parent*2+1; 然后继续2。
- /**
- * 向下调整
- * @param parent
- * @param len
- */
- public void shiftDown(int parent, int len) {
- int child = 2 * parent + 1;
- //最起码是有左孩子
- while (child < len) {
- //判断 左孩子 和 右孩子 谁最大,前提是 必须有 右孩子
- if (child+1 < len && elem[child] < elem[child+1]) {
- child++;//此时 保存了最大值的下标
- }
- if (elem[child] > elem[parent]) {
- swap(elem,child,parent);
- parent = child;
- child = 2*parent+1;
- }else {
- break;
- }
- }
- }
- //交换函数
- public static void swap(int[] arr, int i, int j) {
- int tmp = arr[i];
- arr[i] = arr[j];
- arr[j] = tmp;
- }
插入步骤:
- /**
- * 插入
- * @param x
- */
- public void offer(int x) {
- if(isFull()) {
- elem = Arrays.copyOf(elem,elem.length*2);
- }
- this.elem[usedSize] = x;
- usedSize++;
- shiftDown((usedSize-1-1)/2, usedSize);
- }
-
- public boolean isFull() {
- return usedSize == elem.length;
- }
删除步骤:
- /**
- * 删除
- */
- public int poll() {
- if(isEmpty()) {
- return -1;
- }
- int old = elem[0];
- swap(elem,0,usedSize-1);
- usedSize--;
- shiftDown(0,usedSize);
- return old;
- }
-
- public boolean isEmpty() {
- return usedSize == 0;
- }