版权声明:文章为作者原创,若要转载请获得作者同意。尊重版权,从你我做起! https://blog.csdn.net/qq_37768971/article/details/88565545
一、概念介绍
1.最大堆;
(1)最大堆是一颗完全二叉树、
(2)堆中某个节点的值总是不大于其父节点的值(最大堆)
(3)在数组中表示最大堆
【若数组采用以index=0为根节点】
- Parent(i)=(i-1)/2
- Left child=2*i+1
- Right child=2*i+2
2.优先队列
(1)优先队列是队列中的一种特殊情况;
(2)入队后会自动将优先级最高的元素往前排序;
(3)出队是不按照先进先出,而是优先级高的先出队;
(4)本次数据结构实现以最大堆为基础来实现优先队列。
二、实现的基本功能:
1.最大堆:
isEmpty()
getSize()
void add(E e)
E findMax()
E extractMax()
E replace(E e)
2.优先队列:
getSize;
getFront;
isEmpty;
enqueue;
dequeue;
三、代码及相关注释:
1.最大堆:
package IMUHERO;
public class MaxHeap <E extends Comparable<E>>{
public Array<E> data;
public MaxHeap(int capacity){
data=new Array<>(capacity);
}
public MaxHeap(){
data=new Array<>();
}
//heapify,将一个数组转换成最大堆
/*Heapify:
①寻找最后一个非叶子结点,方法:先找到最后一个叶子结点(length-1),通过这个叶子结点找到它的 父亲节点。
②通过sift down方法调整大小位置(父亲节点永远大于子节点);
③再使用一层循环逐渐递减直至i=0,完成所有非叶子结点的遍历工作。*/
public MaxHeap(E [] arr){
data=new Array<>(arr);
for (int i=parent(arr.length-1);i>=0;i--){
siftDown(i);
}
}
public boolean isEmpty(){
return data.isEmpty();
}
public int getSize(){
return data.getSize();
}
private int parent (int index){
return (index-1)/2;
}
private int leftChild(int index){
return index*2+1;
}
private int rightChild(int index){
return index*2+2;
}
/* 2.添加元素
*①向最后一个位置添加元素(length-1);
*②对比该元素与父亲节点的大小,若大于父亲节点则交换位置
*③重复上述操作,只至父亲节点大于子节点*/
public void add(E e){
data.addLast(e);
siftUp(data.getSize()-1);
}
private void siftUp(int index){
while(index>0&&data.get(parent(index)).compareTo(data.get(index))<0){
data.swap(parent(index),index);
index=parent(index);
}
}
public E findMax(){
if (getSize()==0)throw new IllegalArgumentException("There is no element exist");
return data.get(0);
}
/*3.取出最大元素
(1)小技巧:
①将数组下标为0(二叉树根节点)的元素取出
②将子节点最后一个替换成根节点,注意删除最后一个子节点
③设计使用Sift Down方法,将当前根节点与自己的两个子节点进行比较,选择较大的子节点进行比较。重 复该操作,直至到达最后一层。*/
public E extractMax(){
E reMax=findMax();
data.swap(0,getSize()-1);
data.removeLast();
siftDown(0);
return reMax;
}
/*4.siftDown(int index)
Int j=leftChild(k)
① 判断当前index的左孩子是否大于length(是否有左孩子)
② 判断当前index的左孩子是否有右孩子,如果有则判断左右孩子的大小,若右孩子大于左孩子则j++,否则不变;
③ SWAP 父子节点
④ 重复上述判断,直至父亲节点大于等于子节点;*/
private void siftDown(int index){
if (index<0||index>getSize())throw new IllegalArgumentException("Index is illegal");
while(leftChild(index)<getSize()){
int j=leftChild(index);
if (j++<getSize()&&data.get(j).compareTo(data.get(j+1))<0)
j++;
if (data.get(j).compareTo(data.get(index))<=0) {
break; //父亲节点大于等于子节点中最大的值则直接跳出循环
}
data.swap(j,index);//如果子节点中有比父亲节点大,则交换并进行下一轮判断
index=j;
}
}
public E replace(E e){
E reMax=findMax();
data.set(0,e);
siftDown(0);
return reMax;
}
}
2.优先队列:(基于最大堆实现)
package IMUHERO;
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
package IMUHERO;
public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
MaxHeap<E> priorityQueue=new MaxHeap<>();
@Override
public boolean isEmpty() {
return priorityQueue.isEmpty();
}
@Override
public int getSize() {
return priorityQueue.getSize();
}
@Override
public void enqueue(E e) {
priorityQueue.add(e);
}
@Override
public E dequeue() {
return priorityQueue.extractMax();
}
@Override
public E getFront() {
return priorityQueue.findMax();
}
}
注:关于数据结构的所有代码都放在我的Github上,有需要的同学可以自行Fork,如果觉得还不错,可以打个☆Star哦~~~