数据结构《栈和队列》

文章目录

  • 一、什么是栈?
    • [1.1 栈的模拟实现](#1.1 栈的模拟实现)
    • [1.2 关于栈的例题](#1.2 关于栈的例题)
  • 二、什么是队列?
    • [2.2 队列的模拟实现](#2.2 队列的模拟实现)
    • [2.2 关于队列的例题](#2.2 关于队列的例题)
  • 总结

提示:关于栈和队列的实现其实很简单,基本上是对之前的顺序表和链表的一种应用,代码部分也不难。主要的是对栈和队列的实际运用。

一、什么是栈?

可以理解为一个竖过来的数组、顺序表,同时这个数组只能将末尾的元素先推出来,再推出来前面的元素,也就是我们所说的,先进后出、后进先出。

栈的实例化

java 复制代码
Stack<E> stack = new Stack<>();

1.1 栈的模拟实现


自定义的接口,规范自定义的类,便于模拟实现

java 复制代码
public interface IStack {
    //放入元素
    int push(int a);
    //推出栈顶元素
    int pop();
    //查看栈顶元素
    int peek();
    //栈是否为空
    boolean isEmpty(int[] array);
    //栈中的元素个数
    int size();
    //栈中寻找某个元素距离栈顶的距离
    int search(int a);
}

push(int a) --- 将元素放入栈中

java 复制代码
public int push(int a) {
        isFull(array);
        array[useSide++] = a;
        return a;
    }

peek() --- 查看栈顶元素

java 复制代码
public int peek() {
        try {
            if(isEmpty(array)){
                throw new EmptyException("空数组读取异常");
            }
        }catch (EmptyException e){
            e.printStackTrace();
        }
        return array[useSide - 1];
    }

pop() --- 出栈顶元素

java 复制代码
public int pop() {
        int top = peek();
        useSide--;
        return top;
    }

isEmpty(int[] array) --- 判断栈是否为空

java 复制代码
public boolean isEmpty(int[] array) {
        return array.length == useSide;
    }

size() --- 得到栈中的元素个数

java 复制代码
public int size() {
        return useSide;
    }

search(int a) --- 得到栈中某个元素距离栈顶的距离,栈顶元素位置按1来计算

java 复制代码
public int search(int a) {
        int cur = useSide - 1;
        int len = 1;
        while (0 <= cur){
            if(a == array[cur]){
                return len;
            }else {
                cur--;
                len++;
            }
        }
        return -1;
    }

代码整合

java 复制代码
public class MyStack implements IStack{
    private int[] array;

    public MyStack() {
        this.array = new int[10];
    }
    private int useSide;


    private void isFull(int[] check){
        if(isEmpty(check)){
            array = Arrays.copyOf(check,2*check.length);
        }
    }
    @Override
    public int push(int a) {
        isFull(array);
        array[useSide++] = a;
        return a;
    }

    @Override
    public int pop() {
        int top = peek();
        useSide--;
        return top;
    }

    @Override
    public int peek() {
        try {
            if(isEmpty(array)){
                throw new EmptyException("空数组读取异常");
            }
        }catch (EmptyException e){
            e.printStackTrace();
        }
        return array[useSide - 1];
    }

    @Override
    public boolean isEmpty(int[] array) {
        return array.length == useSide;
    }

    @Override
    public int size() {
        return useSide;
    }

    @Override
    public int search(int a) {
        int cur = useSide - 1;
        int len = 1;
        while (0 <= cur){
            if(a == array[cur]){
                return len;
            }else {
                cur--;
                len++;
            }
        }
        return -1;
    }
}

1.2 关于栈的例题

例题1 有效括号

java 复制代码
class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        if(s == null){
            return false;
        }
        for(int i = 0; i < s.length(); i++){
            char cur = s.charAt(i);
            if(cur == '(' || cur == '{' || cur == '['){
                stack.push(cur);
            }else if(cur == ')' || cur == '}' || cur == ']'){
                if(stack.isEmpty()){
                    return false;
                }
                if(cur == ')'&&stack.peek() == '(' || 
                   cur == '}'&&stack.peek() == '{' || 
                   cur == ']'&&stack.peek() == '['){
                    stack.pop();
                }else{
                    return false;
                }
            }else{
                return false;
            }
        }
        if(stack.isEmpty()){
            return true;
        }
        return false;
    }
}

例题2 逆波兰表达式

java 复制代码
public int evalRPN(String[] tokens) {
        
        Stack<String> stack = new Stack<>();
        for(int i = 0; i < tokens.length; i++){
            if(tokens[i].equals("+") || tokens[i].equals("-") || tokens[i].equals("*") || tokens[i].equals("/")){
                int m = Integer.parseInt(stack.pop());
                int n = Integer.parseInt(stack.pop());
                if(tokens[i].equals("+")){
                    stack.push(String.valueOf(m+n));
                }else if(tokens[i].equals("-")){
                    stack.push(String.valueOf(n-m));
                }else if(tokens[i].equals("*")){
                    stack.push(String.valueOf(m*n));
                }else{
                    stack.push(String.valueOf(n/m));
                }
            }else{
                stack.push(tokens[i]);
            }
        }
        return Integer.parseInt(stack.pop());
    }

例题3 最小栈

java 复制代码
public Stack<Integer> stack;
    public Stack<Integer> minStack;

    public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();
    }
    
    public void push(int val) {
        stack.push(val);
        if(minStack.empty()){
            minStack.push(val);
        }else{
            int m = minStack.peek();
            if(m >= val){
                minStack.push(val);
            }
        }
    }
    
    public void pop() {
        if(stack.empty()){
            return;
        }
        int m = stack.pop();
        if(m == minStack.peek()){
            minStack.pop();
        }
    }
    
    public int top() {
        if(stack.empty()){
            return -1;
        }
        return stack.peek();
    }
    
    public int getMin() {
        if(minStack.empty()){
            return -1;
        }
        return minStack.peek();
    }

例题4 栈的压入、弹出序列

java 复制代码
public boolean IsPopOrder (int[] pushV, int[] popV) {
        // write code here
        Stack<Integer> stack = new Stack<>();
        int j = 0;
        for(int i = 0; i < pushV.length;i++){
            stack.push(pushV[i]);
            while(!stack.isEmpty() && stack.peek() == popV[j] && j < popV.length){
                stack.pop();
                j++;
            }
        }
        
        return stack.isEmpty();
    }

二、什么是队列?

可以理解为一个双向链表(一个一个节点在排队),同时这个链表只能将队头的元素先推出来,再推出来后面的元素,也就是我们所说的,先进先出、后进后出。

队列的实例化

java 复制代码
Deque<E> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<E> queue = new LinkedList<>();//双端队列的链式实现

2.2 队列的模拟实现


自定义的接口,规范自定义的类,便于模拟实现

java 复制代码
public interface IQueue {
    //
    int offer(int a);
    int poll();
    int peek();
    boolean isEmpty();
}

isEmpty() --- 判断是否为空队列

java 复制代码
@Override
    public boolean isEmpty() {
        return useSide == 0;
    }

offer(int a) --- 从队尾放入元素

java 复制代码
public int offer(int a) {
        ListNode listNode = new ListNode(a);
        listNode.val = a;
        if(isEmpty()){
            head = listNode;
            last = listNode;
        }else {
            last.next = listNode;
            listNode.pre = last;
            last = listNode;
        }
        useSide++;
        return a;
    }

peek() --- 查看队头元素

java 复制代码
public int peek() {
        try {
            if(head == null){
                throw new EmptyException("空指针异常访问");
            }
        }catch (EmptyException e){
            e.printStackTrace();
        }
        return head.val;
    }

poll() --- 推出队头的元素

java 复制代码
public int poll() {
        int fisrt = peek();
        head = head.next;
        useSide --;
        return fisrt;
    }

代码整合

java 复制代码
public class MyQueue implements IQueue{

    static class ListNode{
        int val;
        ListNode pre;
        ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }

    private ListNode head;
    private ListNode last;
    private int useSide;


    @Override
    public int offer(int a) {
        ListNode listNode = new ListNode(a);
        listNode.val = a;
        if(isEmpty()){
            head = listNode;
            last = listNode;
        }else {
            last.next = listNode;
            listNode.pre = last;
            last = listNode;
        }
        useSide++;
        return a;
    }

    @Override
    public int poll() {
        int fisrt = peek();
        head = head.next;
        useSide --;
        return fisrt;
    }

    @Override
    public int peek() {
        try {
            if(head == null){
                throw new EmptyException("空指针异常访问");
            }
        }catch (EmptyException e){
            e.printStackTrace();
        }
        return head.val;
    }

    @Override
    public boolean isEmpty() {
        return useSide == 0;
    }

}

2.2 关于队列的例题

例题1 设计循环队列

java 复制代码
class MyCircularQueue {
    public int[] array;
    int front;
    int rear;

    public MyCircularQueue(int k) {
        array = new int[k+1];
    }
    // 向循环队列插入一个元素。如果成功插入则返回真。
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        array[rear] = value;
        rear = (rear+1) % array.length;
        return true;
    }
    //从循环队列中删除一个元素。如果成功删除则返回真。
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }
        front = (front+1) % array.length;
        return true;
    }
    //从队首获取元素。如果队列为空,返回 -1 。
    public int Front() {
        if(isEmpty()){
            return -1;
        }
        return array[front];
    }
    //获取队尾元素。如果队列为空,返回 -1 。
    public int Rear() {
        if(isEmpty()){
            return -1;
        }
        if(rear == 0){
            return array[array.length - 1];
        }
        return array[rear-1];
    }
    //检查循环队列是否为空。
    public boolean isEmpty() {
        return rear == front;
    }
    //检查循环队列是否已满。
    public boolean isFull() {
        return (rear+1) % array.length == front;
    }
}

