zoukankan      html  css  js  c++  java
  • 队列

    队列是只能在一端进行插入,一端进行删除的线性表。允许插入的一端称为队尾,允许删除的一端为队头。跟我们平常排队买东西是一样的,后来者要插入时只能排在队尾,买完东西的人是从队头出去的(删除)。因为队列中队尾和队头都可以进行操作,所以定义两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置。

    既然队列也是线性表,那么也分顺序存储结构和链式存储结构。在队列的顺序存储结构中,在队头进行删除元素的操作,在队尾插入元素,可能导致分配的数组空间浪费很大一部分内存,很不明智,因此出现了循环队列。循环队列是指队列头尾相接的顺序存储结构。当队列为空时,front=rear;当队列满时,数组中还有一个空闲单元。

    当rear>front时,也就是队尾指针指向的数组下标大于队头指针指向的数组下标,此时队列的长度为rear-front;当rear<front时,此时队列的长度为rear-front+QueSize;所以队列的长度的通用计算公式为(rear-front+QueSize)%QueSize。

    一.顺序存储结构

    1.队列的结构定义

    代码实现:

    class SqQueue{
        int maxSize=8;
        Object[] array=new Object[maxSize];
        int front;
        int rear;
    }
    

    2.初始化一个空循环队列

    代码实现:

    public static void initQueue(SqQueue sq){
        sq.front=0;
        sq.rear=0;
    }
    

    3.计算队列的长度

    代码实现:

    public static int calculateLength(SqQueue sq){
        int length=(sq.rear-sq.front+sq.maxSize)%sq.maxSize;
        return length;
    }
    

    4.循环队列的入队列操作

    算法思路:
        1. 判断队列是否满,队列已满的判定条件为队列中还有一个空闲单元,%QueSize是考虑到队列的最后一个位置,如果直接rear+1则指针溢出队列,而求余则将指针指向队头第一个位置;
        2. 队尾(即rear指针指向的位置)插入元素;
        3. rear指针向后移一位,%QueSize原因如1;

    代码实现:

    public static void EnQueue(SqQueue sq,Object e){
        //判断队列是否满
        if((sq.rear+1)%sq.maxSize==sq.front){
            System.out.println("队列已满");
        }else{
            //队尾插入元素e
            sq.array[sq.rear]=e;
            //队尾指针向后移一位
            sq.rear=(sq.rear+1)%sq.maxSize;
        }
    }
    

    5.循环队列的出队列操作

    算法思路:
        1. 判断队列是否为空,队列为空的判定条件为rear==front;
        2. front指针后移一位;

    代码实现:

    public static void DeQueue(SqQueue sq){
        //判断队列是否为空队列
        if(sq.rear==sq.front){
            System.out.println("队列为空");
        }else{
            //队头元素赋值给e
            Object e=sq.array[sq.front];
            //指针后移一位
            sq.front=(sq.front+1)%sq.maxSize;
        }
    }
    

    完整代码:

    package com.java.Queue;
    
    import java.util.Arrays;
    
    public class QueueTest {
        static SqQueue sq=new SqQueue();
        
        public static void main(String[] args){
            EnQueue(sq,"A");
            EnQueue(sq,"B");
            EnQueue(sq,"C");
            EnQueue(sq,"D");
            DeQueue(sq);
            DeQueue(sq);
            System.out.println(sq);
            System.out.println(calculateLength(sq));
        }
        //循环队列的出队列操作
        public static void DeQueue(SqQueue sq){
            //判断队列是否为空队列
            if(sq.rear==sq.front){
                System.out.println("队列为空");
            }else{
                //队头元素赋值给e
                Object e=sq.array[sq.front];
                sq.array[sq.front]=null;
                //指针后移一位
                sq.front=(sq.front+1)%sq.maxSize;
            }
        }
        //循环队列的入队列操作
        public static void EnQueue(SqQueue sq,Object e){
            //判断队列是否满
            if((sq.rear+1)%sq.maxSize==sq.front){
                System.out.println("队列已满");
            }else{
                //队尾插入元素e
                sq.array[sq.rear]=e;
                //队尾指针向后移一位
                sq.rear=(sq.rear+1)%sq.maxSize;
            }
        }
        //计算循环队列的长度
        public static int calculateLength(SqQueue sq){
            int length=(sq.rear-sq.front+sq.maxSize)%sq.maxSize;
            return length;
        }
        //初始化一个空循环队列
        public static void initQueue(SqQueue sq){
            sq.front=0;
            sq.rear=0;
        }
    }
    class SqQueue{
        int maxSize=8;
        Object[] array=new Object[maxSize];
        int front;
        int rear;
        @Override
        public String toString() {
            return "SqQueue [maxSize=" + maxSize + ", array=" + Arrays.toString(array) + ", front=" + front + ", rear="
                    + rear + "]";
        }
    }
    

    二.链式存储结构

    队列的链式存储结构和单链表差不多,只不过之只能在队尾插入元素在队头删除元素。还有一个区别是链式存储结构中队头指针指向的是队列的头结点,队尾指针指向队尾结点;而在顺序存储结构中,队头指针指向队列的队头元素,而队尾指针指向队尾元素的下一结点。队列的链式存储结构也是不需要事先分配内存空间的。

    1.链式队列结点

    class QNode{
        Object data;
        QNode next;
        public QNode(Object data,QNode next){
            this.data=data;
            this.next=next;
        }
        @Override
        public String toString() {
            return "QNode [data=" + data + ", next=" + next + "]";
        }
    }
    

    2.初试化空队列,空队列时front和rear都指向头结点

    class LinkQueue{
        static QNode front=new QNode("头结点",null);
        QNode rear=front;
    }
    

    3.入队操作(尾进)

        1. 将新结点赋值给队尾指针的下一个元素;
        2. 将队尾指针重新指向新结点;

    代码实现:

    public static void EnLinkQueue(LinkQueue lq,QNode node){
        lq.rear.next=node;
        lq.rear=node;
    }
    

    4.出队操作(头出)
        1. 先判断队列栈中是否有元素;
        2. 若非空栈,头结点后移一位;
        3. 如果头结点之后的结点为要出栈的元素,rear指向front;

    代码实现:

    public static void DeLinkQueue(LinkQueue lq){
        //先判断队列栈中是否有元素
        if(lq.front==lq.rear){
            System.out.println("空栈");
        }else{
            //要出栈的元素
            QNode p=lq.front.next;
            //头结点后移一位
            lq.front.next=p.next;
        }
        //如果头结点之后的结点为要出栈的元素,rear指向front
        if(lq.rear==lq.front.next){
            lq.rear=lq.front;
        }
    }
    

    完整代码:

    package com.java.Queue;
    
    public class LinkQueueTest {
        static QNode node=new QNode("A",null);
        static QNode node1=new QNode("B",null);
        static LinkQueue lq=new LinkQueue();
        public static void main(String[] args){
            EnLinkQueue(lq,node);
            System.out.println(lq.rear);
            EnLinkQueue(lq,node1);
            System.out.println(lq.rear);
            DeLinkQueue(lq);
            System.out.println(lq.front.next);
        }
        //出队操作(头出)
        public static void DeLinkQueue(LinkQueue lq){
            //先判断队列栈中是否有元素
            if(lq.front==lq.rear){
                System.out.println("空栈");
            }else{
                //要出栈的元素
                QNode p=lq.front.next;
                //头结点后移一位
                lq.front.next=p.next;
            }
            //如果头结点之后的结点为要出栈的元素,rear指向front
            if(lq.rear==lq.front.next){
                lq.rear=lq.front;
            }
        }
        //入队操作(尾进)
        public static void EnLinkQueue(LinkQueue lq,QNode node){
            lq.rear.next=node;
            lq.rear=node;
        }
    }
    //初始化空队列,空队列时front和rear都指向头结点
    class LinkQueue{
        static QNode front=new QNode("头结点",null);
        QNode rear=front;
    }
    
    class QNode{
        Object data;
        QNode next;
        public QNode(Object data,QNode next){
            this.data=data;
            this.next=next;
        }
        @Override
        public String toString() {
            return "QNode [data=" + data + ", next=" + next + "]";
        }
    }
    



  • 相关阅读:
    组织机构数据隔离(上级可看下级,同级屏蔽)的高效实现思路
    .NET Core 3.x 基于AspectCore实现AOP,实现事务、缓存拦截器
    .NET Core 3.x 基于Autofac的AOP缓存
    Web开发中【密码加密】详解
    python多线程 DBUtils操作数据库
    处理MariaDB Galera cluster初始化和启动报错两例
    搭建MariaDB Galera Cluster集群 10.3.8
    AzureWeb应用作为客户端携带证书访问其他链接办法
    CTF
    [KuangBin专题四]Silver Cow Party
  • 原文地址:https://www.cnblogs.com/naihuangbao/p/10262386.html
Copyright © 2011-2022 走看看