首页 > 编程语言 > 数据结构之优先队列(java)

数据结构之优先队列(java)

时间:2023-11-25 19:06:32浏览次数:38  
标签:优先 java 队列 出队 childIndex array 数据结构 节点

一:概述

队列的特点是:先进先出(FIFO).入队列,将元素置于队尾;

                            数据结构之优先队列(java)_二叉堆

出队列,队头元素最先被移出:

                            数据结构之优先队列(java)_出队_02

优先队列不遵循先入先出的原则,而是分两种情况。

  • 最大优先队列,无论入队顺序如何,都是当前最大的元素优先出队
  • 最小优先队列,无论入队顺序如何,都是当前最小的元素优先出队。

例如有一个最大优先队列,其中的最大元素是8,那么虽然8不是队头元素,但出队时仍然让元素8首先出队。

                            数据结构之优先队列(java)_出队_03

需要实现上述的需求,利用线性数据结构并不能实现,但是时间复杂度较高。

二:具体说明

上述这个需求可以利用二叉堆去实现。

二叉堆的特性:

最大堆的堆顶是整个堆中的最大元素。

最小堆的堆顶是整个堆中的最小元素。

所以,可以利用最大堆来实现最大优先队列,每一次入队操作都是堆的插入操作,每一次出队操作都是删除堆顶节点。

<1>入队具体操作步骤如下:

  1. 插入新节点5.

                            数据结构之优先队列(java)_出队_04

  1. 新节点5”上浮“到合适的位置。

                            数据结构之优先队列(java)_二叉堆_05

<2>出队操作具体步骤如下。

  1. 让原堆点节点10出队

                            数据结构之优先队列(java)_优先队列_06

  1. 把最后一个节点1替换到堆顶位置。

                            数据结构之优先队列(java)_出队_07

  1. 节点1”下沉“,节点9成为新堆顶。

                            数据结构之优先队列(java)_二叉堆_08

二叉堆节点”上浮“和”下浮“的时间复杂度都是O(logn),所以优先队列入队和出队时间复杂度也是O(logn).

下面是优先队列的代码实现:

import java.util.Arrays;

/**
 * 优先队列
 *
 */
public class PriorityQueue {
    private int[] array;
    private int size;

    public PriorityQueue() {
        // 队列初始长度为32
        array = new int[32];
    }


    /**
     * 入队
     *
     * @param key 入队元素
     */
    public void enQueue(int key) {
        // 队列长度超出范围,扩容
        if (size >= array.length) {
            resize();
        }
        array[size++] = key;
        upAdjust();
    }


    /**
     * 出队
     *
     * @return 返回堆顶元素
     * @throws Exception 异常处理
     */
    public int deQueue() throws Exception {
        if (size <= 0) {
            throw new Exception("the queue is empty!");
        }
        // 获取堆顶元素
        int head = array[0];
        // 让最后一个元素移动到堆顶
        array[0] = array[--size];
        downAdjust();
        return head;
    }

    /**
     * "上沉" 调整
     */
    private void upAdjust() {
        int childIndex = size - 1;
        int parentIndex = (childIndex - 1) / 2;
        // temp保存插入的叶子节点值,用于最后的赋值
        int temp = array[childIndex];
        while (childIndex > 0 && temp > array[parentIndex]) {
            // 无须真正交换,单项赋值即可
            array[childIndex] = array[parentIndex];
            childIndex = parentIndex;
            parentIndex = parentIndex / 2;
        }
        array[childIndex] = temp;
    }


