Java14/堆

一 优先级队列(堆)

通过层序遍历将二叉树放入数组中,即使用数组保存二叉树结构。
对于完全二叉树的下标关系:
leftChild = 2parent+1;
rightChild = 2parent +2;
parent = (child-1)/2;

1 堆(heap)
  • 堆逻辑上是一个完全二叉树
  • 堆保存在数组中
  • 任意节点的值都大于其子节点的值,称为大堆
  • 任意节点的值都小于其子节点的值,称为小堆
  • 堆能够快速找到集合中的最值
2 通过向下调整,建立一个大堆
public class TestHeap {
    public int[] elem;
    public int usedSize;
    public TestHeap(){
        this.elem = new int[10];
        this.usedSize=0;
    }
 //1 向下调整,建立一个大堆
    public void createHeap(int[] array){
        //传入一个数组,赋值给elem
        for (int i = 0; i <array.length ; i++) {
            this.elem[i] = array[i];
            this.usedSize++;
        }
        //this.usedSize-1为最后一个节点,
        // (最后一个节点-1)/2为最后一个子树的父节点
        for(int i=(this.usedSize-1-1)/2;i>=0;i--){
            //每一棵树都按照向下调整的方式进行调整为一个大堆
            AdjustDown(i,this.usedSize);
        }
    }

    public void AdjustDown(int root,int len){
        //len为数组长度
        int parent = root;
        int child = 2*parent+1;
        //child<len说明该父节点有左节点
        while(child<len){
            //child+1<len说明有右节点,然后比较左右孩子大小,让child指向大值
            if(child+1<len&&this.elem[child]<this.elem[child+1]){
                child = child+1;
            }
            //child是左右孩子的最大值下标
            if(this.elem[child]>this.elem[parent]){
                //交换
                int tmp = this.elem[child];
                this.elem[child]=this.elem[parent];
                this.elem[parent]=tmp;
                //向下调整被打乱的子树顺序
                parent = child;
                child = 2*parent+1;
            }else{
                break;
            }
        }
    }
3 入堆(大堆)
 // 3 入堆,前提是已经是一个大根堆
    public boolean isFull(){
        return this.usedSize==this.elem.length;
    }

    public void pushHeap(int val){
        //elem数组如果满了则先扩容
        if(isFull()){
            //二倍扩容
            this.elem = Arrays.copyOf(this.elem,this.elem.length*2);
        }
        //将入堆元素放到最后位置
        this.elem[this.usedSize] = val;
        this.usedSize++;
        //开始向上调整,this.usedSize-1指向最后一个位置
        AdjustUp(this.usedSize-1);
    }
    public void AdjustUp(int child) {
        int parent = (child-1)/2;
        while (child > 0) {
            if(this.elem[child] > this.elem[parent]) {
                int tmp = this.elem[child];
                this.elem[child] = this.elem[parent];
                this.elem[parent] = tmp;
                // 向上调整 child 指向 parent
                child = parent;
                parent = (child-1)/2;
            }else {
                break;
            }
        }
    }
4 出堆(大堆)
    // 4 出堆
    public boolean isEmpty(){
        return this.usedSize==0;
    }
    public void popHeap(){
        if(isEmpty()){
            return;
        }
        //第一个元素和最后一个元素互换,用this.usedSize--剔除最后一个元素
        int tmp = this.elem[0];
        this.elem[0] = this.elem[this.usedSize-1];
        this.elem[this.usedSize-1]=tmp;

        this.usedSize--;
        //向下调整,this.usedSize为数组长度,0为传入的父节点
       AdjustDown(0,this.usedSize);
    }

5 堆排序
// 5  堆排序,从小到大,本例中的都是大根堆
//时间复杂度n*log2n以2为底
//空间复杂度o(1)
//一次调整的时间复杂度log2n以2为底
public void heapSort() {
    //end最后元素的下标
    int end = this.usedSize-1;
    while (end > 0) {
        int tmp = this.elem[end];
        this.elem[end] = this.elem[0];
        this.elem[0] = tmp;
        //不断的将大元素往后排,最后完成从小到大的排序
        //此处end代表数组大小
        AdjustDown(0,end);
        end--;
    }
}
6 Java中的优先级队列(默认为小堆)

PriorityQueue implements Queue

抛出异常 返回特殊值
入队列 add(e) offer(e)
出队列 remove() poll()
队首元素 element() peek()
发布了54 篇原创文章 · 获赞 6 · 访问量 4819

猜你喜欢

转载自blog.csdn.net/glpghz/article/details/103762623