1.01 堆(heap)
是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。
堆的性质
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。
最大堆
将根节点最大的堆叫做最大堆或大根堆。
最小堆
根节点最小的堆叫做最小堆或小根堆。
常见的堆有二叉堆、斐波那契堆等。
堆支持的基本操作:
build:建立一个空堆;
insert:向堆中插入一个新元素;
update:将新元素提升使其符合堆的性质;
get:获取当前堆顶元素的值;
delete:删除堆顶元素;
heapify:使删除堆顶元素的堆再次成为堆。
某些堆实现还支持其他的一些操作,如斐波那契堆支持检查一个堆中是否存在某个元素。
1.02 二叉堆


1.03 MaxHeap基于动态数组的最大堆类的定义
- 定义类
public class MaxHeap<E extends Comparable<E>>
- 定义成员变量
public ArrayList<E> data;
- 定义构造函数
public MaxHeap(int capacity){ //自定义堆的大小
data=new ArrayList<E>(capacity);
}
public maxHeap(){
data=new ArrayList<>();
}
public MaxHeap(E[] arr){ //自定义堆时 传入一个数组
data=new ArrayList<E>(arr);
for(int i=parent(arr.length-1);i>=0;i--){
siftDown(i);
}
}
- 定义功能(全部通过数组角标操作元素)
//返回堆中的元素个数
public int size(){
return data.getSize();
}
//堆是否为空
public boolean isEmpty(){
return data.isEmpty();
}
//用数组表示堆 给定一个点 返回其父亲节点的角标
private int parent(int index){
if(index==0){
throw new IllegalArgumentException("node parent");
}
return (index-1)/2;
}
//用数组表示堆 给定一个点 返回其左孩子节点的角标
private int leftChild(int index){
return index*2+1;
}
//用数组表示堆 给定一个点 返回其右孩子结点的角标
private int rightChild(int index){
return index*2+2;
}
//向堆中添加元素
public void add(E e){
data.addLast(e); //元素添加到末尾后
siftUp(data.getSize()-1); //新添加的元素上浮
}
//将新加入的元素上浮
private void siftUp(int k){
while(k>0&&data.get(parent(k)).compareTo(data.get(k))<0){ //不是根节点并且其父亲节点的值小于当前节点的值
data.swap(k,parent(k)); //元素交换
k=parent(k); //重置要上浮元素的角标
}
}
//返回堆中的最大值
public E findMax(){
if(data.isEmpty()){
throw new IllegalArgumentException("head is null");
}
return data.getFirst();
}
//删除堆中的最大值
public E extractMax(){
E ret=findMax(); //找到最大值
data.swap(0,data.getSize()-1) ; //将最大值和数组最后一个元素交换
data.removeLast(); //删除最后一个元素
siftDown(0); //数组第一个元素下沉
return ret;
}
//将第一个元素下沉
private void siftDown(int k){
while(leftChild(k)<data.getSize()){ //没到叶子结点
int j=leftChild(k);
if(j+1<data.getSize()&&data.get(j+1).compareTo(data.get(j))>0){ //右子树没到叶子结点并且右节点的值大于左节点的值
j=rigthChild(k);
}
if(data.get(k).compareTo(data.get(j))<0){ //要下沉的元素小于左右子树结点中较大的一个时
data.swap(k,j); //交换 元素实现下沉
k=j; //重置要下沉元素的角标
}else{ //下沉结束
break;
}
}
}
//去除最大元素后,放入一个新元素
public E replace(E e){
E ret=findMax(); //找打最大的元素
data.set(0,e); //修改元素
siftDown(0); //元素下沉
return ret;
}
1.04 优先队列
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。
普通队列:先进先出,后进后出
优先队列:出队顺序和入队顺序无关,和优先级相关,本质还是队列
优先队列是0个或多个元素的集合,每个元素都有一个优先权或值。
优先队列的操作:
(1)查找 查找操作用来搜索优先权最小的元素,
(2)插入一个元素
(3)删除
优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。
应用:
(1)任务管理器中:动态选择优先级最高的任务执行
(2)游戏中:塔防优先攻击(距离,威胁,先后)
1.04 PriorityQueue基于最大堆实现的优先对列的定义
public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
private MaxHeap<E> heap;
public priorityQueue(){
heap=new MaxHeap<E>();
}
public void enqueue(E e){ //入队
heap.add(e);
}
public E dequeue(){ //出队
return heap.extractMax(); //删除堆中最大的元素
}
public E getFront(){ //获取对头
return heap.findMax();
}
public int getSize(){ //对的有效长度
return heap.size();
}
public boolean isEmpty(){ //对是否为空
return heap.isEmpty();
}
}
对比普通线性结构有何区别?

本文介绍了堆的概念,包括最大堆和最小堆,以及二叉堆等不同类型。接着详细讲解了二叉堆的实现,特别是MaxHeap类的设计。此外,还探讨了优先队列,它是一种根据优先级决定出队顺序的特殊队列,常通过堆来实现。最后,讨论了优先队列的应用及其与普通队列的区别。
959

被折叠的 条评论
为什么被折叠?



