• 队列


    队列是只能在一端进行插入,一端进行删除的线性表。允许插入的一端称为队尾,允许删除的一端为队头。跟我们平常排队买东西是一样的,后来者要插入时只能排在队尾,买完东西的人是从队头出去的(删除)。因为队列中队尾和队头都可以进行操作,所以定义两个指针,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 + "]";
        }
    }
    



  • 相关阅读:
    1105 Spiral Matrix (25分)(蛇形填数)
    1104 Sum of Number Segments (20分)(long double)
    1026 Table Tennis (30分)(模拟)
    1091 Acute Stroke (30分)(bfs,连通块个数统计)
    1095 Cars on Campus (30分)(排序)
    1098 Insertion or Heap Sort (25分)(堆排序和插入排序)
    堆以及堆排序详解
    1089 Insert or Merge (25分)
    1088 Rational Arithmetic (20分)(模拟)
    1086 Tree Traversals Again (25分)(树的重构与遍历)
  • 原文地址:https://www.cnblogs.com/naihuangbao/p/10262386.html
Copyright © 2020-2023  润新知