【数据结构】之二叉堆

这里我就不演示了,给大家推荐一个网站:数据结构和算法动态可视化

里面很多常见的数据结构和算法都能动态的演示出来。

五、代码实现


二叉堆虽然是一颗完全二叉树,但是并不是用链式结构存储的,因完全二叉树的性质,可以存储在数组当中。

在这里插入图片描述

数组中,在没有左右指针的情况下,如何定位到一个父节点的左孩子和右孩子呢?

像图中那样,我们可以依靠数组下标来计算。

假设父节点的下标是parent,那么它的左孩子下标就是 2_parent+1;它的右孩子下标就是 2_parent+2 。

比如上面例子中,节点6包含9和10两个孩子,节点6在数组中的下标是3,节点9在数组中的下标是7,节点10在数组中的下标是8。

7 = 3*2+1

8 = 3*2+2

刚好符合规律。

有了这个前提,下面的代码就更好理解了:

package com.algorithm.heap.binaryHeap;

import java.util.Random;

/**

  • @author riemann

  • @date 2019/09/04 0:09

*/

public class BinaryHeap {

private int elementCount;

private int[] elements;

private static final int DEFAULT_CAPACITY = 16;

private static final int MAXIMUM_CAPACITY = 1 << 30;

public BinaryHeap() {

this(DEFAULT_CAPACITY);

}

public BinaryHeap(int[] data) {

this();

for (int d : data) {

push(d);

}

}

public BinaryHeap(int capacity) {

elements = new int[tableSizeFor(capacity)];

}

/**

  • 入队

  • @param data 入队数据

*/

public void push(int data) {

if (elements.length - 1 == elementCount) {

resize((elementCount + 1) << 1);

}

elements[++elementCount] = data;

floatElement(elementCount);

}

/**

  • 出队

  • @return 返回队列最大或者最小值

*/

public int pop() {

if (elements.length < elementCount >> 2) {

resize(elementCount >> 2);

}

int res = elements[1];

swap(1, elementCount);

elements[elementCount–] = 0;

sinkElement();

return res;

}

/**

  • 查看队首元素

  • @return 返回队列第一个元素

*/

public int peek() {

return elementCount == 0 ? -1 : elements[1];

}

/**

  • 元素个数

  • @return 返回元素个数

*/

public int size() {

return elementCount;

}

/**

  • 检验非空

  • @return TRUE 队列为空

*/

public boolean isEmpty() {

return elementCount == 0;

}

/**

  • 重新设置elements元素大小

  • @param size 新数组的大小

*/

private void resize(int size) {

if (size > MAXIMUM_CAPACITY) {

// TODO

}

int[] newElements = new int[size];

copyArray(elements, newElements);

elements = newElements;

}

/**

  • 元素上浮

  • @param index 上浮元素索引位置

*/

private void floatElement(int index) {

while (index > 1 && elements[index >> 1] < elements[index]) {

swap(index >> 1, index);

index >>= 1;

}

}

/**

  • 元素下沉

*/

private void sinkElement() {

int index = 1;

while (index << 1 <= elementCount &&

(elements[index] < elements[index << 1] || elements[index] < elements[(index << 1) + 1])) {

int p = index << 1;

int i = elements[p] > elements[p + 1] ? p : p + 1;

swap(index, i);

index = (i & 0x01) == 1 ? (index << 1) + 1 : index << 1;

}

}

/**

  • HashMap中的方法,把传入参数变为下一个 1 << n (2的n次方大于 cap 并且 2的n-1次方小于 cap)

  • @param cap 改变的参数

  • @return 1 << n

*/

private static int tableSizeFor(int cap) {

int n = cap - 1;

n |= n >>> 1;

n |= n >>> 2;

n |= n >>> 4;

n |= n >>> 8;

n |= n >>> 16;

return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;

}

/**

  • 数组复制

  • @param source 被复制的源数组

  • @param target 复制目标数组

*/

private static void copyArray(int[] source, int[] target) {

System.arraycopy(source, 0, target, 0, source.length);

}

/**

  • 交换数组两元素位置

  • @param indexA 元素A的索引位置

  • @param indexB 元素B的索引位置

*/

private void swap(int indexA, int indexB) {

int temp = elements[indexA];

elements[indexA] = elements[indexB];

elements[indexB] = temp;

最后

学习视频:

大厂面试真题:

length);

}

/**

  • 交换数组两元素位置

  • @param indexA 元素A的索引位置

  • @param indexB 元素B的索引位置

*/

private void swap(int indexA, int indexB) {

int temp = elements[indexA];

elements[indexA] = elements[indexB];

elements[indexB] = temp;

最后

学习视频:

[外链图片转存中…(img-XfRJtOxr-1721164882479)]

大厂面试真题:

[外链图片转存中…(img-912KTnKY-1721164882479)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值