• 数据结构之栈和队列


    一、栈

    1. 栈的基本概念

    • 栈(Stack):是限定仅在一端(栈顶)进行插入或者删除操作的线性表,是一种后进先出的线性表
    • 栈顶(Top):允许进行插入或删除操作的一端
    • 栈底(Bottom):固定的,不允许进行任何操作的一端

    2.栈的存储结构

    顺序存储(数组实现)

    ​ 在JDK中,Java Stack类是vector的一个子类,继承vector,在util包下。并且只定义了默认构造方法,大部分方法的实现也来源于vector。

    public class Stack<E> extends Vector<E> {}
    
    代码实现
    public class ArrayStack{
        private static final int DEFAULT_CAPACITY = 100; //栈的默认容量
        private Object[] arrStack; //实现栈的数组
        private int topOfStack; //栈顶
        
        //栈的初始化
        public ArrayStack(){
            arrStack = new Object[DEFAULT_CAPACITY];
            topOfStack = -1;
        }
        
        //栈空判断
        public boolean isEmpty(){
            return topOfStack == -1;
        }
        
        //栈满判断
        public boolean isFull(){
            return topOfStack == DEFULT_CAPACITY - 1;
        }
        
        //入栈
        public void push(Object o){
            if(isFull()){
                throw new RuntimeException("栈满");
            }
            arrStack[topOfStack++] = o;
        }
        
       //出栈
        public Object pop(){
            if(isEmpty()){
                throw new RuntimeException("栈空");
            }
            return arrStack[topOfStack--];
        }
    }
    

    3.栈的应用

    • 表达式转换和求值
    • 括号匹配
    • 递归程序的非递归化
    • 二叉树遍历
    • 图的深度优先搜寻

    二、队列

    1.队列的基本概念

    • 队列(Queue):限定在一端进行插入,另一端进行删除。是一种先进先出的线性表
    • 队头:允许删除的一端
    • 队尾:允许插入的一端

    2. 队列的存储结构

    在JDK中,队列是collection的一个子类

    2.1 顺序队列(数组实现)

      设front指向队头元素,rear指向队尾元素,那么
    

    队空条件:front = rear = -1;

    入队操作:队不满时,队尾rear指针向后移一位,再将值放入队尾,即++rear;

    出队操作:队非空时,队头指针向后移动一位,再从队头取值,即++front;

    代码实现
    class ArrayQueue{
        private Object[] arrQueue;
        private int front;
        private int rear;
        private int maxSize;
        
        //构造函数初始化
        public ArrayQueue(){
            arrQueue = new Object[maxSize];
            front = -1;
            rear = -1;
        }
        
        //判断队列是否已满
        public boolean isFull(){
            return rear == this.maxSize - 1;
        }
        
    	//判断队列是否为空
        public boolean isEmpty(){
            return rear == front;
        }
        
        //入队
        public void EnQueue(Object o){
            if(isFull()){
                throw new RuntimeException("队列已满");
            }
            arrQueue[++rear] = o;
        }
        
        //出队
        public Object DeQueue(){
            if(isEmpty()){
                throw new RuntimeException("队列为空");
            }
            return arrQueue[++front];
        } 
    }
    

    2.2 循环队列(数组实现)

    ​ 在上面的顺序队列中,能否通过rear == maxSize - 1 来判断数组中元素是否已满?答案是不能,如图,此时已经不能再插入新的元素,然而在数组左侧仍然有空位,这就是顺序队列中的假溢出

    因此,就引出了循环队列,将存储队列元素的数组表从逻辑上看成一个环,当队头front = maxSize -1后,再前进一格位置就到达数组的0位,节约了内存空间。

    队空条件:front = rear;

    队满条件:(rear + 1) % maxSize == front;

    入队操作:rear = (rear + 1) % maxSize;

    出队操作:front = (front + 1) % maxSize;

    队列长度:(rear + maxsize - front) % maxSize;

    代码实现
    class CircleQueue{
        private Object[] arrQueue;
        private int front;
        private int rear;
        private int maxSize;
        
        //构造函数初始化
        public CircleQueue(){
            arrQueue = new Object[maxSize];
            front = 0;
            rear = 0;
        }
        
        //判断队列是否已满
        public boolean isFull(){
            return (rear + 1) % maxSize == front;
        }
        
    	//判断队列是否为空
        public boolean isEmpty(){
            return rear == front;
        }
        
        //入队
        public void EnQueue(Object o){
            if(isFull()){
                throw new RuntimeException("队列已满");
            }
            arrQueue[rear] = o;
            rear = (rear + 1) % maxSize;
        }
        
        //出队
        public Object DeQueue(){
            if(isEmpty()){
                throw new RuntimeException("队列为空");
            }
            Object value = arrQueue[front];
            front = (front + 1) % maxSize;
            return value;
        } 
        
        //队列长度
        public int len(){
            if(isEmpty()){
                return 0;
            }
            return (rear + maxSize - front ) % maxSize;
        }
    }
    

    3. 队列的应用

    • 作业排队
    • 层序遍历二叉树
  • 相关阅读:
    [BZOJ3997][TJOI2015]组合数学(Dilworth定理+DP)
    [BZOJ4000][TJOI2015]棋盘(状压DP+矩阵快速幂)
    BZOJ2462[Beijing2011]矩阵模板(二维Hash)
    [BZOJ2458][BeiJing2011]最小三角形(分治)
    [HDU5354]Bipartite Graph(CDQ分治+并查集)
    [NOIP2017]时间复杂度(模拟)
    [Luogu2540][NOIP2016]斗地主增强版(搜索+DP)
    [Luogu1979][NOIP2013]华容道(BFS+SPFA)
    WQS二分题集
    [CC-XXOR]Chef and Easy Problem
  • 原文地址:https://www.cnblogs.com/EthanWong/p/13461078.html
Copyright © 2020-2023  润新知