Java实现堆(最大堆)
程序员文章站
2022-03-31 19:08:06
...
1、什么是堆
现在有这么一个需求,设计一个结构,满足两个操作要求:
- 删除时,返回该结构的最大值或者最小值的元素
- 往结构中新增元素
问题:如何组织优先这种结构?
- 一般数组、链表?
- 有序数组或者链表?
- 二叉搜索树或者AVL树?
结构 | 插入 | 删除 |
---|---|---|
数组 | 插到数组尾部时间复杂度O(n) | 查找最大或者最小值,删除后需要移动元素,时间复杂度O(2n) |
链表 | 插入到链表头部,时间复杂度 O(1) | 查找最大或者最小值,删除结点,时间复杂度O(n) |
有序数组 | 查找插入位置,插入后移动元素并且插入,时间复杂度O(2n) | 删除尾部,时间复杂度O(1) |
有序链表 | 查找插入位置,插入节点,时间复杂度O(n) | 删除首或者尾节点,时间复杂度O(1) |
二叉搜索树 | 查找节点位置,插入,时间复杂度为log2(n), | 找到根节点右子树最大的节点,时间复杂度为O(n) |
如果在用二叉树结构
- 删除的时候怎么设计?
- 插入又应该怎么设计?
堆:完全二叉树结构
堆的结构定义
public class Heap {
Integer[] data;
int capacity; //堆容量
int size; //堆中元素个数
int max=100000;
public Heap(){
this.capacity = 10;
this.data = new Integer[capacity+1];
//定义"哨兵"为大于堆中所有可能元素的值
data[0] = max;
}
public Heap(int capacity) {
this.data = new Integer[capacity+1];
this.capacity = capacity;
data[0] = max;
}
}
2、最大堆的插入
- 首先在堆尾部(数组的尾部)
- 判断插入节点是否大于父节点,如果大于的话,插入节点和父节点互换位置,重复上述操作,直到出现插入节点小于父节点或者插入节点一路互换后变成根节点。
public void insert(int value) {
if (this.size==capacity) {
this.data = (Integer[]) Arrays.copyOf(this.data, capacity * 2);
}
data[++size] = value;
for (int i=size;i>0;i/=2) {
if (data[i]>data[i/2]) {
swap(data,i,i/2); //数组中两数交换
}
}
}
3、最大堆的删除
- 首先保存要返回的根节点
- 保存堆最后一个节点为X
- 从根节点往下遍历,如果根节点的左右儿子有大于X的,那么左右儿子中大的值设置为根节点,将左右儿子中较大的节点作为该节点的儿子节点的根节点,重复上述判断。最后如果出现X大于根节点的左右儿子节点或者根节点为叶子节点时,将当前根节点设置为X。
private Integer delete() {
if (size==0){
return null;
} else {
int parent,chrild = 0;
int maxValue = data[1];
int X = data[size--];
for (parent = 1; parent<=size; parent = chrild) {
chrild = parent*2;
if (chrild!=size && (data[chrild]<data[chrild+1])) {
chrild++;
}
if (X>data[chrild]) {
break;
} else {
data[parent] = data[chrild];
}
}
data[parent] = X;
data[size+1] = null;
return maxValue;
}
}
4、最大堆的建立
从堆最后一位的父节点开始,将该节点作为根节点,把该节点的堆调整为最大堆,然后依次取前一位父节点,直到根节点调整结束。
public void createMaxHeap(int[] heap) {
for ( int i=size/2; i>0;i/=2) {
percDown(heap,i);
}
}
private void percDown(int[] heap, int i) {
int parent,chrild = 0;
int X = data[i];
for (parent = 1; parent<=size; parent = chrild) {
chrild = parent*2;
if (chrild!=size && (data[chrild]<data[chrild+1])) {
chrild++;
}
if (X>data[chrild]) {
break;
} else {
data[parent] = data[chrild];
}
}
data[parent] = X;
}
上一篇: 机器人AI的制作
下一篇: 树形结构----最大堆与优先队列