Stack and Queue - Detailed Explanation

foreword

This blog - describes the following related concepts about stacks and queues

  1. The concept and use of stack
  2. The concept and use of queue

the stack

concept

Stack: A special linear list that only allows insertion and deletion of elements at a fixed end. The end where data insertion and deletion operations are performed is called the top of the stack, and the other end is called the bottom of the stack. The data elements in the stack follow the principle of LIFO (Last In First Out)

common term

Push - push the stack: The insertion operation of the stack is called push/push/push, and the incoming data is at the top of the stack.
Pop - Popping: The deletion operation of the stack is called popping. The output data is on the top of the stack.
insert image description here

stack usage

method explain
Stack() construct an empty stack
And push(And e) Push e onto the stack and return e
And pop() Pop the top element of the stack and return
E peek() Get the top element of the stack
int size() Get the number of valid elements in the stack
boolean empty() Check if the stack is empty

Simulation implementation of the stack

insert image description here
As can be seen from the above figure, Stack inherits Vector, and Vector is similar to ArrayList, both of which are dynamic sequence tables. The difference is that Vector is thread-safe.

public class MyStack {
    
    
	int[] array;
	int size;
	public MyStack(){
    
    
		array = new int[3];
	}
	public int push(int e){
    
    
		ensureCapacity();
		array[size++] = e;
		return e;
	}
	public int pop(){
    
    
		int e = peek();
		size--;
		return e;
	}
	public int peek(){
    
    
		if(empty()){
    
    
			throw new RuntimeException("栈为空,无法获取栈顶元素");
		}
		return array[size-1];
	}
	public int size(){
    
    
		return size;
	}
	public boolean empty(){
    
    
		return 0 == size;
	}
	private void ensureCapacity(){
    
    
		if(size == array.length){
    
    
			array = Arrays.copyOf(array, size*2);
		}
	}
}

Application scenarios of the stack

  1. Change the sequence of elements - as follows

If the push sequence is 1,2,3,4, and the stack can be popped during the push process, then the following impossible pop sequence is ()
A: 1,4,3,2 B: 2,3,4, 1 C: 3,1,4,2 D: 3,4,2,1

  1. Turn recursion into loop
// 递归方式
void printList(Node head){
    
    
	if(null != head){
    
    
		printList(head.next);
		System.out.print(head.val + " ");
	}
}
// 循环方式
void printList(Node head){
    
    
	if(null == head){
    
    
			return;
	}
	Stack<Node> s = new Stack<>();
	// 将链表中的结点保存在栈中
	Node cur = head;
	while(null != cur){
    
    
		s.push(cur);
		cur = cur.next;
	}
}


  1. bracket matching
  2. Reverse Polish expression evaluation
  3. The order of popping and stacking matches
  4. minimal stack

What is the difference between a stack, a virtual machine stack, and a stack frame?

A stack is a first-in, last-out data structure. The virtual machine stack is a memory space of the JVM. A stack frame is a piece of memory opened up on the java virtual machine stack during a function call

monotonic stack

As can be heard from the name, the data stored in the monotonic stack should be in order, so the monotonic stack is also divided into a monotonically increasing stack and a monotonically decreasing stack

Monotonically increasing stack: Monotonically increasing stack means that the data from the bottom of the stack to the top of the stack is from large to small. Monotonically
decreasing stack: The monotonically decreasing stack means that the data from the bottom of the stack to the top of the stack is from small to large

Simulation implementation

stack<int> st;
//此处一般需要给数组最后添加结束标志符,具体下面例题会有详细讲解
for (遍历这个数组)
{
    
    
	if (栈空 || 栈顶元素大于等于当前比较元素)
	{
    
    
		入栈;
	}
	else
	{
    
    
		while (栈不为空 && 栈顶元素小于当前元素)
		{
    
    
			栈顶元素出栈;
			更新结果;
		}
		当前数据入栈;
	}
}

Queue

concept

