当前位置:   article > 正文

Java集合框架:栈、Stack详解_java栈

java栈

目录

一、栈

二、栈的使用

         1. Stack类

2. 栈的模拟实现

三、栈的应用场景

1. 改变元素的序列

2. 将递归转化为循环(如:逆序打印链表)

3. 栈的oj题练习(oj题中都用到了栈这种数据结构)

四、栈,虚拟机栈,栈帧的区别


前言

    栈是一种数据结构,一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作。数据插入和删除的操作的一端称作栈顶,另一端称作栈底。栈中的数据元素遵守一个原则:先进后出。   

一、栈

压栈:栈的插入操作叫做压栈/ 进栈,压栈在栈顶操作。

出栈:栈的删除操作叫做出栈,出栈数据也是在栈顶。

 如下图解:

     栈中的数据元素遵循后进先出的原则(Last in first out)就像子弹的上膛操作和射击操作。

二、栈的使用

    在Java集合框架中,栈使用的具体类是Stack,(但是并不是只有Sack一个类可以当作栈来使用)接下来就具体介绍下集合框架中栈的使用。

 1. Stack类

    Stack类的方法的使用:

Stack()实例化一个栈(此时栈是空的)

E push(E e)

压栈操作,将e元素入栈,并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素(但此时栈顶元素并没有出栈,只是看了一眼栈顶元素是哪个)
int size()获取栈中有效元素个数
boolean empty()判断栈是否为空(是否有元素),返回值为布尔类型

    栈方法的使用演示:

  1. public static void main(String[] args) {
  2. Stack<Integer> stack = new Stack<>();
  3. stack.push(1);
  4. stack.push(2);
  5. stack.push(3);
  6. stack.push(4);
  7. System.out.println(stack.size());
  8. System.out.println(stack.peek());
  9. System.out.println(stack.pop());
  10. System.out.println(stack.size());
  11. System.out.println(stack.empty());
  12. }

要想真正了解Stack类中方法实现的逻辑最好还是模拟实现一个栈;

2. 栈的模拟实现

  1. //用数组/顺序表实现的栈
  2. //顺序栈
  3. public class MyStack {
  4. public int[] elem;
  5. public int usedSize;
  6. public MyStack() {
  7. this.elem = new int[10];
  8. }
  9. //压栈
  10. public void push(int val) {
  11. if (isFull()) {
  12. elem = Arrays.copyOf(elem,2*elem.length);
  13. }
  14. elem[usedSize++] = val;
  15. }
  16. public boolean isFull() {
  17. return usedSize == elem.length;
  18. }
  19. //出栈
  20. public int pop() {
  21. if (isEmpty()) {
  22. throw new EmptyException("栈是空的!");
  23. }
  24. /*int val = elem[usedSize - 1];
  25. usedSize--;
  26. return val;*/
  27. return elem[--usedSize];
  28. }
  29. public boolean isEmpty() {
  30. return usedSize == 0;
  31. }
  32. //求栈中元素个数
  33. public int size() {
  34. return usedSize;
  35. }
  36. //获取栈顶元素
  37. public int peek() {
  38. if (isEmpty()) {
  39. throw new EmptyException("栈是空的!");
  40. }
  41. return elem[usedSize - 1];
  42. }

三、栈的应用场景

1. 改变元素的序列

 2. 将递归转化为循环(如:逆序打印链表)

     几种打印链表的方式:

  1. //递归打印链表(逆序打印链表)
  2. public void display3(ListNode pHead) {
  3. if (pHead == null) return;
  4. if (pHead.next == null) {
  5. System.out.print(pHead.val + " ");
  6. return;
  7. }
  8. display3(pHead.next);
  9. System.out.print(pHead.val + " ");
  10. }
  11. //用栈结构打印链表(逆序打印链表)
  12. public void display4() {
  13. Stack<ListNode> stack = new Stack<>();
  14. ListNode cur = head;
  15. while (cur != null) {
  16. stack.push(cur);
  17. cur = cur.next;
  18. }
  19. //遍历栈
  20. while (!stack.isEmpty()) {
  21. ListNode top = stack.pop();
  22. System.out.print(top.val + " ");
  23. }
  24. System.out.println();
  25. }
  26. //遍历打印链表
  27. public void display() {
  28. ListNode cur = head;
  29. while (cur != null) {
  30. System.out.print(cur.val + " ");
  31. cur = cur.next;
  32. }
  33. System.out.println();
  34. }

3. 栈的oj题练习(oj题中都用到了栈这种数据结构)

1. 括号匹配    力扣思路:用栈这种数据结构即可解决问题:遇到的左括号就入栈,如果遇到右括号就获取栈顶元素进行匹配,能够匹配就出栈。 最后看栈是否为空,如果站空,则括号就是匹配的。
2. 逆波兰表达式求值    力扣思路:遇到操作数就入栈,遇到运算符就出栈两个操作数(注:先出右操作数,再出左边操作数) ,进行运算,之后把运算结果入栈,然后重复上述操作,最后栈中的元素就是表达式的结果。
3. 出栈入栈次序匹配    栈的压入、弹出序列_牛客题霸思路:先入栈压入序列,在压入序列入栈的过程中,判断出栈序列中的数据和入栈序列中的数据是否相同,如果相同就开始出栈,最后看栈是否为空,如果栈空,入栈序列和出栈序列就是相对应的。
4. 最小栈    力扣思路:用两个栈,其中一个放入的元素是入栈的序列,另一个栈维护最小值,当minStack空时,先入栈第一个元素,之后和入栈序列中的元素进行比较,如果minStack中的栈顶元素比当前入栈元素大,此时就更新minStack中的最小值。

四、栈,虚拟机栈,栈帧的区别

是一种数据结构,在Java标准库中有对应的实现 --> Stack类,而Stack类是继承于Vector的,和Vector的区别:Stack不是线程安全的,而Vector是线程安全的。

虚拟机栈是一块有特殊作用的内存空间,jvm为了对数据更好的管理,将内存按照不同的需求划分出的一种结构。 栈区:包含方法调用的相关信息,最主要的就是栈帧,其中栈帧是按照栈这种数据结构实现的。
栈帧当new一个对象或赋值内置类型时,jvm就会在栈区中开辟一块空间,这块空间就是在栈区中,栈帧也是一种结构,包含局部变量表,操作数....每个方法在运行时,jvm都会创建一个栈帧,然后将栈帧入栈到虚拟机栈中执行方法体,当方法调用结束时,该方法对应的栈帧就会从虚拟机中出栈。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/611816
推荐阅读
相关标签
  

闽ICP备14008679号