jdk1.8 PriorityQueue源码学习笔记

一、堆在这里里面是一个逻辑上的概念,源码实现的是一个小顶堆,
二、优先级队列的状态 ,如果是小顶堆 最小值是第一个元素 。
如果以树形结构看这个实现,最小值是根元素,并且子节点大于等于父节点,
三、看图理解更丝滑,实际上数据存放在一个数组中
在这里插入图片描述
4、部分源码个人理解(结合上图理解代码)

堆的构造代码,
注意  元素的下标以0开始,从下标(size >>> 1) - 1的元素开始,执行下沉操作,操作的目的就是把小的值放到 i 上。即把小的元素 上提,以树的视图看 就是子元素大于等于父元素
private void heapify() {
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }

这个方法是根据是否设置比较器选择对应扽方法,我们只看siftDownComparable方法
private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }


//这里执行真正的下沉操作,删除元素或者从集合初始化堆会执行下沉操作1)、while循环的目的是下沉直到遇到叶子节点,
k < half 为非叶子节点,反之为叶子节点。
(2)、如果不是叶子节点获取它的两个子节点 左节点 : child = (k << 1) + 1 右节点:right = child + 1,如果 right < size 并且 左节点大于右节点把最小值赋给c 并且 小的下标赋给child,就是c中保存最小值 child保存最小值的下标。接下来如果传入的key如果小于最小值循环退出,执行 queue[k] = key;赋值。
如果 right < size 并且 左节点大于等于右节点,此时c中仍然保存最小值 child保存最小值的下标,这是如果传入的值key大于最小值则执行
 queue[k] = c; k = child;及把小的值上提并且让k保存小值的下标,如果下标k对应的元素不是叶子节点继续执行上述循环。
 (3)、下沉过程中都是拿子节点最小值和key进行比较
private void siftDownComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>)x;
        int half = size >>> 1;        // loop while a non-leaf
        while (k < half) {
            int child = (k << 1) + 1; // assume left child is least
            Object c = queue[child];
            int right = child + 1;
            if (right < size &&
                ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
                c = queue[child = right];
            if (key.compareTo((E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        }
        queue[k] = key;
    }


//上浮操作 添加元素会执行上浮操作
//(1)、(k - 1) >>> 1或者父节点下标,如果插入的元素大于等于父元素直接退出循环,否则执行
queue[k] = e; k = parent;把父元素下沉为的是让插入元素上浮,然后让parent赋值给k,如果没有到堆顶继续执行循环,最后确定的key的位置。
private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (key.compareTo((E) e) >= 0)
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = key;
    }

//移除对应索引位置的元素
//
private E removeAt(int i) {
        // assert i >= 0 && i < size;
        modCount++;
        int s = --size;
        if (s == i) // removed last element
            queue[i] = null;
        else {
            E moved = (E) queue[s];
            queue[s] = null;
            siftDown(i, moved);
            if (queue[i] == moved) {//这里说明下沉失败就是说moved元素小于等于他的两个子元素,否则不用执行上浮操作提高效率,。如果上面的下沉成功浮上来的元素不可能比他父节点小。
                siftUp(i, moved);//执行上浮操作
                if (queue[i] != moved)
                    return moved;//如果上浮成功返回move
            }
        }
        return null;
    }

个人理解 有误地方多谢指教

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值