数据结构之栈和队列

一、栈

1、栈的概念

是一种线性表,具有后进先出的特点。只能在固定的一段进行数据的插入和删除,进行元素插入和删除的一端称为栈顶,另一端称为栈底。

2、栈的使用
3、栈实例
(1)逆序打印链表

eg:链表为1->2->3->4->5

逆序打印:5->4->3->2->1

递归方式:

java 复制代码
void printList(ListNode head){
    if(null!=head){
       printList(head.next);
       System.out.print(head.val+" ");
    }
}

栈方式:

java 复制代码
Stack<Integer> stack=new Stack<>();
while(head!=null){
   stack.push(head.val);
   head=head.next;
}
while(!stack.empty()){
    System.out.print(stack.pop()+" ");
}
(2)括号匹配
java 复制代码
class Solution {
    public boolean isValid(String s) {
        int n=s.length();
        Stack<Character> stack=new Stack<>();
        for(int i=0;i<n;i++){
            char c=s.charAt(i);
            if(c=='('||c=='['||c=='{'){
                stack.push(c);
            }else{
                if(stack.empty()){
                    return false;
                }
                if(c==')'&&stack.peek()=='('||c==']'&&stack.peek()=='['||
                c=='}'&&stack.peek()=='{'){
                    stack.pop();
                }else{
                    return false;
                }
            }
        }
        return stack.empty();
    }
}
(3)逆波兰表达式求值
java 复制代码
class Solution {
    public int evalRPN(String[] tokens) {
        int n=tokens.length;
        Stack<Integer> s=new Stack<>();
        for(int i=0;i<n;i++){
            String temp=tokens[i];
            if(!(temp.equals("+")||temp.equals("-")||temp.equals("*")||temp.equals("/"))){
                s.push(Integer.valueOf(temp));
            }else{
                int b=s.pop();
                int a=s.pop();
                if(temp.equals("+")){
                    s.push(a+b);
                }else if(temp.equals("-")){
                    s.push(a-b);
                }else if(temp.equals("*")){
                    s.push(a*b);
                }else{
                    s.push(a/b);
                }
            }
        }
        return s.pop();
    }
}
(4)出栈入栈次序匹配
java 复制代码
 public boolean IsPopOrder (int[] pushV, int[] popV) {
        // write code here
        Stack<Integer> s=new Stack<>();
        int n=pushV.length;
        int j=0;
        for(int i=0;i<n;i++){
            s.push(pushV[i]);
            while(!s.empty()&&s.peek()==popV[j]){
                s.pop();
                j++;
            }
        }
        return j==n;
    }
(5)最小栈
java 复制代码
class MinStack {
    Stack<Integer> s1;
    Stack<Integer> s2;
    public MinStack() {
        s1=new Stack<>();
        s2=new Stack<>();
    }
    
    public void push(int val) {
        s1.push(val);
        if(s2.empty()){
            s2.push(val);
        }else{
            if(s2.peek()>=val){
                s2.push(val);
            }
        }
    }
    
    public void pop() {
        int a=s1.pop();
        if(!s2.empty()&&s2.peek()==a){
            s2.pop();
        }
    }
    
    public int top() {
        return s1.peek();
    }
    
    public int getMin() {
        if(s2.empty()){
            return -1;
        }else{
            return s2.peek();
        }
    }
}
(6)栈、虚拟机栈、栈帧有什么区别?

栈:是一种线性表,具有后进先出的特点;

虚拟机栈:jvm划分的一块内存;

栈帧:调用方法的时候会在虚拟机当中给这个方法开辟一块内存。

二、队列

1、队列的概念

是一种线性表,具有先进先出的特点。只能在固定的一段进行数据的插入和删除,进行元素插入一端称为队尾,另一端称为队头。

2、队列的使用

注意:Queue是一个接口,在实例化对象时,使用LinkedList实例化对象,因为LinkedList实现了Queue接口。

3、队列实例
(1)循环队列

区分空与满

①记录长度标记

放入一个元素,长度+1;取出一个元素,长度-1;长度>队列最长长度,已满;长度<=0,已空;

