【数据结构与算法之线性结构】栈

﹏ヽ暗。殇╰゛Y 2024-03-25 12:36 214阅读 0赞

【数据结构与算法之线性结构】栈

文章目录

      • 【数据结构与算法之线性结构】栈
          • 1 栈的基本概念
          • 2 栈的定义
          • 3 栈的基本操作
            • 入栈
            • 出栈
          • 4 案例
            • 二/十进制转换器
            • 括号匹配问题
1 栈的基本概念

栈Stack 是一个后进先出 LIFO的线性表,它要求只能在表尾执行删除和插入等操作。其实栈就是一个线性表(可以是数组,也可以是链表),就是操作受到限制。

栈的操作只能在线性表尾进行,表尾 → 栈顶top,表头 → 栈底bottom。

在这里插入图片描述

2 栈的定义

使用数组实现栈。

  1. /**
  2. * @Projectname: JavaData_StructureAndAlgorithm
  3. * @Classname: MyStack
  4. * @Author: Ding Jiaxiong
  5. * @Data:2023/3/13 9:27
  6. */
  7. public class MyStack {
  8. int[] stack; // 数组实现栈
  9. int top; // 栈顶索引
  10. int capacity; // 栈的容量
  11. public MyStack(int capacity) {
  12. stack = new int[capacity]; // 动态初始化栈,长度为capacity
  13. top = 0; // 栈顶索引为0,说明此时栈空
  14. this.capacity = capacity; // 初始化栈的容量
  15. }
  16. public void push(int elem) {
  17. // 元素入栈
  18. }
  19. public int pop() {
  20. // 出栈
  21. }
  22. public void increaseCapacity() {
  23. // 增加栈的容量
  24. }
  25. }

这里我们并没有定义栈顶位置的值,因为用数组实现栈的话,bottom恒为0就行了,如果使用链表实现栈,则需要定义bottom,它应该是指向栈顶节点的指针变量。

初始化后,top = bottom = 0,说明此时空栈。

3 栈的基本操作
入栈

入栈就是向栈中存入数据。入栈操作在栈顶执行,每当向栈中压入一个数据,栈顶指针top + 1,直到栈满。

  1. public void push(int elem) {
  2. // 元素入栈
  3. if (top == capacity) {
  4. // 扩容
  5. increaseCapacity();
  6. }
  7. stack[top] = elem;
  8. top++;
  9. }
  10. public void increaseCapacity() {
  11. // 增加栈的容量
  12. // 初始化一个新栈,容量是原栈容量的2倍
  13. int[] stackTmp = new int[stack.length * 2];
  14. System.arraycopy(stack, 0, stackTmp, 0, stack.length);
  15. stack = stackTmp;
  16. }

top 始终指向栈顶元素的上一个位置,所以当top 数值上 = capacity时,说明栈满。

出栈

出栈与入栈相反,从栈顶取出元素,top -1 。

  1. public int pop() {
  2. // 出栈
  3. if (top == 0) {
  4. System.out.println("栈中没有数据");
  5. return -1; // 返回一个无效值
  6. }
  7. top--;
  8. return stack[top];
  9. }

测试

  1. /**
  2. * @Projectname: JavaData_StructureAndAlgorithm
  3. * @Classname: MyStack
  4. * @Author: Ding Jiaxiong
  5. * @Data:2023/3/13 9:27
  6. */
  7. public class MyStack {
  8. int[] stack; // 数组实现栈
  9. int top; // 栈顶索引
  10. int capacity; // 栈的容量
  11. public MyStack(int capacity) {
  12. stack = new int[capacity]; // 动态初始化栈,长度为capacity
  13. top = 0; // 栈顶索引为0,说明此时栈空
  14. this.capacity = capacity; // 初始化栈的容量
  15. }
  16. public void push(int elem) {
  17. // 元素入栈
  18. if (top == capacity) {
  19. // 扩容
  20. increaseCapacity();
  21. }
  22. stack[top] = elem;
  23. top++;
  24. }
  25. public void increaseCapacity() {
  26. // 增加栈的容量
  27. // 初始化一个新栈,容量是原栈容量的2倍
  28. int[] stackTmp = new int[stack.length * 2];
  29. System.arraycopy(stack, 0, stackTmp, 0, stack.length);
  30. stack = stackTmp;
  31. }
  32. public int pop() {
  33. // 出栈
  34. if (top == 0) {
  35. System.out.println("栈中没有数据");
  36. return -1; // 返回一个无效值
  37. }
  38. top--;
  39. return stack[top];
  40. }
  41. public static void main(String[] args) {
  42. MyStack stack = new MyStack(3);
  43. stack.push(1);
  44. stack.push(2);
  45. stack.push(3);
  46. stack.push(4);
  47. stack.push(5);
  48. System.out.println(stack.pop());
  49. System.out.println(stack.pop());
  50. System.out.println(stack.pop());
  51. System.out.println(stack.pop());
  52. System.out.println(stack.pop());
  53. }
  54. }

运行结果

在这里插入图片描述

如果再弹

在这里插入图片描述

没问题。

4 案例
二/十进制转换器

利用栈结构将二进制数转为十进制数。

举个栗子:将二进制数 11001转换为十进制数, → 1x2^0 + 0x2^1 + 0x2^2 + 1x2^3 + 1x2^4 = 25.

由于栈后进先出的特性,首先将二进制数从高位到地位顺序入栈,从栈顶依次取出,第i个元素,就对应的乘上 2 i − 1 2^{i - 1} 2i−1 。