    /**
     * "下沉操作"
     */
    private void downAdjust() {
        // temp保存父节点的值,用于最后的赋值
        int parentIndex = 0;
        int temp = array[parentIndex];
        int childIndex = 1;
        while (childIndex < size) {
            if (childIndex + 1 < size && array[childIndex + 1] > array[childIndex]) {
                childIndex++;
            }
            // 如果父节点大于任何一个孩子的值,直接跳出
            if (temp >= array[childIndex])
                break;
            // 无须真正交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        array[parentIndex] = temp;

    }


    /**
     * 队列扩容
     */
      public void resize() {
        // 队列容量翻倍
        int newSize = this.size * 2;
        this.array = Arrays.copyOf(this.array, newSize);
      }


       public static void main(String[] args) throws Exception {
          // 创建一个优先队列的对象
          PriorityQueue priorityQueue = new PriorityQueue();
         // 调用封装好的入队方法,向队列中插入元素
         priorityQueue.enQueue(3);
         priorityQueue.enQueue(5);
         priorityQueue.enQueue(10);
         priorityQueue.enQueue(2);
         priorityQueue.enQueue(2);
         priorityQueue.enQueue(7);
         System.out.println("出队元素:" + priorityQueue.deQueue());
         System.out.println("出队元素:" + priorityQueue.deQueue());
       }

/*
 上述代码采用数组来存储二叉堆的元素,因此当元素数量超过数组长度时,需要进行扩容来扩大数组长度
 */

三:树、二叉树、二叉堆、优先队列的总结

什么是树:

树是n个节点的有限集,有且仅有一个特定的称为根的节点。当n > 1时,其余节点可分为m个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。

什么是二叉树:

二叉树是树的一种特殊形式,每一个节点最多有两个孩子节点。二叉树包含完全二叉树和满二叉树两种特殊的形式。

二叉树的遍历方式:

根据遍历节点之间的关系,可以分为前序遍历、中序遍历、后序遍历、层序遍历这4种方式;从更宏观的角度的划分,可以划分为深度优先遍历和广度优先遍历两大类。

什么是二叉堆

二叉堆是一种特殊的完全二叉树,分为最大堆和最小堆。

在最大堆中,任何一个父节点的值,都大于或等于它的左、右孩子节点的值。

在最小堆中,任何一个父节点的值,都小于或等于它的左、右孩子节点的值。

什么是优先队列

优先队列分为最大优先队列和最小优先队列

在最大优先队列中,无论入队顺序如何,当前最大的元素都会优先出队,这是基于最大堆实现的。

在最小优先队列中,无论入队顺序如何,当前最小元素都会优先出队,这是基于最小堆实现的。

标签:优先,java,队列,出队,childIndex,array,数据结构,节点
From: https://blog.51cto.com/u_15912723/8561558

相关文章

  • Day05 Java程序运行机制
    Java程序运行机制编译型解释型如同中国人写了一本书美国人想看编译型就类似把整本书全部翻译成美国人看得懂的书(中文书-->英文书)解释型就类似美国人找了个翻译官翻译一段美国人看一段(说一句解释一句用一下编译一下)程序运行机制源程序(*.java)文件-->Jav......
  • Day08 Java关键字和标识符
    Java关键字和标识符首先Java的所有组成部分都需要有名字类名、方法名、变量名都被称为标识符如HelloWorld中publicclassHello{ publicstaticvoidmain(String[]args){Stringteacher="秦疆"; System.out.print("Hello,World!"); }}关键词有publicclas......
  • Day09 Java的数据类型
    Java的数据类型强类型语言(安全性高速度略慢)要求变量的使用要严格符合规定,所有变量都必须先定义后才能便用弱类型语言(安全性不高速度较快)publicclassDemo02{publicstaticvoidmain(String[]args){Stringa="hello";intnum=10;......
  • JavaWeb中的文件上传和下载功能的实现
    导入相关支持jar包:commons-fileupload.jar,commons-io.jar对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件......
  • JavaWeb-文件的上传和下载
    文件上传1.要有一个form标签,method=post请求2.form标签的encType属性的值必须为multipart/form-data值3.在from标签中使用inputtype=file添加上传的文件4.编写服务器代码接收上传的数据Content-Type:表示提交的数据类型enctype="multipart/form-data":表示提交的数据,以多段(每......
  • java日期的使用
    ......
  • java - 您使用 ARM Jazelle 的体验如何?
    java-您使用ARMJazelle的体验如何?标签 java embedded jvm arm jazelle 我正在为ARM在开源和闭源JVM之间进行评估。特别是,闭源JVM可以利用Jazelle(用于较新ARM的java加速)。您对这项技术有任何经验吗?(顺便说一句,您使用哪个操作系统?) 最佳答......
  • java Calendar常见方法使用
    ......
  • Java日期加减
    Java日期加减目录1.使用Calendar2.使用LocalDate类3.使用Date类 概括:在开发Java应用程序时,经常需要对日期进行加减操作。日期的加减操作在很多场景下都非常有用,比如计算某个事件发生前后的日期,计算某个日期之后的一段时间等等。本文将介绍Java中进行日期加减的方......
  • JavaWeb实现文件上传和下载
    环境配置:导入依赖jar包。commons-fileupload-1.4.jarcommons-io-2.6.jar上传表单的enctype属性enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。语法<formenctype="value">1属性值值 描述application/x-www-form-urlencoded 在发送前编码所有字符(默认)multi......