Queue: A special linear table that only allows inserting data operations at one end and deleting data operations at the other end. The queue has the characteristics of first-in-first-out FIFO. Entering the queue: the end that performs the insertion operation is called the end of the
queue
. Out the queue: the end that performs the deletion operation Called the head
(Head/Front)

Queue usage

In Java, Queue is an interface, and the underlying layer is implemented through a linked list.
insert image description here

method explain
boolean offer(E e) queue
E poll() out of queue
peek() Get the element at the head of the queue
int size() Get the number of valid elements in the queue
boolean isEmpty() Check if the queue is empty

Queue simulation implementation

public class Queue {
    
    
	// 双向链表节点
	public static class ListNode{
    
    
	ListNode next;
	ListNode prev;
	int value;
	ListNode(int value){
    
    
		this.value = value;
	}
	}
	ListNode first; // 队头
	ListNode last; // 队尾
	int size = 0;
	// 入队列---向双向链表位置插入新节点
	public void offer(int e){
    
    
		ListNode newNode = new ListNode(e);
		if(first == null){
    
    
			first = newNode;
			// last = newNode;
		}else{
    
    
			last.next = newNode;
			newNode.prev = last;
			// last = newNode;
		}
		last = newNode;
		size++;
	}
	// 出队列---将双向链表第一个节点删除掉
	public int poll(){
    
    
	// 1. 队列为空
		// 2. 队列中只有一个元素----链表中只有一个节点---直接删除
		// 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除
		int value = 0;
		if(first == null){
    
    
			return null;
		}else if(first == last){
    
    
			last = null;
			first = null;
		}else{
    
    
			value = first.value;
			first = first.next;
			first.prev.next = null;
			first.prev = null;
		}
		--size;
		return value;
	}
	// 获取队头元素---获取链表中第一个节点的值域
	public int peek(){
    
    
		if(first == null){
    
    
			return null;
		}
		return first.value;
	}
	public int size() {
    
    
		return size;
	}
	public boolean isEmpty(){
    
    
		return first == null;
	}
}

circular queue

circular queue. For example, when the operating system course explains the producer-consumer model, a circular queue can be used. Ring queues are usually implemented using arrays

insert image description here

  1. The subscript is at the end and later (offset is less than array.length): index = (index + offset) % array.length
  2. Subscript first and then forward (offset is less than array.length): index = (index + array.length - offset) % array.length

How to tell the difference between empty and full

  1. Record by adding size attribute
  2. reserve a spot
  3. use markup

design circular queue


import java.util.*;
class MyCircularQueue {
    
    
//    设计循环队列
    /*
 MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
* */
    private int[] elem;
    private int front;
    private int rear;
   // private int usedSize;//这样写太简单了
    public MyCircularQueue(int k) {
    
    
        elem=new int[k+1];
    }
    
    public boolean enQueue(int value) {
    
    
        if (isFull()){
    
    
            return false;
        }
        elem[rear]=value;
        rear=(rear+1)% elem.length;
       // usedSize++;
        return true;
    }
    
    public boolean deQueue() {
    
    
        if (isEmpty()){
    
    
            return false;
        }
        front=(front+1)%elem.length;
       // usedSize--;
        return true;
    }
    
    public int Front() {
    
    
        if (isEmpty()){
    
    
            return -1;
        }
        return elem[front];
    }
    
    public int Rear() {
    
    
        if (isEmpty()){
    
    
            return -1;
        }
        int index=rear!=0?rear-1:elem.length-1;
        return elem[index];

    }
    
    public boolean isEmpty() {
    
    
        //return usedSize==0;
        return rear==front;
    }
    
    public boolean isFull() {
    
    
        return (rear+1)%elem.length==front;
    }


}

Double-ended queue (Deque)

A double-ended queue (deque) refers to a team that allows both ends to enter and exit the queue. Deque is the abbreviation of "double ended queue". That means elements can exit and enter the team from the head of the queue, and can also exit and enter the team from the tail of the queue

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

Guess you like

Origin blog.csdn.net/qq_56454895/article/details/131858710