堆操作(1)-堆中插入元素,删除元素

一、堆定义

堆是一个优先队列,右二叉树来表示,其特性:

  1. 是一颗完全二叉树
  2. 任意节点的元素是其子树的最大值(最小值)
    1. 最大值,大顶堆
    2. 最小值,小顶堆

示例:

完全二叉树用数组继续存储。定义如下:

public class HeapStruct {
    private Integer[] elements;//用数组存储
    private Integer capacity;//带表数组的容量

    public HeapStruct(Integer capacity) {
        this.capacity = capacity;
        this.elements = new Integer[capacity];
    }

    public Integer[] getElements() {
        return elements;
    }

    public Integer getCapacity() {
        return capacity;
    }
    //代表实际存储的元素
    public Integer getSize() {
        int index = 0;
        for (Integer data : elements) {
            if (data != null) {
                index++;
            }
        }
        return index;
    }
}

二、向堆中插入一个元素

插入一个元素后要保证还是一个堆,就要保证对的两个属性不能变(完全二叉树和任意元素的值大于其子树的值)。

  1. 保证完全二叉树:首先将新插入的元素插入的数组的最后面。
  2. 保证如何节点元素大于其子树:在1的基础上继续调整,如果新插入的数据大于其父节点,和父节点继续交换,一直比较到小于父节点或者新插入的数据变成整个二叉树的根节点为止。
    public static void insert(HeapStruct heapStruct, Integer data) {
        if (heapStruct.getCapacity().equals(heapStruct.getSize())) {
            return;//full
        }
        int currentIndex = heapStruct.getSize();//放到最后
        Integer[] elements = heapStruct.getElements();
        while (currentIndex > 0) {
            int parentIndex = currentIndex / 2;//父节点对应的index
            if (elements[parentIndex] < data) {//父节点的元素比插入的值要小。
                elements[currentIndex] = elements[parentIndex];//父节点下移。
                currentIndex = parentIndex;//继续往上找
            } else {
                break;
            }
        }
        elements[currentIndex] = data;
    }

三、从堆中删除一个元素

堆的删除只在对顶进行。删除后还得保证是一个堆。

具体思路是。

  1. 对顶元素直接删除后返回
  2. 把最后一个元素放置到堆顶。
  3. 然后用堆顶元素和左右儿子进行对比,把三者最大的和堆顶元素进行交换【最大的儿子上移】。
public static Integer deleteMax(HeapStruct heapStruct) {
        if (heapStruct == null || heapStruct.getSize() == 0) {
            return null;
        }
        Integer[] elements = heapStruct.getElements();
        Integer maxValue = elements[0];//直接删除堆顶返回
        Integer finalValue = elements[heapStruct.getSize() - 1];//最后一个元素,当做堆顶,持续和左右儿子进行对比
        int parent = 0;
        while (parent * 2 <= heapStruct.getSize() - 1) {
            int child = parent * 2 + 1;
            if (child > heapStruct.getSize() - 1 && elements[child].compareTo(elements[child + 1]) < 0) {
                child = child + 1;//右儿子大。最大的儿子找到
            }
            if (finalValue.compareTo(elements[child]) > 0) {//最后一个元素和最大的儿子进行比较,如果最后的元素大,说明可以做顶,找到了位置。
                break;
            } else {
                elements[parent] = elements[child];//儿子大,儿子上移。持续下一轮的对比。
                parent = child;
            }
        }
        elements[parent] = finalValue;
        elements[heapStruct.getSize() - 1] = null;
        return maxValue;
    }
posted @ 2021-09-23 23:09  ibrake  阅读(2065)  评论(0编辑  收藏  举报