• 【数据结构与算法】栈与队列相关算法的实现


    目录

    检查括号是否成对出现

    反转字符串

    循环队列的实现

    使用队列实现栈

    使用栈实现队列


    检查括号是否成对出现

    算法要求

    给定一个只包括 '(',')','{','}','[',']' 的字符串,判断该字符串是否有效。
    有效字符串需满足:

    1. 左括号必须用相同类型的右括号闭合。
    2. 左括号必须以正确的顺序闭合。

    比如: "()"、"()[]{}"、"{[]}" 都是有效字符串,而 "(]" 、"([)]" 则不是 

    解题思路     

    1、我们可以通过一个HashMap来存放所有括号类型,右括号为键,左括号为值。

    2、遍历字符串,如果是左括号就入栈,右括号则和栈顶元素作比较,如果刚好形成一对完成括号,则继续。否则说明不是一对完整括号。

    3、遍历结束后判断栈中元素是否全部取出,只有全部取出,说明这个字符串中符号成对出现。

    1. /**
    2. * 判断这个符号字符串中符号是否成对出现
    3. * @param s
    4. * @return
    5. */
    6. public static boolean isValid(String s){
    7. //创建一个hashMap把所有符号都存入
    8. Map maps =new HashMap<>();
    9. maps.put(')','(');
    10. maps.put(']','[');
    11. maps.put('}','{');
    12. Stack stack =new Stack<>();
    13. //将字符串转换为字符数组
    14. char[] chars= s.toCharArray();
    15. //遍历字符数组
    16. for (int i = 0; i
    17. //判断这个符号是否为右括号
    18. if (maps.containsKey(chars[i])){
    19. //栈中如果为空赋值为#否则取出栈顶元素
    20. char isEmpty =stack.isEmpty()?'#':stack.pop();
    21. //判断这个右括号对应的左括号是否等于栈顶元素
    22. if (isEmpty!=maps.get(chars[i])){
    23. return false;
    24. }
    25. }else {
    26. //如果为左括号则入栈
    27. stack.push(chars[i]);
    28. }
    29. }
    30. //遍历结束 如果栈中还有元素 则说明其中没有对应括号
    31. return stack.isEmpty();
    32. }

    测试

    1. public static void main(String[] args) {
    2. System.out.println("[]{}()中符号是否成对出现:"+isValid("[]{}()"));
    3. System.out.println("{([})}中符号是否成对出现:"+isValid("{([])}"));
    4. System.out.println("([)]中符号是否成对出现:"+isValid("([)]"));
    5. System.out.println("(()中符号是否成对出现:"+isValid("(()"));
    6. }

    测试结果


    反转字符串

    这个就直接运用栈的后进先出原则,把字符串依次入栈再出栈就行。

    1. /**
    2. * 字符串的反转
    3. * @param s
    4. * @return
    5. */
    6. public static String stringReversal(String s){
    7. Stack stack =new Stack<>();
    8. for (int i =0;i
    9. stack.push(s.charAt(i));
    10. }
    11. String news="";
    12. for (int i = 0, len = stack.size(); i < len; i++) {
    13. news+=stack.pop();
    14. }
    15. return news;
    16. }

    测试

    1. public static void main(String[] args) {
    2. String ts ="the shy";
    3. String yskm ="you should know me";
    4. System.out.println("ts反转前:"+ts);
    5. System.out.println("ts反转后:"+stringReversal(ts));
    6. System.out.println("yskm反转前:"+yskm);
    7. System.out.println("yskm反转后:"+stringReversal(yskm));
    8. }

    测试结果


    循环队列的实现

    和队列相比,循环队列的优点就是不会造成假溢出,因为当队尾到达数组的末尾时,如果数组头部还有空间,则会继续向头部移动。会形成一个循环,除非队尾与队头相邻,则队列才满。

    1. /**
    2. * 循环队列的实现
    3. * @author CC
    4. * @version 1.0
    5. * @since2023/9/28
    6. */
    7. public class CircularQueue {
    8. private int[] array;//使用数组来存储
    9. private int front;//对头
    10. private int rear;//队尾
    11. //实例队列并设置初始容量
    12. public CircularQueue(int capacity){
    13. this.array =new int[capacity];
    14. }
    15. /**
    16. * 入队
    17. * @param element
    18. * @throws Exception
    19. */
    20. public void offer(int element) throws Exception {
    21. //队尾不能存值 所以队尾的下一个元素如果是队头 说明队列已满
    22. if ((rear+1)%array.length==front){
    23. throw new Exception("队列已满!");
    24. }
    25. //将值存入队尾
    26. array[rear] =element;
    27. //队尾向后移动
    28. rear =(rear+1)%array.length;
    29. }
    30. /**
    31. * 出队
    32. * @return
    33. * @throws Exception
    34. */
    35. public int pull() throws Exception {
    36. //如果队头等于队尾 则只有一个可能 就是该队为空
    37. if (rear==front){
    38. throw new Exception("队列为空!");
    39. }
    40. //取出队头元素
    41. int deQueueElement =array[front];
    42. //队头向后移动
    43. front=(front+1)%array.length;
    44. return deQueueElement;
    45. }
    46. /**
    47. * 输出队列
    48. * @return
    49. */
    50. @Override
    51. public String toString() {
    52. StringJoiner sj =new StringJoiner("-");
    53. for (int i=front;i!=rear;i=(i+1)%array.length){
    54. sj.add(String.valueOf(array[i]));
    55. }
    56. return sj.toString()+"-队尾";
    57. }
    58. }

    测试

    1. /**
    2. * @author CC
    3. * @version 1.0
    4. * @since2023/9/28
    5. */
    6. public class CTest {
    7. public static void main(String[] args) throws Exception {
    8. CircularQueue queue = new CircularQueue(5);
    9. queue.offer(1);
    10. queue.offer(2);
    11. queue.offer(3);
    12. queue.offer(4);
    13. System.out.println("接连将1、2、3、4分别入队后:"+queue);
    14. queue.pull();
    15. System.out.println("发生一次出队后:"+queue);
    16. queue.offer(5);
    17. System.out.println("将5入队后:"+queue);
    18. }
    19. }

    测试结果


    使用队列实现栈

    实现原理

    通过创建两个队列,一个为出栈队列,一个为入栈队列。首先入栈队列是一直为空的,在入栈时先将元素存入入栈队列,再将出栈队列的元素依次存入入栈队列,这就将刚入元素就被放入了队尾。然后交换两个队列,出栈时将出栈队列队头元素出栈,也就是最早入栈的元素。

    1. /**
    2. * @author CC
    3. * @version 1.0
    4. * @since2023/9/30
    5. */
    6. public class MyStack {
    7. private Queue queue1; //出栈队列
    8. private Queue queue2; //入栈队列
    9. /**
    10. * 初始化栈 底层使用链表存储
    11. */
    12. public MyStack() {
    13. queue1 = new LinkedList();
    14. queue2 = new LinkedList();
    15. }
    16. /**
    17. * 入栈
    18. * @param item
    19. */
    20. public void push(int item) {
    21. //将元素存入队列2
    22. queue2.offer(item);
    23. //将队列1中元素依次出队 并存入队列2
    24. while (!queue1.isEmpty()){
    25. queue2.offer(queue1.poll());
    26. }
    27. //交换队列1 与 队列2
    28. Queue temp = queue1;
    29. queue1 = queue2;
    30. queue2 = temp;
    31. }
    32. /**
    33. * 出栈
    34. * @return
    35. */
    36. public int pop(){
    37. return queue1.poll();
    38. }
    39. /**
    40. * 获取栈顶元素
    41. * @return
    42. */
    43. public int top(){
    44. return queue1.peek();
    45. }
    46. /**
    47. * 判断该栈是否为空
    48. * @return
    49. */
    50. public boolean isEmpty(){
    51. return queue1.isEmpty();
    52. }
    53. /**
    54. * 输出栈中元素
    55. * @return
    56. */
    57. @Override
    58. public String toString() {
    59. StringJoiner sj =new StringJoiner("-");
    60. for (Integer integer : queue1) {
    61. sj.add(String.valueOf(integer));
    62. }
    63. return "栈顶"+sj.toString();
    64. }
    65. }

    测试

    1. /**
    2. * @author CC
    3. * @version 1.0
    4. * @since2023/9/30
    5. */
    6. public class MyStackT {
    7. public static void main(String[] args) {
    8. MyStack stack =new MyStack();
    9. stack.push(1);
    10. stack.push(2);
    11. stack.push(3);
    12. stack.push(4);
    13. System.out.println("1、2、3、4依次入栈后:"+stack);
    14. System.out.println("出栈元素:"+stack.pop());
    15. System.out.println("出栈一次后:"+stack);
    16. System.out.println("查看栈顶元素(不取出):"+stack.top());
    17. System.out.println("查看栈顶元素后:"+stack);
    18. System.out.println("该栈是否为空:"+stack.isEmpty());
    19. System.out.println("出栈元素:"+stack.pop());
    20. System.out.println("出栈元素:"+stack.pop());
    21. System.out.println("出栈元素:"+stack.pop());
    22. System.out.println("该栈是否为空:"+stack.isEmpty());
    23. }
    24. }

     测试结果


    使用栈实现队列

    实现原理

    创建两个栈,一个为入队栈、一个为出队栈。入队栈的出栈顺序为后进先出。因为出队时,需要把入队栈的元素依次出栈再入栈到出队栈。后进先出的后进先出就为先进先出。所以出队栈的出栈顺序为先进先出。以此来实现和队列相同逻辑,先进先出。

    1. /**
    2. * @author CC
    3. * @version 1.0
    4. * @since2023/9/30
    5. */
    6. public class MyQueue {
    7. private Stack inStack =new Stack<>(); //入队栈
    8. private Stack outStack =new Stack<>(); //出队栈
    9. /**
    10. * 入队
    11. * @param item
    12. */
    13. public void offer(int item){
    14. //将出堆栈中的元素依次放入入队栈中
    15. while (!outStack.isEmpty()){
    16. inStack.push(outStack.pop());
    17. }
    18. //入队栈入栈
    19. inStack.push(item);
    20. }
    21. /**
    22. * 出队
    23. * @return
    24. */
    25. public int poll(){
    26. //将入堆栈中的元素依次放入出队栈中
    27. while (!inStack.isEmpty()){
    28. outStack.push(inStack.pop());
    29. }
    30. //出堆栈出栈
    31. return outStack.pop();
    32. }
    33. /**
    34. * 判断队中是否为空
    35. * @return
    36. */
    37. public boolean isEmpty(){
    38. return inStack.isEmpty()&outStack.isEmpty();
    39. }
    40. /**
    41. * 查看队列元素
    42. * @return
    43. */
    44. @Override
    45. public String toString() {
    46. while (!inStack.isEmpty()){
    47. outStack.push(inStack.pop());
    48. }
    49. StringJoiner sj =new StringJoiner("-");
    50. for (Integer integer : outStack) {
    51. sj.add(integer.toString());
    52. }
    53. return "队尾-"+sj.toString();
    54. }
    55. }

    测试

    1. public class MyQueueT {
    2. public static void main(String[] args) {
    3. MyQueue myQueue =new MyQueue();
    4. // 入队
    5. myQueue.offer(1);
    6. myQueue.offer(2);
    7. myQueue.offer(3);
    8. myQueue.offer(4);
    9. myQueue.offer(5);
    10. System.out.println("依次入队1、2、3、4、5后:"+myQueue);
    11. // 出队
    12. System.out.println("出队:"+myQueue.poll()); // 1
    13. System.out.println("出队:"+myQueue.poll()); // 2
    14. System.out.println("出队:"+myQueue.poll()); // 3
    15. System.out.println("连续三次出队后:"+myQueue);
    16. // 入队
    17. myQueue.offer(6);
    18. myQueue.offer(7);
    19. myQueue.offer(8);
    20. System.out.println("依次入队6、7、8后:"+myQueue);
    21. // 出队
    22. System.out.println("出队:"+myQueue.poll()); // 4
    23. System.out.println("出队:"+myQueue.poll()); // 5
    24. System.out.println("出队:"+myQueue.poll()); // 6
    25. System.out.println("连续三次出队后:"+myQueue);
    26. System.out.println("队内是否为空:"+myQueue.isEmpty());
    27. System.out.println("出队:"+myQueue.poll()); // 7
    28. System.out.println("出队:"+myQueue.poll()); // 8
    29. System.out.println("队内是否为空:"+myQueue.isEmpty());
    30. }
    31. }

    测试结果

  • 相关阅读:
    电脑电源灯一闪一闪开不了机怎么办
    汇编基础(1)--ARM32
    十二、SpringBoot文件上传使用及流程分析【文件上传参数解析器】
    备战数学建模48-数学规划模型终结篇(全)(攻坚战13)
    前端面试题JS篇(3)
    Opencv 基本操作三 实现各个形态学处理并实现多图展示
    精心整理了超详细的Linux入门笔记,零基础也能看懂,一学就会
    辅助驾驶功能开发-执行器篇(03)-Mobileye Control Requirements
    leetcode-二叉搜索树与双向链表-89
    python的/ 和// 学习
  • 原文地址:https://blog.csdn.net/c1390527393/article/details/133430258