zoukankan      html  css  js  c++  java
  • [数据结构与算法]08 队列( Queue )以及队列实现的三种方式( Java 版)

    队列

    说队列的时候,常常会想到栈,因为栈是后进先出,而队列则是先进先出.
    关于栈,前面已经写过了:[数据结构与算法]05 Stack 经典面试题之判断字符串是否合法( Java 版)
    这篇文章的主要焦点就在队列上了.

    队列,你的第一反应是不是排队?不管是在食堂买饭,还是在银行办理业务,或者进高铁站的时候,都会排队.
    排队有一个很明显的特点:早来的人,就会早点儿办完事情.
    这就是队列:先进先出.

    队列可以用数组实现,叫做顺序队列.也可以用链表实现,叫做链式队列.
    在这里,分别用数组和链表来实现一下.

    数组实现队列

    使用数组来实现队列,相对来说还是比较简单的,因为数组和队列一样都是线性表结构.
    废话不多说,咱们直接看代码

    /**
     * 用数组实现队列
     * @author 郑璐璐
     * @date 2020-1-29 15:51:32
     */
    public class ArrayQueue {
        /**
           数组:items,数组大小:n
         */
        private String[] items;
        private int n = 0;
        /**
           head表示队头下标,tail表示队尾下标
         */
        private int head = 0;
        private int tail = 0;
    
        /**
           申请一个大小为capacity的数组
         */
        public ArrayQueue(int capacity) {
            items = new String[capacity];
            n = capacity;
        }
    
        /**
           入队
         */
        public boolean enqueue(String item) {
            // 如果tail == n 表示队列已经满了
            if (tail == n) return false;
            items[tail] = item;
            tail++;
            return true;
        }
    
        /**
           出队
         */
        public String dequeue() {
            // 如果head == tail 表示队列为空
            if (head == tail) return null;
            String ret = items[head];
            head++;
            return ret;
        }
    
        public void printAll() {
            for (int i = head; i < tail; i++) {
                System.out.print(items[i] + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            ArrayQueue queue=new ArrayQueue(5);
            queue.enqueue("1");
            queue.enqueue("2");
            queue.enqueue("3");
            queue.enqueue("4");
            queue.enqueue("5");
            queue.dequeue();
            queue.enqueue("6");
    
            queue.printAll();
        }
    }
    

    使用数组实现队列有个问题,就是删除不是真的删除,只是在打印的时候将 i 的值指向了 head 而已,但是要删除的数据,仍然在数组中.

    链表实现队列

    使用链表实现队列也较为简单:

    /**
     * 用链表实现队列
     * @author 郑璐璐
     * @date 2020-1-30 09:20:41
     */
    public class LinkListQueue {
        /**
            队列的队首和队尾
         */
        private Node head = null;
        private Node tail = null;
    
        /**
             入队
         */
        public void enqueue(String value) {
            if (tail == null) {
                Node newNode = new Node(value, null);
                head = newNode;
                tail = newNode;
            } else {
                tail.next = new Node(value, null);
                tail = tail.next;
            }
        }
    
        /**
            出队
         */
        public String dequeue() {
            if (head == null) return null;
    
            String value = head.data;
            head = head.next;
            if (head == null) {
                tail = null;
            }
            return value;
        }
    
        public void printAll() {
            Node p = head;
            while (p != null) {
                System.out.print(p.data + " ");
                p = p.next;
            }
            System.out.println();
        }
    
        private static class Node {
            private String data;
            private Node next;
    
            public Node(String data, Node next) {
                this.data = data;
                this.next = next;
            }
    
            public String getData() {
                return data;
            }
        }
    
        public static void main(String[] args) {
            LinkListQueue queue=new LinkListQueue();
            queue.enqueue("3");
            queue.enqueue("2");
            queue.dequeue();
            queue.printAll();
        }
    }
    

    栈实现队列

    除了使用数组和链表实现,还有一种方法就是使用栈来实现队列.
    使用栈来实现队列,顾名思义就是只能使用栈的操作: pop , push , peek 等,其他操作不允许出现,否则就不是使用栈来实现队列了.
    使用数组和链表来实现栈都较为简单,因为在读取数据时,只需要按照顺序读取即可.
    但是对于栈来说,顺序读取行不通,为什么呢?假设我的队列数据为 1,2,3,4 依次存入栈中之后再读取的话,则是 4,3,2,1 因为栈是后进先出.
    如果使用栈来实现队列的话,需要用到两个栈.一个栈的输出顺序就是 4,3,2,1 在读取之前,我们把读取出来的数据存入到另外一个栈中,然后从后面这个栈读取,那么输出顺序就是 1,2,3,4 和原来队列的数据一致.
    在这里要注意一点:当后面的栈中有数据,前面的栈中也有数据时,要先将后面的栈中数据读取完毕,再将前面的数据放到后面的数据中.
    接下来看下代码实现:

    /**
     * 使用栈实现队列
     * @author 郑璐璐
     * @date 2020-1-30 17:21:19
     */
    public class StackQueue {
        private  static Stack<Integer> stackTemp = new Stack<Integer>();
        private static Stack<Integer> stackQueue = new Stack<Integer>();
    
        /**
           入队
         */
        public void push(int x){
            stackTemp.push(x);
        }
    
        /**
            出队
         */
        public int pop(){
            // 整个队列不为空时
            if (empty()!=0){
                // 如果 stackQueue 为空时,则将 stackTemp 中的数据放入 stackQueue 中
                // 如果 stackQueue 不为空,直接输出即可
                if (stackQueue.isEmpty()){
                    backFill();
                }
                return stackQueue.pop();
            }else {
                // 整个队列为空,则返回 -1 ,代表队列中没有值
                System.out.println("队列为空");
                return -1;
            }
        }
        public int empty(){
            // 判断队列是否为空,如果返回值为 0 ,则代表队列为空
            // 注意,两个栈均为空时,队列才为空
            return stackQueue.size() + stackTemp.size();
        }
        /**
            将 stackTemp 中的数据放入 stackQueue 中
         */
        public void backFill(){
            while (!stackTemp.isEmpty()){
                stackQueue.push(stackTemp.pop());
            }
        }
        public static void main(String[] args){
            StackQueue stack = new StackQueue();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            stack.push(4);
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.pop());
        }
    }
    
    

    以上,就是想要分享的内容了
    感谢您的阅读哇~

  • 相关阅读:
    VB中Null、Empty、Nothing及vbNullString的区别
    hs_err_pidXXX.log 解读
    测试Windows Live Writer——开博
    BCPC2021预赛
    软件设计模式之策略模式(Strategy) 壹
    留言板 壹
    友链 壹
    正则表达式练习 壹
    SpringBoot+Mybatis+自定义注解+Atomikos+实现多源数据库切换和分布式事务
    Dependency failed for File System Check on /dev/vdb1 服务器配置升级
  • 原文地址:https://www.cnblogs.com/zll-0405/p/12534093.html
Copyright © 2011-2022 走看看