Java-数据结构(二)栈和队列

学习目标


学习栈的原理及基本实现
学习队列的原理及基本实现
熟练使用 java 中的栈和队列

目录

1.栈(stack)

1.1概念

1.2实现

2.队列

2.1概念

2.2实现

2.3循环队列

3.双端队列

3.1 概念

4.Java 中的栈和队列

5.面试题


1.栈(stack)


1.1概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈
顶,另一端称为栈底。栈中的数据元素遵守后进先出 LIFO Last In First Out )的原则。
压栈:栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶
出栈:栈的删除操作叫做出栈。 出数据在栈顶

        后进先出(Last In Fist Out) 

中缀表达式 转 后缀表达式

(5+4)*3-2

先乘除后加减

1 按运算顺序加括号

((5+4)*3)+号移出来一个括号   *也移出来一个括号 -再移出来

(((54)+3)* 2)-再将所有括号去掉
54+3*2- 得到后缀表达式
如何通过一个后缀表达式来计算一个值呢
这时候就需要借助栈
帮助手册 或按住CTRL alt f7

import java.util.Stack;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 星有野
 * Date: 2022-05-09
 * Time: 18:25
 */
public class Demo {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(  1);
        stack.push(  2);
        stack.push(  3);
        stack.push(  4);
        System.out.println(stack.pop());
    }
}

4
3
3
false
false

为什么可以调用 isempty

因为

class Stack<E> extends Vector<E>子类

  

1.2实现

 public class MyStack{
     // 简单起见,我们就不考虑扩容问题了
     private int[] array = new int[100];
     private int size = 0; 

    public void push(int v) {
         array[size++] = v; 
}
    public int pop() {
     return array[--size]; 
}
public int peek() {
     return array[size - 1];
}
public boolean isEmpty() { 
    return size == 0; 
}
public int size() {
     return size;
   } 
}

2.队列


2.1概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾( Tail/Rear 出队列:进行删除操作的一端称为 队头 Head/Front

2.2实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会

class Node { 
    int val;
     Node next; 
        Node(int val, Node next) { 
            this.val = val; this.next = next;
     }
        Node(int val) { this(val, null);
     }
 }
public class MyQueue {
     private Node head = null;
     private Node tail = null; 
     private int size = 0;
     public void offer(int v) {
     Node node = new Node(v); 
            if (tail == null) { head = node;
         }
        else { tail.next = node;
         }
        tail = node; size++;
 }
public int poll(){
if (size == 0) { 
    throw new RuntimeException("队列为空");
    }
    Node oldHead = head; 
    head = head.next;
     if (head == null) { 
        tail = null;
         }
        size--; 
        return oldHead.val;
    }
    public int peek() {
         if (size == 0) { 
            throw new RuntimeException("队列为空");
         }

        return head.val;
         }
    public boolean isEmpty() {
         return size == 0;
    }
         public int size() { 
            return size;
    } 
}

2.3循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。

3.双端队列


3.1 概念

双端队列( deque )是指允许两端都可以进行入队和出队操作的队列, deque “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

4.Java 中的栈和队列


Stack

方法解释                                         
E push(E item)    压栈                     
E poo()出栈
E peek()查看栈顶元素
boolean empty()判断栈是否为空
错误处理                         抛出异常                        返回特殊值                                
入队列add(e)offer(e)
出队列remove()poll()
队首元素element()peek()
 

5.面试题


1. 括号匹配问题。 OJ 链接
2. 用队列实现栈。 OJ 链接
3. 用栈实现队列。 OJ 链接
4. 实现一个最小栈。 OJ 链接
5. 设计循环队列。 OJ 链接
public class TestDemo {

    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();

        for(int i = 0; i < s.length();i++) {
            char ch = s.charAt(i);
            if(ch == '(' || ch == '[' || ch == '{') {
                //如果是左括号 直接入栈
                stack.push(ch);
            }else{
                //遇到了右括号
                if(stack.empty()) {
                    //右括号多
                    System.out.println("右括号多");
                    return false;
                }
                char top = stack.peek();//哪个左括号
                if(top == '{' && ch == '}' || top == '[' && ch == ']' || top == '(' && ch == ')') {
                    stack.pop();
                }else{
                    //左右括号不匹配
                    System.out.println("左右括号不匹配");
                    return false;
                }
            }
        }
        if(!stack.empty()) {
            //左括号多
            System.out.println("左括号多");
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        MyStack stack = new MyStack();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        stack.push(6);
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 6
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 5
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 3
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 2
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 1
        System.out.println(stack.peek());//获取栈顶元素,但是不删除 5
        System.out.println(stack.peek());//获取栈顶元素,但是不删除 5
        System.out.println(stack.isEmpty());//false
    }

    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();

        for(int i = 0;i < tokens.length;i++) {
            String val = tokens[i];
            if(isOperation(val) == false) {
                //如果不是运算符
                stack.push(Integer.parseInt(val));
            }else {
                //到底啥运算符????
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch(val) {
                    case "+":
                        stack.push(num1+num2);
                        break;
                    case "-":
                        stack.push(num1-num2);
                        break;
                    case "*":
                        stack.push(num1*num2);
                        break;
                    case "/":
                        stack.push(num1/num2);
                        break;
                }
            }
        }
        return stack.pop();
    }
    private boolean isOperation(String x) {
        if(x.equals("+") || x.equals("-") ||x.equals("*") ||x.equals("/")) {
            return true;
        }
        return false;
    }
    public boolean IsPopOrder(int [] pushA,int [] popA) {

        Stack<Integer> stack = new Stack<>();
        int j = 0;//遍历popA
        for(int i = 0; i < pushA.length;i++) {
            stack.push(pushA[i]);
            while(j < popA.length && !stack.empty() && stack.peek() == popA[j]) {
                stack.pop();
                j++;
            }
        }
        return stack.empty();
    }
    public static void main1(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
        System.out.println(stack.peek());//获取栈顶元素,但是不删除 3
        System.out.println(stack.peek());//获取栈顶元素,但是不删除 3
        System.out.println(stack.empty());
        System.out.println("============");
        System.out.println(stack.isEmpty());
    }
}

内容重点总结

掌握栈和队列的数据结构知识并做简单实现
掌握 java 中栈、队列、双端队列的使用
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值