Loading

数据结构之栈和队列

一、栈

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. 队列的应用

  • 作业排队
  • 层序遍历二叉树
posted @ 2020-08-08 23:41  归思君  阅读(283)  评论(0编辑  收藏  举报