定义:
最大堆要求根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值。
API
API代码实现
api分析:
最大堆为完全二叉树,index(子节点)/2=index(父节点)
操作中采用了哨兵,所以对应元素下标即为堆中的位置(从1开始)
insert():插入时插到末尾,通过与父节点的比较,进行上浮操作
deleteMax(MaxHeap H):得到根节点的值并删除,把最末尾的数字放到根节点,进行下沉操作
buildHeap(MaxHeap H):从最末尾节点的父节点开始,对该树进行调整,然后前进一个节点,接着调整
public class MaxHeap {
int Size;
int Capacity;
int[] Data;
/*
创建规定容量的堆
*/
public MaxHeap(int capacity) {
Size = 0;
Capacity = capacity;
Data = new int[capacity];
}
/*
直接赋值data
*/
public MaxHeap(int capacity, int[] data) {
Capacity = capacity + 1;
Data = data;
Size = Data.length - 1;
}
/*
创建空的最大堆,设置哨兵
*/
public static MaxHeap createMaxHeap(int MaxSize) {
MaxHeap maxHeap = new MaxHeap(MaxSize + 1);
maxHeap.Data[0] = 999;
return maxHeap;
}
/*
isFull
*/
public static boolean isFull(MaxHeap maxHeap) {
return maxHeap.Capacity == maxHeap.Size + 1;
}
/*
insert
将元素插入堆中,元素data[0]已经定义为哨兵
*/
public static boolean insert(MaxHeap maxHeap, int x) {
if (isFull(maxHeap)) {
System.out.println("满了兄弟");
return false;
}
int i = ++maxHeap.Size;
for (; maxHeap.Data[i / 2] < x; i /= 2) {
//大于父结点时,父节点的值下沉
maxHeap.Data[i] = maxHeap.Data[i / 2];
}
maxHeap.Data[i] = x;
return true;
}
/*
isEmpty
*/
public static boolean isEmpty(MaxHeap maxHeap) {
return maxHeap.Size == 0;
}
/*
delete
*/
public static int deleteMax(MaxHeap maxHeap) {
int Parent, Child;
int MaxItem, X;
if (isEmpty(maxHeap)) {
System.out.println("最大堆已经为空");
return 0;
}
//取出堆的最大值,即第一个元素,把最后的元素换到第一个,向下开始交换
MaxItem = maxHeap.Data[0];
X = maxHeap.Data[maxHeap.Size--];
Child = 0;
//判断是否有子节点
for (Parent = 1; Parent * 2 <= maxHeap.Size; Parent = Child) {
Child = Parent * 2;
//判断是否有右结点,并得到较大的位置
if ((Child != maxHeap.Size) && (maxHeap.Data[Child] < maxHeap.Data[Child + 1])) {
Child++;
}
//和较大者进行比较,若X>该值,则不用交换,否则交换
if (X >= maxHeap.Data[Child]) break;
else {
maxHeap.Data[Parent] = maxHeap.Data[Child];
}
}
//退出循环,说明找到了合适的位置,把X的值赋值过去
//这样就只要交换N次
maxHeap.Data[Parent] = X;
return MaxItem;
}
/*
建造最大堆
*/
public static void buildHeap(MaxHeap maxHeap) {
//调整元素,使得满足最大堆的有序性
int i;
//从最后一个结点的父节点开始,直到根节点
for (i = maxHeap.Size / 2; i > 0; i--) {
percDown(maxHeap, i);
}
}
/*
建造最大堆,将做右子节点中的较大值和根节点进行比较
调整
*/
public static void percDown(MaxHeap maxHeap, int p) {
int Parent, Child;
int X;
//根节点的值
Child = 0;
X = maxHeap.Data[p];
//循环中调整
for (Parent = p; Parent * 2 <= maxHeap.Size; Parent = Child) {
Child = Parent * 2;
if ((Child != maxHeap.Size) && (maxHeap.Data[Child] < maxHeap.Data[Child + 1])) {
Child++;
}
if (X >= maxHeap.Data[Child]) break;
else {
maxHeap.Data[Parent] = maxHeap.Data[Child];
}
}
maxHeap.Data[Parent] = X;
}
}
测试:
public class HeapTest {
public static void main(String[] args) {
MaxHeap maxHeap=MaxHeap.createMaxHeap(10);
System.out.println("---");
System.out.println("isEmpty "+ MaxHeap.isEmpty(maxHeap));
System.out.println("---");
for (int i=0;i<10;i++){
MaxHeap.insert(maxHeap, (int) (Math.random()*90));
}
System.out.println("insert "+ Arrays.toString(maxHeap.Data));
System.out.println("---");
System.out.println("isFull "+ MaxHeap.isFull(maxHeap));
System.out.println("---");
int x= MaxHeap.deleteMax(maxHeap);
System.out.println("Max "+ x );
System.out.println("delete Max "+ Arrays.toString(maxHeap.Data));
System.out.println("---");
int[] arrayy={99,44,33,22,33,55,2,4,1};
MaxHeap maxHeap2=new MaxHeap(10,arrayy);
MaxHeap.buildHeap(maxHeap2);
System.out.println("after build "+ Arrays.toString(maxHeap2.Data) );
}
}
结果:
总结:
关键点在于熟悉最大堆的基础是完全二叉树,下标的关系是很重要的信息。