priority queue 优先队列堆

本文介绍了堆这种数据结构,特别是小顶堆的性质和操作。堆通常以数组形式存储,其中每个元素对应二叉树的一个节点。小顶堆保证每个节点的值小于或等于其子节点,堆顶元素是最小值。关键操作包括percolate up(插入元素后调整堆)和percolate down(保持堆性质)。通过这些操作,可以将无序数组转换为小顶堆。此外,还提及了如何将comparable数组转换为特定类型E的数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆:本质是数组,通常从下标1开始存储元素。以二叉树的形式展现堆时,堆内每一个元素对应一个节点,并且节点n的的左子树下标为2n,右子树的下标为2n+1。
每一个节点的父节点下标为[n/2]。

小顶堆:每个结点的值都小于或等于其左右子结点的值,堆顶元素必然是最小值。小顶堆的每一个子堆都是小顶堆。

堆的两个关键操作:
percolate up 已经有一个小顶堆,在尾部插入一个元素,这个元素依次和他的父节点交换,直到小于等于其父节点。此时新堆也是一个小顶堆。
percolate down 假设已有一个堆,堆顶的两个子堆都是小顶堆。这时候依次交换堆顶元素和他的较小的子节点,直到小于等于其较小的子节点。这时新堆也是一个小顶堆。

当向一个堆插入元素时,每次都将元素放置在堆数组的末尾,然后通过percolate up将新插入的元素放置在正确的位置,使新堆仍然是一个小顶堆。
当有一个无序数组需要构建成小顶堆时,可以从其最后一个有子节点的元素开始,对每一个元素执行percolate down直到第一个元素。相当于每次都将子堆变为小顶堆,然后再将父堆变为小顶堆。

泛型学习,下面是将一个comparable的数组强转为可比较的E类型的数组的方法:

heap = (E[]) new Comparable[this.capacity + 1]
package pers.machi.dataSturcture.priorityQueue;

import pers.machi.dataSturcture.disorderArr.DisorderArr;

class PriorityQueue<E extends Comparable<E>> { //堆的元素类型为泛型E,必须继承Comparable
    public static void main(String[] args) {
    }

    private int capacity = 0; //堆的容积,堆所能放置的最大元素个数,初始化后不可变
    private int size = 0; //当前堆元素的个数
    private E[] heap = null; //堆的数组


    public int getCapacity() {
        System.out.println("capacity: " + capacity);
        return capacity;
    }
    // 获得堆容积

    public int getSize() {
        System.out.println("size: " + size);
        return size;
    }
    // 获得当前堆元素个数


    public void initialize(int capacity) {
        this.capacity = capacity;
        size = 0;
        heap = (E[]) new Comparable[this.capacity + 1];
        heap[0] = null;
    }
    // 初始化堆,注意如何获得泛型E的数组

    public void putSentinel(E e) {
        heap[0] = e;
    }
    // 放置哨兵,个人习惯,在数组零的位置放置E类型的最小对象

    public boolean isFull() {
        if (size == capacity) {
            System.out.println("Priority queue is full");
            return true;
        } else
            return false;
    }
    // 判断是否填满

    public boolean isEmpty() {
        if (size == 0) {
            System.out.println("Priority queue is empty");
            return true;
        } else
            return false;
    }
    // 判断是否为空

    public void insert(E e) {
        if (isFull())
            return;
        int i = ++size;
        for (; heap[i / 2].compareTo(e) > 0; i /= 2)
            heap[i] = heap[i / 2];

        heap[i] = e;
    }
    // 插入元素,每次插入元素都要执行percolate up

    public E deleteMin() {
        if (isEmpty()) {
            return null;
        }

        E minElement = heap[1];
        E lastElement = heap[size];
        heap[size--] = null;

        int i;
        int child;
        for (i = 1; i * 2 <= size; i = child) {
            child = i * 2;
            if (child < size && heap[child].compareTo(heap[child + 1]) > 0)
                child++;

            if (lastElement.compareTo(heap[child]) > 0) {
                heap[i] = heap[child];
            } else {
                heap[child] = lastElement;
                break;
            }
        }
        return minElement;
    }
    // 删除最小元素,最小元素就是第一个元素,但是删除之后,要依次把被删除元素的较小子元素填充到被删除元素的位置上去

    public void printHeap() {
        int i = 1, j = 1;
        for (; i < capacity; i++) {
            System.out.print(heap[i] + "\t");
            if (i == Math.pow(2, j) - 1) {
                System.out.println();
                j++;
            }
        }
        System.out.println();
    }

    public void buildHeap(E[] heapToBuild,int heapToBuildSize) {
        int lastIndex = heapToBuildSize;
        E tmp;
        int j=-1;
        int child=-1;
        for (int i = lastIndex / 2; i > 0; i--) {

            tmp = heapToBuild[i];
            for (j = i; j*2 <= lastIndex; j = child) {
                child = j * 2;
                if ((child < lastIndex) && heapToBuild[child].compareTo(heapToBuild[child + 1]) > 0) {
                    child++;
                }
                if (tmp.compareTo(heapToBuild[child]) > 0) {
                    heapToBuild[j] = heapToBuild[child];
                } else
                    break;
            }
            heapToBuild[j]=tmp;
        }
    }
    // 构建堆,从下标为lastIndex/2的元素开始不断的percolate down
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值