数据结构-队列

本文详细介绍了Java中队列的几种实现方式,包括数组实现的循环队列、链表实现的队列,以及ArrayDeque的使用。讨论了它们的特点、优缺点和适用场景,特别提到了优先级队列和生产者-消费者问题的应用。
摘要由CSDN通过智能技术生成
  • 定义:队列是一种特殊的线性数据结构,它的特点是先进先出(FIFO,First In First Out)。
  • 循环队列的实现
    • 定义:循环队列是一种线性数据结构,其操作表现基于FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。
    • 数组实现
      static class QueueArray{
              private int maxSize;//定义数组最大容量
              private int front;//定义队列头
              private int rear;//定义队列尾
              private int[] data;//数据
              //初始化队列(构造器)
              //初始化队列
              public QueueArray(int maxSize) {
                  this.maxSize = maxSize;
                  this.front = 0;
                  this.rear = 0;
                  this.data=new int[maxSize];
              }
              //1.判断队列是否满
              public boolean isFull(){
                  return (rear+1)%maxSize==front;
              }
              //2.判断队列是否为空
              public boolean isEmpty(){
                  return rear==front;
              }
              //3.入队
              public void addQueue(int value){
                  if (isFull()){
                      System.out.println("队列已满");
                      return;
                  }
                  data[rear]=value;
                  rear=(rear+1)%maxSize;
              }
              //4.出队
              public int getQueue(){
                  if (isEmpty()){
                      throw new RuntimeException("队列为空");
                  }
                  //获取队头
                  int value = data[front];
                  front=(front+1)%maxSize;
                  return value;
              }
              //5.显示队列所有数据
              public void showQueue(){
                  if (isEmpty()){
                      throw new RuntimeException("队列为空");
                  }
                  System.out.println(Arrays.toString(data));
              }
              //6.显示队列头部数据
              public int showHead(){
                  if (isEmpty()){
                      throw new RuntimeException("队列为空");
                  }
                  return data[front];
              }
          }
      
    • 链表实现
      public class Node {
          int value;
          Node next;
      
          public Node(int value) {
              this.value = value;
              this.next=null;
          }
      }
      
      public class CircularLinkedQueue {
          private Node front;
          private Node rear;
          private int size;
          private int currentSize;
      
          public CircularLinkedQueue(int size) {
              front = null;
              rear = null;
              this.size = size;
              currentSize=0;
          }
          //判空
          public boolean isEmpty(){
              return currentSize==0;
          }
          //判满
          public boolean isFull(){
              return size==currentSize;
          }
          //入队
          public boolean enQueue(int value){
              if (isFull()){
                  System.out.println("队列已满,无法入队");
                  return false;
              }
              Node newNode = new Node(value);
              if(isEmpty()){
                  front=newNode;
                  rear=newNode;
              }else {
                  rear.next=newNode;
                  rear=newNode;
              }
              currentSize++;
              return true;
          }
          //出队
          public int dequeue(){
              if (isEmpty()){
                  System.out.println("队列为空,无法出队");
                  return -1;
              }
              int value = front.value;
              //最后一个节点出队
              if (front==rear){
                  rear=null;
              }
              front=front.next;
              currentSize--;
              return value;
          }
      }
      
      
    • 数组实现中队满浪费空间处理
      • 新增currentSize字段记录队列当前容量
         //判断队列是否满
         public boolean isFull(){
             return currentSize==maxSize;
         }
         //判断队列是否为空
         public boolean isEmpty(){
             return currentSize==0;
         }
         //入队
         public void addQueue(int value){
             if (isFull()){
                 System.out.println("队列已满");
                 return;
             }
             data[rear]=value;
             currentSize++;
             rear=(rear+1)%maxSize;
         }
         //出队
         public int getQueue(){
             if (isEmpty()){
                 throw new RuntimeException("队列为空");
             }
             //获取队头
             int value = data[front];
             front=(front+1)%maxSize;
             currentSize--;
             return value;
         }
        
  • 双端队列的实现
    • 定义:双端队列是一种特殊的队列,它允许元素从两端被插入和删除。
    • 数组实现
      public class DoubleQueue {
          private int[] data;
          private int front;
          private int rear;
          private int size;
          private int currentSize;
          public DoubleQueue(int size){
              this.size=size;
              this.data=new int[size];
              this.currentSize=0;
              front=0;
              rear=0;
          }
          //判空
          public boolean isEmpty(){
              return currentSize==0;
          }
          //判满
          public boolean isFull(){
              return currentSize==size;
          }
          //队头插入
          public boolean insertFront(int item){
              if (isFull()){
                  System.out.println("队满");
                  return false;
              }
              //队列为空
              if (isEmpty()){
                  data[front]=item;
                  currentSize++;
                  //队列不为空
              }else {
                  front=(front-1+size)%size;
                  data[front]=item;
                  currentSize++;
              }
              return true;
          }
          //队尾插入
          public boolean insertRear(int item){
              if (isFull()){
                  System.out.println("队满");
                  return false;
              }
              data[rear]=item;
              currentSize++;
              rear=(rear+1)%size;
              return true;
          }
          //队头删除
          public boolean deleteFront(){
              if (isEmpty()){
                  System.out.println("队空");
                  return false;
              }
              front=(front+1)%size;
              currentSize--;
              return true;
          }
          //队尾删除
          public boolean deleteRear(){
              if (isEmpty()){
                  System.out.println("队空");
                  return false;
              }
              rear=(rear-1+size)%size;
              currentSize--;
              return true;
          }
      }
      
    • 链表实现
      public class DequeNode {
          public int data;
          public DequeNode prev;
          public DequeNode next;
          public DequeNode(int data) {
              this.data = data;
              this.prev=null;
              this.next=null;
          }
      }
      
      public class LinkedDoubleDeque {
          private DequeNode head;
          private DequeNode tail;
      
          public LinkedDoubleDeque() {
              head = null;
              tail = null;
          }
          //队头添加元素
          public void addFirst(int value){
              DequeNode newNode = new DequeNode(value);
              if (head == null){
                  head = newNode;
                  tail = newNode;
              }else {
                  newNode.next = head;
                  head.prev = newNode;
                  head = newNode;
              }
          }
          //队尾添加元素
          public void addLast(int value){
              DequeNode newNode = new DequeNode(value);
              if (tail==null){
                  head=newNode;
                  tail=newNode;
              }else {
                  newNode.prev=tail;
                  tail.next=newNode;
                  tail=newNode;
              }
          }
          //队头删除元素
          public int removeFirst(){
              if (head==null){
                  throw new RuntimeException("队列为空");
              }
              int value = head.data;
              head=head.next;
              //删除的是最后的数据
              if (head==null){
                  tail=null;
              }else {
                  head.prev=null;
              }
              return value;
          }
          //队尾删除元素
          public int removeLast(){
              if (tail==null){
                  throw new RuntimeException("队列为空");
              }
              int value = tail.data;
              tail=tail.prev;
              //删除的是最后的数据
              if (tail==null){
                  head=null;
              }else {
                  tail.next=null;
              }
              return value;
          }
      }
      
  • Java 中可以用来实现队列的数据结构
    • ArrayDeque
      public class ArrayDequeDemo {
          private ArrayDeque<Integer> deque;
      
          public ArrayDequeDemo() {
              this.deque =new ArrayDeque<>();
          }
          //判断队空
          public boolean isEmpty() {
              return deque.isEmpty();
          }
          //获取队头
          public Integer getFront() {
              return deque.peekFirst();
          }
          //获取队尾
          public Integer getRear() {
              return deque.peekLast();
          }
          //获取队列长度
          public int size() {
              return deque.size();
          }
          //添加到队头
          public void addFront(Integer e) {
              deque.addFirst(e);
          }
          //添加到队尾
          public void addRear(Integer e) {
              deque.addLast(e);
          }
          //删除队头
          public void removeFront() {
              deque.removeFirst();
          }
          //删除队尾
          public void removeRear() {
              deque.removeLast();
          }
      }
      
      • getFirst 方法和peekFirst方法区别
        • peekFirst检索但不删除此双端队列的最后一个元素,如果此双端队列为空,则返回 null 。
        • getFirst方法与peekFirst的不同之处仅在于,如果此双端队列为空,则会抛出NoSuchElementException异常。
    • LinkedList:LinkedList 和 ArrayDeque 都是 Java 中的类,都可以用来实现队列。LinkedList 使用双向链表实现,而 ArrayDeque 使用可变大小的数组实现。实现方法基本类似。
    • PriorityBlockingQueue:这是一个优先级队列,它基于堆实现。
  • 数组队列和链表队列的优缺点以及使用场景
    • 数组队列
      • 优点
        • 支持随机访问:可以通过索引直接访问队列中的任意元素。
        • 快速出队:出队操作(dequeue)的时间复杂度为 O(1)。
      • 缺点
        • 长度固定:队列长度固定,当队列满时,无法添加新元素,需要动态扩容。
        • 内存占用高:需要一块连续的内存空间来存储队列元素,扩容时可能需要重新分配内存
      • 使用场景:需要快速出队和随机访问元素的场景,如生产者-消费者问题、优先级队列等。
    • 链表队列
      • 优点
        • 长度可变:队列长度可以动态变化,不会因为固定长度而限制队列的大小。
        • 快入队和出队:入队(enqueue)和出队(dequeue)操作的时间复杂度为 O(1)。
      • 缺点
        • 不支持随机访问:不能通过索引直接访问队列中的元素。
        • 内存占用高:每个节点需要存储数据和指向下一个节点的引用,内存占用相对较高。
      • 使用场景:需要动态调整队列长度的场景,如消息队列、任务队列等。
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Iron_Sp-man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值