例题2 用队列实现栈

java 复制代码
class MyStack {
    public Queue<Integer> queue1;
    public Queue<Integer> queue2;
    int size;
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
        if(queue1.isEmpty() && queue2.isEmpty()){
            queue1.offer(x);
            size++;
        }else if(!queue1.isEmpty()){
            queue1.offer(x);
            size++;
        }else if(!queue2.isEmpty()){
            queue2.offer(x);
            size++;
        }
    }
    
    public int pop() {
        if(queue1.isEmpty() && queue2.isEmpty()){
            return -1;
        }
        if(queue1.isEmpty() && !queue2.isEmpty()){
            int cur = size - 1;
            while(cur != 0){
                queue1.offer(queue2.poll());
                cur--;
            }
            size--;
            return queue2.poll();
        }else if(!queue1.isEmpty() && queue2.isEmpty()){
            int cur = size - 1;
            while(cur != 0){
                queue2.offer(queue1.poll());
                cur--;
            }
            size--;
            return queue1.poll();
        }
        return -1;
    }
    
    public int top() {
        if(queue1.isEmpty() && queue2.isEmpty()){
            return -1;
        }
        if(queue1.isEmpty() && !queue2.isEmpty()){
            int cur = size - 1;
            while(cur != 0){
                queue1.offer(queue2.poll());
                cur--;
            }
            int m = queue2.peek();
            queue1.offer(queue2.poll());
            return m;
        }else if(!queue1.isEmpty() && queue2.isEmpty()){
            int cur = size - 1;
            while(cur != 0){
                queue2.offer(queue1.poll());
                cur--;
            }
            int m = queue1.peek();
            queue2.offer(queue1.poll());
            return m;
        }
        return -1;
    }
    
    public boolean empty() {
        return size == 0;
    }

}

