【Hello】堆的实现-基于数组

堆的实现-基于数组

package com.gm.heap;

import java.util.ArrayList;
import java.util.List;

/**
 * 堆的结构
 */
public class HelloHeap {
    /**
     * 数组,存放堆数据
     */
    private int[] heap;
    /**
     * 堆的大小,
     * 也是堆中最后一个元素的数组下标
     */
    private int size;
    /**
     * 堆的最大容量,数组长度-1
     */
    private int capacity;

    /**
     * C1-建堆
     *
     * @param capacity
     */
    public HelloHeap(int capacity) {
        if (capacity < 2) {
            throw new RuntimeException("堆容量至少为2");
        }
        this.capacity = capacity;
        this.heap = new int[capacity];
        this.size = 0;
    }

    /**
     * R1-遍历输出堆
     */
    public void printAll() {
        //每一层的首节点下标
        List<Integer> everyFloorFirstIndex = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            everyFloorFirstIndex.add((int) Math.pow(2, i));
        }
        for (int index = 1; index < size + 1; index++) {
            if (everyFloorFirstIndex.contains(index)) {
                System.out.println();
            }
            System.out.print("    " + this.heap[index]);

        }
        System.out.println();
    }

    /**
     * C2-增加一个元素(大顶堆)
     *
     * @param val
     * @return
     */
    public boolean insert(int val) {
        if (this.capacity - 1 == this.size) {
            System.out.println("堆已满");
            return false;
        }
        //当前val应该被插入的数组下标
        int curIndex = this.size + 1;
        this.heap[curIndex] = val;
        //自下向上堆化
        //父节点下标不为0,并且val大于父节点值,向上交换,循环
        while (curIndex / 2 > 0 && val > this.heap[curIndex / 2]) {
            int parentVal = this.heap[curIndex / 2];
            this.heap[curIndex / 2] = val;
            this.heap[curIndex] = parentVal;
            //继续向上遍历
            curIndex = curIndex / 2;
        }
        ++size;
        return true;
    }

    /**
     * D-删除头节点(大顶堆)
     * 实现思路,将最后一个元素放在堆顶,然后
     * 利用同样的父子节点对比方法,解决数组空洞问题
     *
     * @return
     */
    public boolean deleteHead() {
        if (this.size == 0) {
            return false;
        }
        this.heap[1] = this.heap[size];
        --this.size;
        int curIndex = 1;
        while (true) {
            //自上向下堆化
            if (curIndex * 2 > this.size) {
                break;
            }
            //左右两个节点都有
            if (curIndex * 2 < this.size) {
                if (this.heap[curIndex * 2] > this.heap[curIndex * 2 + 1]) {
                    swap(curIndex, curIndex * 2);
                    curIndex = curIndex * 2;
                } else {
                    swap(curIndex, curIndex * 2 + 1);
                    curIndex = curIndex * 2 + 1;
                }
                continue;
            }
            //只有左节点
            if (curIndex * 2 == this.size) {
                if (this.heap[curIndex * 2] > this.heap[curIndex]) {
                    swap(curIndex, curIndex * 2);
                }
            }
            curIndex = curIndex * 2;
        }
        return true;
    }

    /**
     * 交换
     *
     * @param curIndex 当前下标
     * @param target   目标下标
     */
    private void swap(int curIndex, int target) {
        int tmp = this.heap[curIndex];
        this.heap[curIndex] = this.heap[target];
        this.heap[target] = tmp;
    }


    public static void main(String[] args) {
        //测试1
//        HelloHeap helloHeap2 = new HelloHeap(2);
//        helloHeap2.insert(1);
//        helloHeap2.insert(2);
//        helloHeap2.printAll();
//        System.out.println("===========");
        //测试2
        HelloHeap helloHeap10 = new HelloHeap(20);
        helloHeap10.insert(3);
        helloHeap10.insert(2);
        helloHeap10.insert(1);
        helloHeap10.insert(4);
        helloHeap10.insert(5);
        helloHeap10.insert(6);
        helloHeap10.insert(7);
//        helloHeap10.insert(8);
//        helloHeap10.insert(9);
//        helloHeap10.insert(-1);

        helloHeap10.printAll();
        System.out.println("删除结果:" + helloHeap10.deleteHead());
        helloHeap10.printAll();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值