Java代码实现:

  1. /**
  2. * @Projectname: JavaData_StructureAndAlgorithm
  3. * @Classname: BiToDecTest
  4. * @Author: Ding Jiaxiong
  5. * @Data:2023/3/13 10:15
  6. */
  7. public class BiToDecTest {
  8. public static String BiToDec(String binary) {
  9. MyStack stack = new MyStack(10);
  10. int i;
  11. // 将二进制串binary 从高位到地位入栈
  12. for (i = 0; i < binary.length(); i++) {
  13. if (binary.charAt(i) == '0') {
  14. stack.push(0); // 将0整数形式入栈
  15. } else {
  16. stack.push(1); // 1同理
  17. }
  18. }
  19. i = 0;
  20. int e;
  21. long sum = 0;
  22. // 将栈中元素顺序出栈,并将其转换为十进制数
  23. while ((e = stack.pop()) != -1) {
  24. // 没到栈底
  25. sum += (int) (e * Math.pow(2, i));
  26. i++;
  27. }
  28. return String.valueOf(sum);
  29. }
  30. public static void main(String[] args) {
  31. System.out.println(BiToDec("11001"));
  32. }
  33. }

运行结果

在这里插入图片描述

括号匹配问题

判断表达式中有两种括号, () 和 [],括号必须成对出现,编写一个程序,判断一个括号表达式是否合法。

【经典问题】利用栈来保存输入的括号,并判断输入的括号表达式是否合法。

每输入一个括号都与栈顶的括号进行比较,如果输入括号与栈顶保存的括号匹配,则栈顶出栈,如果不匹配,则输入符号入栈。输入完毕时,栈为空则表示合法,如果栈中还有剩余元素,则表明输入不完全匹配。

Java实现:

稍微进行了修改的自定义栈类:

  1. /**
  2. * @Projectname: JavaData_StructureAndAlgorithm
  3. * @Classname: MyStack
  4. * @Author: Ding Jiaxiong
  5. * @Data:2023/3/13 9:27
  6. */
  7. public class MyStack {
  8. char[] stack; // 数组实现栈
  9. int top; // 栈顶索引
  10. int capacity; // 栈的容量
  11. public MyStack(int capacity) {
  12. stack = new char[capacity]; // 动态初始化栈,长度为capacity
  13. top = 0; // 栈顶索引为0,说明此时栈空
  14. this.capacity = capacity; // 初始化栈的容量
  15. }
  16. public void push(char elem) {
  17. // 元素入栈
  18. if (top == capacity) {
  19. // 扩容
  20. increaseCapacity();
  21. }
  22. stack[top] = elem;
  23. top++;
  24. }
  25. public void increaseCapacity() {
  26. // 增加栈的容量
  27. // 初始化一个新栈,容量是原栈容量的2倍
  28. char[] stackTmp = new char[stack.length * 2];
  29. System.arraycopy(stack, 0, stackTmp, 0, stack.length);
  30. stack = stackTmp;
  31. }
  32. public char pop() {
  33. // 出栈
  34. if (top == 0) {
  35. // System.out.println("栈中没有数据");
  36. return ' '; // 返回一个无效值
  37. }
  38. top--;
  39. return stack[top];
  40. }
  41. public static void main(String[] args) {
  42. MyStack stack = new MyStack(3);
  43. stack.push('a');
  44. stack.push('b');
  45. stack.push('c');
  46. stack.push('d');
  47. stack.push('e');
  48. System.out.println(stack.pop());
  49. System.out.println(stack.pop());
  50. System.out.println(stack.pop());
  51. System.out.println(stack.pop());
  52. System.out.println(stack.pop());
  53. }
  54. }

测试

  1. import java.util.Stack;
  2. /**
  3. * @Projectname: JavaData_StructureAndAlgorithm
  4. * @Classname: MatchBracketTest
  5. * @Author: Ding Jiaxiong
  6. * @Data:2023/3/13 10:28
  7. */
  8. public class MatchBracketTest {
  9. private static boolean match(char a, char b) {
  10. if ((a == '(' && b == ')') || (a == '[' && b == ']')) {
  11. return true;
  12. }
  13. return false;
  14. }
  15. public static boolean MatchBracket(String expression) {
  16. // 判断括号表达式expression是否合法
  17. MyStack stack = new MyStack(10);
  18. char c;
  19. for (int i = 0; i < expression.length(); i++) {
  20. if ((c = stack.pop()) != ' ') {
  21. if (!match(c, expression.charAt(i))) {
  22. stack.push(c);
  23. stack.push(expression.charAt(i));
  24. }
  25. } else {
  26. stack.push(expression.charAt(i));
  27. }
  28. }
  29. if (stack.pop() != ' ') {
  30. return false;
  31. } else {
  32. return true;
  33. }
  34. }
  35. public static void main(String[] args) {
  36. String expression = "[([])]";
  37. System.out.println(MatchBracket(expression));
  38. }
  39. }

运行结果【匹配情况】

在这里插入图片描述

不匹配情况

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,214人围观)

还没有评论,来说两句吧...

相关阅读

    相关 数据结构算法

    前言 在前面几篇我们有讲到数组,链表等数据结构,这些都是存储数据的最基本的结构。而本篇文章讲解的则是利用算法和数据结构来实现一些小工具,来解决现实中某种需求。它就是栈。