java数据结构-------栈和队列


目标:1、 栈的概念及使用,2、 队列的概念及使用,3.、相关OJ题

1、栈(Stack)

1、什么是栈

栈:
1、一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。

2、进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
3、栈中的数据元素遵守先进后出的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。

进栈:
在这里插入图片描述
出栈
在这里插入图片描述

2、栈中常使用的方法

在这里插入图片描述

public class Test {
    public static void main(String[] args) {
        Stack stack = new Stack<>();//构造一个空栈

        //push()方法是往栈中存放元素
        stack.push(1);//向栈中压入元素,底层可以理解为是以数组的形式存储的
        stack.push(2);
        stack.push(3);
        System.out.println(stack);
    }
}

运行结果:
在这里插入图片描述

//pop()方法是将栈顶元素弹出,并返回栈顶元素
        //所谓栈顶元素就是最后入栈的元素
        stack.pop();
        System.out.println(stack);

运行结果:
在这里插入图片描述

        //peek()方法是获取栈顶元素,并不弹出
        System.out.println(stack.peek());

运行结果:
在这里插入图片描述

      stack.push(1);//向栈中压入元素,底层可以理解为是以数组的形式存储的
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        System.out.println(stack);

    //获取栈中有效元素的个数
        int ret = stack.size();
        System.out.println(ret);

运行结果:
在这里插入图片描述

        //判断栈是否为空,栈为空返回true,栈中有元素返回false
        Boolean flag = stack.isEmpty();
        System.out.println(flag);

运行结果:
在这里插入图片描述

3、栈的应用场景

1、逆序打印链表

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class Test1 {
    Stack stack = new Stack<>();//构造一个空栈

    class ListNode{
        public int val;
        ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }
    ListNode head;
    public ListNode creatNode(){
        ListNode listNode1 = new ListNode(1);
        ListNode listNode2 = new ListNode(2);
        ListNode listNode3 = new ListNode(3);
        ListNode listNode4 = new ListNode(4);
        ListNode listNode5 = new ListNode(5);
        
        head = listNode1;//创建一个头结点
        
        listNode1.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;
        listNode4.next = listNode5;
        listNode5.next = null;
        return listNode1;
        
    }


    public void print(ListNode Node){
        ListNode cur = Node;//将原始链表的头结点保存,防止丢失

        //打印原始链表
        while (Node != null){
            System.out.print(Node.val+" ");
            Node = Node.next;
        }
        System.out.println();

        //将链表中的元素存入栈中
        while (cur != null){
            stack.push(cur.val);//元素入栈
            cur = cur.next;
        }

        //在链表不为空的情况下,将栈中元素出栈并打印
        //重点:栈中的元素是先入后出
        while(!stack.isEmpty()){
            System.out.print(stack.pop()+" ");
        }

    }
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.creatNode();//创建一个链表
        test1.print(test1.head);//逆序打印一个链表
        
    }

}

运行结果:
在这里插入图片描述

2、有效的括号

力扣第20题:添加链接描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

其次,我们要想到利用栈相关的知识去解决问题
解题思路:

创建一个栈,并将所有的左括号压入栈中,一旦遇到右括号,从栈中弹出一个元素与之比较,相同则继续比较下一个,否则返回false;因为栈是先进后出的特性,所以弹出的那个元素就是与右括号相邻的左括号。

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack();//创建一个栈
          for(int i=0;i<s.length();i++){
          //遍历整个字符串,并获取每一个元素
              char x  = s.charAt(i);
              //元素是左括号,则存入栈中
              if(x == '('||x == '['||x == '{'){
                 stack.push(x);
              }else{
                  if(stack.empty()){
                      return false;
                  }
                  char ch2 = stack.peek();
                  //先判断栈中最顶部的元素是否与之匹配
                  if((x==')'&&ch2=='(')||(x=='}'&&ch2=='{')||(x==']'&&ch2=='[')){
                  //如果匹配,则弹出该元素
                       stack.pop();
                  }else{
                  //否则返回false
                      return false;
                  }


              }
          }
          //当字符串遍历完成之后,如果栈不为空,则意味着左括号多了,此时也返回false
          if(!stack.empty()){
              return false;
          }
          //当字符串遍历完成之后,如果栈为空,此时也返回true;
          return true;
          
    }
}

2、队列(Queue)

1、什么是队列

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特性。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头

队的插入删除操作是在队的两端进行的,这一点需要和栈进行区别

在这里插入图片描述

2、队列的使用

在Java中,Queue(队列)是个接口,底层是通过链表实现的。

在这里插入图片描述

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

public class Test {

        public static void main(String[] args) {
            Queue<Integer> queue = new LinkedList<Integer>();
            //因为Queue只是一个接口,所以我们要创建一个LinkedList,并进行向下转型

            //offer()往队列中放入元素
            queue.offer(1);
            queue.offer(2);
            queue.offer(3);
            queue.offer(4);
            System.out.println(queue);//因为Queue底层是链表实现的,所以我们直接打印即可

        }
}

运行结果:
在这里插入图片描述

          //poll()将队头的元素删除
            queue.poll();
            System.out.println(queue);

运行结果:
在这里插入图片描述
peek()、isEmpty()、size()使用方法与Stack相同,故不再做过多讲解。

3、循环队列

实际中我们有时还会使用一种队列叫循环队列

循环队列通常使用数组实现。
在这里插入图片描述

创建一个循环队列:
题目地址:
添加链接描述

//MyCircularQueue(k): 构造器,设置队列长度为 k 。
//Front: 从队首获取元素。如果队列为空,返回 -1 。
//Rear: 获取队尾元素。如果队列为空,返回 -1 。
//enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
//deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
//isEmpty(): 检查循环队列是否为空。
//isFull(): 检查循环队列是否已满。

class MyCircularQueue {

    public int[] elem;
     public int front;//队头
    public int rear;//队尾


   //构造器,设置队列长度为 k
    public MyCircularQueue(int k) {
    //创建一个k+1长度的数组,防止溢出
         elem = new int[k+1];

    }


    // enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
    public boolean enQueue(int value) {
        if(isFull()){
        //数组已满的情况下,直接返回false
            return false;
        }

        elem[rear] = value;
        rear = (rear+1)%elem.length;
        return true;

    }

    //    deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。

    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }
        front = (front+1)%elem.length;
        return true;

    }


    //    Front: 从队首获取元素。如果队列为空,返回 -1 。

    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];
        }
    }

    //    isEmpty(): 检查循环队列是否为空。

    public boolean isEmpty() {
        if(front == rear){
            return true;
        }
        return false;

    }


    //    isFull(): 检查循环队列是否已满。

    public boolean isFull() {
          if((rear+1)%elem.length == front){
              return true;
          }
          return false;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值