数据结构 最大堆的实现

定义:

最大堆要求根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值。

 

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) );

    }
}

结果:


总结:

关键点在于熟悉最大堆的基础是完全二叉树,下标的关系是很重要的信息。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值