该方法操作简单,就不再详细编写代码。

②保留一个位置

java 复制代码
class MyCircularQueue {
    int[] elem;
    int front;
    int rear;
    public MyCircularQueue(int k) {
        elem=new int[k+1];
    }
    
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }else{
            elem[rear]=value;
            rear=(rear+1)%elem.length;
            return true;
        }
    }
    
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }else{
            front=(front+1)%elem.length;
            return true;
        }
    }
    
    public int Front() {
        if(isEmpty()){
            return -1;
        }else{
            return elem[front];
        }
    }
    
    public int Rear() {
        if(isEmpty()){
            return -1;
        }else{
            int index=(rear==0)?elem.length-1:rear-1;
            return elem[index];
        }
    }
    
    public boolean isEmpty() {
        return front==rear;
    }
    
    public boolean isFull() {
        return (rear+1)%elem.length==front;
    }
}
(2)用队列实现栈

队列:先进先出;栈:先进后出

两个队列一模一样:进出队列变换。

java 复制代码
class MyStack {
    Queue<Integer> q1;
    Queue<Integer> q2;
    public MyStack() {
        q1=new LinkedList<Integer>();
        q2=new LinkedList<Integer>();
    }
    
    public void push(int x) {
        if(q1.isEmpty()){
            q2.offer(x);
        }else{
            q1.offer(x);
        }
    }
    
    public int pop() {
        if(empty()){
            return -1;
        }
        int temp=0;
        if(q1.isEmpty()){
            while(!q2.isEmpty()){
                temp=q2.poll();
                if(!q2.isEmpty()){
                   q1.offer(temp);
                }
            }
        }else{
            while(!q1.isEmpty()){
                temp=q1.poll();
                if(!q1.isEmpty()){
                    q2.offer(temp);
                }
            }
        }
        return temp;
    }
    
    public int top() {
        if(empty()){
            return -1;
        }
        int temp=0;
         if(q1.isEmpty()){
            while(!q2.isEmpty()){
                temp=q2.poll();
                q1.offer(temp);
            }
        }else{
            while(!q1.isEmpty()){
                temp=q1.poll();           
                q2.offer(temp);                
            }
        }
        return temp;
    }
    
    public boolean empty() {
        return q1.isEmpty()&&q2.isEmpty();
    }
}
(3)用栈实现队列

两个栈不一样,一个栈固定为入队列,一个栈固定为出队列。

java 复制代码
class MyQueue {
    Stack<Integer> s1;
    Stack<Integer> s2;
    public MyQueue() {
        s1=new Stack<>();
        s2=new Stack<>();
    }
    public void push(int x) {
        s1.push(x);
    }
    
    public int pop() {
        if(empty()){
            return -1;
        }
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }
    
    public int peek() {
        if(empty()){
            return -1;
        }
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }
    
    public boolean empty() {
        return s1.empty()&&s2.empty();
    }
}
4、双端队列(Deque)

允许两端都可以进行入队和出队操作。Deque是一个接口,实例化对象使用LinkedList实现。

相关推荐
qystca40 分钟前
洛谷 P11242 碧树 C语言
数据结构·算法
冠位观测者1 小时前
【Leetcode 热题 100】124. 二叉树中的最大路径和
数据结构·算法·leetcode
XWXnb61 小时前
数据结构:链表
数据结构·链表
悲伤小伞1 小时前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法
hnjzsyjyj3 小时前
“高精度算法”思想 → 大数阶乘
数据结构·高精度算法·大数阶乘
Aileen_0v010 小时前
【AI驱动的数据结构:包装类的艺术与科学】
linux·数据结构·人工智能·笔记·网络协议·tcp/ip·whisper
是小胡嘛10 小时前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
yuanManGan12 小时前
数据结构漫游记:静态链表的实现(CPP)
数据结构·链表
2401_8582861115 小时前
115.【C语言】数据结构之排序(希尔排序)
c语言·开发语言·数据结构·算法·排序算法
猫猫的小茶馆15 小时前
【数据结构】数据结构整体大纲
linux·数据结构·算法·ubuntu·嵌入式软件