IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 2021-07-04优先级队列 -> 正文阅读

[数据结构与算法]2021-07-04优先级队列

目录

1.概述

2.重要方法解读

2.1 构造函数?

2.2 方法“堆化”

2.3?出队

2.4 入队

2.5 其他的方法

3.小结


1.概述

  1. ?优先级队列的底层实现是基于堆排序
  2. 所谓优先级队列,其全局的优先级是通过一步一步访问队头元素之后呈现的,在某一时刻,其队列中的堆从上到下是不严格有序的,这是堆的性质导致的,因为堆只要求父子之间的有序,而不要求兄弟之间的有序。也就是说,队列中出队头元素外的元素们之间在还没有出队时不是严格有序的。其实它们都没有内部排队。
  3. 成员:
    1. 一个数组 Object[],名叫queue,用于存放数据,按照完全二叉树的形式,且queue[0]是队头。即 queue[parent]的两个孩子是?queue[2*parent+1]、queue[2*parent+2]
    2. 一个比较器 Comparator

2.重要方法解读

2.1 构造函数?

    public PriorityQueue(Collection<? extends E> c) {
        if (c instanceof SortedSet<?>) {
        // code 1
            SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
            this.comparator = (Comparator<? super E>) ss.comparator();
            initElementsFromCollection(ss);
        }
        else if (c instanceof PriorityQueue<?>) {
        // code 2
            PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
            this.comparator = (Comparator<? super E>) pq.comparator();
            initFromPriorityQueue(pq);
        }
        else {
            this.comparator = null;
        // code 3 实际上的初始化方法
            initFromCollection(c);
        }
    }
  1. code1 按照有序集合来初始化
  2. code2 按照优先级队列来初始化,内部直接是把复用引用
  3. code3 是实际的初始化方:保存元素到queue数组中,并“堆化”,后者是优先级队列的“本质”

2.2 方法“堆化”

    private void heapify() {
        // 从倒数第一个非叶子节点开始 siftDown
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }
    /**
    * 把元素x放到k的位置上。是堆化的原子操作——重要!重要!重要!
    */
    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. 以上是堆排序的对核心的代码,当然也是优先级队列的。
  2. 堆化之后,该队就是小顶堆了。下面我们看出队和入队

2.3?出队

    public E poll() {
        if (size == 0)
            return null;
        int s = --size;
        modCount++;
        // code1
        E result = (E) queue[0];
        E x = (E) queue[s];
        queue[s] = null;
        if (s != 0)
        // code2
            siftDown(0, x);
        return result;
    }
  1. code1,就是直接返回队头元素 queue[0]
  2. code2,把最后一个元素从队头处插入——注意不是插到队头
  3. siftDown函数在上面已经分析过,就是自伤向下的调整成堆,是堆化的原子操作。

2.4 入队

    public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        modCount++;
        int i = size;
        if (i >= queue.length)
            grow(i + 1);
        size = i + 1;
        if (i == 0)
            queue[0] = e;
        else
        // code1 自下往上的调整
            siftUp(i, e);
        return true;
    }
    /**
    * 自下往上的调整。把元素x从位置k插入
    */
    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;
    }
  1. siftUp是与siftDown相反的防线进行调整,调整的目标一致——堆化,但是具体动作不同,代码中已有注释。
  2. siftUp是仅此于siftDown重要的操作单元了。

2.5 其他的方法

????????主要方法已经讲完了,其他的方法也分类:

  1. 广义的重载方法,比如add(Element)/peek()等
  2. 画蛇添足的方法,比如remove(Object),因为对于队列来讲,就是入队出队。
  3. 比较基础的方法,比如size()/toArray()

3.小结

? ? ? ? 结构性小结。

? ? ? ? 并不想写太细,但是必须突出其精髓。另外就是给自己做的笔记,虽然这笔记也太迟了。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-05 20:27:23  更:2021-07-05 20:27:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 16:33:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码