• 大话数据结构(十)java程序——队列


    1、队列的定义

    队列(queue):是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

    队列是一种先进先出的线性表,简称FIFO(First out firts in)。允许插入的一头是队尾,允许删除的一头是队头。

    注意:

    队列是线性表,也同样有类似线性表的各种操作,不同的就是插入数据只能在队尾进行,删除数据只能在队头进行。

    2、循环队列

    2.1 循环队列的定义

    队列中front指针指向队头元素,rear指针指向队尾元素的下一个元素,这样当front==rear 时,此队列是空队列。

    循环队列的定义是:队列头尾相接的顺序存储结构称为循环队列。

    队列满的条件是:(rear+1)%Queuesize = front;

    通用的计算队列长度的公式为:(rear-front+Queuesize)%Queue

    2.2 队列的顺序存储

    队列插入元素主要步骤:rear = (rear+1)%Queuesize;

    队列删除元素主要步骤:front = (front+1)%Queuesize;

    队列的顺序存储代码实现:

    public class SqeQueue<E> {
       ArrayList<E>  queue = new ArrayList<E>();
       
       final int MAXSIZE = 20;//循环队列的长度
       int font;//对头
       int rear;//队尾
       /*
        * 队列构造函数
        */
       public SqeQueue(){
           initQueue();
       }
       /*
        * 队列初始化
        */
       public void initQueue(){
           font=0;
           rear=0;
       }
       /*
        * 队列的当前长度
        */
       public int getLength(){
           return (rear-font+1)%MAXSIZE;
       }
       /*
        * 入队,队是在队尾入队
        */
       public boolean addQueue(E e){
           //队列满的判断
           if((rear+1)%MAXSIZE == font){
               System.out.println("队满");
           }
           //将e赋给队尾
           queue.add(rear, e);
           //rear 后移一位
           rear =( rear+1) %MAXSIZE;
           return true;
       }
       public E deleteQueue(){
           //队列满的判断
           if(font == rear){
               System.out.println("队为空");
           }
           //队头元素赋值给e
           E e = queue.get(font);
           //对头后移一位
           font = (font+1)%MAXSIZE;
           return e;
       }
       
       public static void main(String args[]){
           SqeQueue<Object> sqeQueue = new SqeQueue<Object>();
           sqeQueue.addQueue("zzzzz");
           sqeQueue.addQueue("bbbbbb");
           sqeQueue.addQueue("333333");
           for(int i=0;i<=sqeQueue.getLength();i++){
               System.out.println(sqeQueue.deleteQueue());
           }
       }
    }

    3、队列的链式存储结构及实现

    队列的链式存储结构,其实就是线性表的单链表,只不过它是尾进头出,我们把它简称为链队列。

    队头指针指向链队列的头结点,队尾指针指向终端结点。

    空队列时,front和rear都指向头结点。

    入队操作时,其实就是在链表尾部插入结点。

    出队操作时,其实就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素,则需要将rear指向头结点。

    package com.aclie.dataStructe4.queue;
    
    public class LinkQueue {
       Node2 rear;//队尾
       Node2 front;//队头
       int count=0;
       /*
        * 无参构造函数,初始化链表
        */
       public LinkQueue(){
           rear = front = null;
       }
       /*
        * 有参构造函数,初始化链表
        */
       public LinkQueue(Object obj){
           front = new Node2(obj);
           rear = front;
           count++;
       }
       /*
        * 得到链表的当前长度
        */
       public int getLinkLength(){
           return count;
       }
       /*
        * 入队,在队尾插入元素
        */
       public void addLinkQueue(Object obj){
          
           if(front == null){//空队列,插入元素
               front = new Node2(obj);
               rear = front;
           }else{//非空队列
               Node2 p = new Node2(obj);//要插入的结点
               rear.next2 = p;//将插入结点赋值给rear后继
               rear = p;//更改rear,rear指向插入的结点
               
           }
           count++;
       }
       public Object deleteLinkQueue(Object obj){
           if(rear == front){
               System.out.println("参数错误");
           }
           Node2 s =front;//将要删除的结点暂存为结点s
           Object data2= s.data;//获取要删除的元素
           front = s.next2;//将原队头结点后继s.next2 赋值给头结点后继
           if(rear == s){//若队头是队尾,则将删除后将rear指向队头
               rear = front;
           }
           s.next2 = null;//释放要删除结点
           count--;       
           return data2;//返回删除
         }
       
       public void printLinkQueue(){
           if(front == null){
               System.out.println("无打印的参数");
           }else{
               Node2 cur = front;
               while(cur != null){
                   System.out.println(cur.data);
                   cur = cur.next2;
               }
           }
          
       }
       public static void main(String args[]){
            LinkQueue linkQueue = new LinkQueue();
            linkQueue.addLinkQueue("222214");
            
            linkQueue.addLinkQueue("ewqtee");
            
            linkQueue.addLinkQueue("35432654");
        
            linkQueue.printLinkQueue();
            System.out.println("...........");
            linkQueue.deleteLinkQueue(linkQueue.front);
            linkQueue.deleteLinkQueue(linkQueue.front);
            linkQueue.deleteLinkQueue(linkQueue.front);
            linkQueue.printLinkQueue();
            
            
          } 
    }
    class Node2{
        Object data;//数字域
        Node2 next2;//指针域
        public Node2(Object d2){
            this.data = d2;
        }
    }

    4、总结

    对应循环队列与链队列的比较,可以从以下两方面:

    时间上:其实他们都是基本的常数时间,即O(1),不过循环队列是事先申请好的空间,使用期间不释放,而对于链队列,每次申请和释放存在一些时间开销,

               如果入队出队频繁,则两者还是有细微差异的。

    空间上:循环队列必须有一个固定的长度,这就造成了存储元素个数和空间上的浪费。而链队列不存在这个问题。尽管它需要一个指针域,会产生一些空间上的开销,但也可以接              受。所以空间上,链队列更加灵活。

    总得来说,在可以确定队列长度最大值情况下,建议用循环队列,如果无法预估队列长度,则用链队列。

  • 相关阅读:
    激光打印机基于主机驱动程序、基于 PCL 驱动程序和 PostScript 驱动程序有何区别?
    转贴:打印机语言PostScript和PCL的比较
    编译器相关配置简介
    Graphics View的体系结构
    解决重装Qt后不能编译Examples的问题
    有符号数和无符号数的区别
    51单片机的外设
    AT89S52单片机P3口解惑
    双向端口设计
    AT89s52单片机的掉电测试
  • 原文地址:https://www.cnblogs.com/snowwang/p/6083783.html
Copyright © 2020-2023  润新知