例题3 用栈实现队列

java 复制代码
Stack<Integer> stack1;
    Stack<Integer> stack2;
    int size = 0;

    public MyQueue() {
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }
    //将元素 x 推到队列的末尾
    public void push(int x) {
        stack1.push(x);
        size++;
    }
    //从队列的开头移除并返回元素
    public int pop() {
        if(empty()){
            return -1;
        }
        if(!stack2.isEmpty()){
            size--;
            return stack2.pop();
        }else if(stack2.isEmpty() && !stack1.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            size--;
            return stack2.pop();
        }
        return -1;
    }
    //返回队列开头的元素
    public int peek() {
        if(empty()){
            return -1;
        }
        if(!stack2.isEmpty()){
            return stack2.peek();
        }else if(stack2.isEmpty() && !stack1.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            return stack2.peek();
        }
        return -1;
    }
    //如果队列为空,返回 true ;否则,返回 false
    public boolean empty() {
        return size == 0;
    }

总结

本篇文章介绍了有关数据结构中的栈和队列的相关内容,以及它们的简单实现,和简单使用,如果有什么不正确的或者不严谨的地方,还望指正,谢谢大家!

相关推荐
心灵彼岸-诗和远方4 分钟前
高效协作:前后端合作规范与应对策略优化
java·架构·devops
我来变强了5 分钟前
EndpointConfig端点配置类使用
java·websocket·网络协议
Horacek8 分钟前
《C++ 实现生成多个弹窗程序》
java·开发语言·c++·学习·算法
白羊@10 分钟前
01、Spring MVC入门程序
java·spring·mvc
licy__11 分钟前
python的matplotlib实现数据分析绘图
开发语言·python
曾经的三心草13 分钟前
JavaWeb之AJAX
java·ajax·json·axios·web
zero_one_Machel20 分钟前
leetcodeQ76最小覆盖子串
java·开发语言·算法
luky!26 分钟前
算法----查找列表中元素的最小值和最大值
开发语言·python·算法
长安 故里30 分钟前
TiDB v7.5.4安装部署
java·linux·tidb
运维佬31 分钟前
要卸载 Grafana 或者从 TiDB 集群中删除 Grafana 服务节点,你需要按以下步骤操作
java·tidb·grafana