java-数据结构与算法-02-数据结构-05-栈

文章目录

    • 1. 栈
      • 1. 概述
      • 2. 链表实现
      • 3. 数组实现
      • 4. 应用
    • 2. 习题
      • E01. 有效的括号-Leetcode 20
      • E02. 后缀表达式求值-Leetcode 120
      • E03. 中缀表达式转后缀
      • E04. 双栈模拟队列-Leetcode 232
      • E05. 单队列模拟栈-Leetcode 225

1. 栈

1. 概述

计算机科学中,stack 是一种线性的数据结构,只能在其一端添加数据和移除数据。习惯来说,这一端称之为栈顶,另一端不能操作数据的称之为栈底,就如同生活中的一摞书

栈是一种特殊的线性表,只能在一端进行操作

  • 往栈中添加元素的操作,一般叫做 push,入栈
  • 从栈中移除元素的操作,一般叫做 pop,出栈(只能移除栈顶元素,也叫做:弹出栈顶元素)
  • 后进先出的原则,Last In First Out,LIFO
    在这里插入图片描述

先提供一个栈接口

public interface Stack<E> {/*** 向栈顶压入元素* @param value 待压入值* @return 压入成功返回 true, 否则返回 false*/boolean push(E value);/*** 从栈顶弹出元素* @return 栈非空返回栈顶元素, 栈为空返回 null*/E pop();/*** 返回栈顶元素, 不弹出* @return 栈非空返回栈顶元素, 栈为空返回 null*/E peek();/*** 判断栈是否为空* @return 空返回 true, 否则返回 false*/boolean isEmpty();/*** 判断栈是否已满* @return 满返回 true, 否则返回 false*/boolean isFull();
}

栈的应用
浏览器的前进和后退

在这里插入图片描述

2. 链表实现

package com.itheima.datastructure.stack;import java.util.Iterator;
import java.util.StringJoiner;/*** 链表实现的栈。* 该类实现了Stack接口和Iterable接口,允许对栈中的元素进行迭代。** @param <E> 栈中元素的类型。*/
public class LinkedListStack<E> implements Stack<E>, Iterable<E> {/*** 栈的容量,默认为Integer.MAX_VALUE,表示不限制容量。*/private int capacity = Integer.MAX_VALUE;/*** 栈中元素的数量。*/private int size;/*** 链表的头节点,用于简化插入和删除操作。*/private final Node<E> head = new Node<>(null, null);/*** 默认构造函数。*/public LinkedListStack() {}/*** 带容量限制的构造函数。** @param capacity 栈的容量限制。*/public LinkedListStack(int capacity) {this.capacity = capacity;}/*** 将元素压入栈顶。** @param value 要压入栈的元素。* @return 如果栈未满,则返回true;否则返回false。*//*head -> 2 -> 1 -> null*/@Overridepublic boolean push(E value) {if (isFull()) {return false;}head.next = new Node<>(value, head.next);size++;return true;}/*** 从栈顶弹出一个元素。** @return 如果栈不为空,则返回栈顶元素;否则返回null。*//*head -> 2 -> 1 -> null*/@Overridepublic E pop() {if (isEmpty()) {return null;}Node<E> first = head.next;head.next = first.next;size--;return first.value;}/*** 查看栈顶元素。** @return 如果栈不为空,则返回栈顶元素;否则返回null。*/@Overridepublic E peek() {if (isEmpty()) {return null;}return head.next.value;}/*** 检查栈是否为空。** @return 如果栈为空,则返回true;否则返回false。*/@Overridepublic boolean isEmpty() {return size == 0;}/*** 检查栈是否已满。** @return 如果栈已满,则返回true;否则返回false。*/@Overridepublic boolean isFull() {return size == capacity;}/*** 创建一个迭代器,用于遍历栈中的元素。** @return栈的元素迭代器。*/@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {Node<E> p = head.next;@Overridepublic boolean hasNext() {return p != null;}@Overridepublic E next() {E value = p.value;p = p.next;return value;}};}/*** 链表节点类,用于存储栈中的元素。** @param <E> 节点中存储的元素类型。*/static class Node<E> {E value;Node<E> next;public Node(E value, Node<E> next) {this.value = value;this.next = next;}}/*** 将栈中的元素转换为字符串表示。** @return 栈的字符串表示,元素之间用逗号分隔。*/@Overridepublic String toString() {StringJoiner sj = new StringJoiner(",");for (E e : this) {sj.add(e.toString());}return sj.toString();}
}

3. 数组实现

/*** 数组实现的栈类,支持泛型元素。* @param <E> 栈中元素的类型。*/
package com.itheima.datastructure.stack;import java.util.Iterator;public class ArrayStack<E> implements Stack<E>, Iterable<E> {/*** 存储栈元素的数组。*/private final E[] array;/*** 栈顶指针,指示当前栈的顶部元素的位置。*/private int top; // 栈顶指针/*** 构造一个指定容量的栈。* @param capacity 栈的初始容量。*/@SuppressWarnings("all")public ArrayStack(int capacity) {this.array = (E[]) new Object[capacity];}/*** 将元素压入栈顶。* @param value 要压入栈的元素。* @return 如果栈未满,则返回true;否则返回false。*/@Overridepublic boolean push(E value) {if (isFull()) {return false;}array[top++] = value;return true;}/*** 弹出栈顶元素。* @return 栈顶元素,如果栈为空,则返回null。*/@Overridepublic E pop() {if (isEmpty()) {return null;}E e = array[--top];array[top] = null; // help GCreturn e;}/*** 查看栈顶元素。* @return 栈顶元素,如果栈为空,则返回null。*/@Overridepublic E peek() {if (isEmpty()) {return null;}return array[top - 1];}/*** 检查栈是否为空。* @return 如果栈为空,则返回true;否则返回false。*/@Overridepublic boolean isEmpty() {return top == 0;}/*** 检查栈是否已满。* @return 如果栈已满,则返回true;否则返回false。*/@Overridepublic boolean isFull() {return top == array.length;}/*** 返回栈元素的迭代器,用于遍历栈。* @return栈元素的迭代器。*//*底          顶0   1   2   3a   b   c   dp*/@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = top;@Overridepublic boolean hasNext() {return p > 0;}@Overridepublic E next() {return array[--p];}};}
}

4. 应用

模拟如下方法调用

public static void main(String[] args) {System.out.println("main1");System.out.println("main2");method1();method2();System.out.println("main3");
}public static void method1() {System.out.println("method1");method3();
}public static void method2() {System.out.println("method2");
}public static void method3() {System.out.println("method3");
}

模拟代码

package com.itheima.datastructure.stack;/*** CPU模拟类,使用栈来模拟方法的调用与返回。*/
public class CPU {/*** 方法帧类,用于存储方法的退出点。*/static class Frame {int exit;/*** 构造方法,初始化方法帧的退出点。* * @param exit 方法的退出点值。*/public Frame(int exit) {this.exit = exit;}}/*** 程序计数器,用于指示当前执行的指令位置。*/static int pc = 1;/*** 方法调用栈,用于模拟方法的调用与返回过程。*/static ArrayStack<Frame> stack = new ArrayStack<>(100);/*** 程序入口点。* * @param args 命令行参数。*/public static void main(String[] args) {// 初始化方法调用栈,压入一个表示main方法开始的帧stack.push(new Frame(-1));// 当栈不为空时,循环执行指令while (!stack.isEmpty()) {// 根据程序计数器的值执行相应的操作switch (pc) {case 1:// 执行main方法的第一段代码System.out.println("main1");pc++;break;case 2:// 执行main方法的第二段代码System.out.println("main2");pc++;break;case 3:// 调用method1方法stack.push(new Frame(pc + 1));pc = 100;break;case 4:// 调用method2方法stack.push(new Frame(pc + 1));pc = 200;break;case 5:// 方法返回,从栈中弹出方法帧,并跳转到退出点System.out.println("main3");pc = stack.pop().exit;break;case 100:// method1方法的代码段System.out.println("method1");stack.push(new Frame(pc + 1));pc = 300;break;case 101:// method1方法返回pc = stack.pop().exit;break;case 200:// method2方法的代码段System.out.println("method2");pc = stack.pop().exit;break;case 300:// method3方法的代码段System.out.println("method3");pc = stack.pop().exit;break;}}}
}

2. 习题

E01. 有效的括号-Leetcode 20

一个字符串中可能出现 [] () 和 {} 三种括号,判断该括号是否有效
有效的例子

()[]{}([{}])()

无效的例子

[)([)]([]

思路

  • 遇到左括号, 把要配对的右括号放入栈顶
  • 遇到右括号, 若此时栈为空, 返回 false,否则把它与栈顶元素对比
    • 若相等, 栈顶元素弹出, 继续对比下一组
    • 若不等, 无效括号直接返回 false
  • 循环结束
    • 若栈为空, 表示所有括号都配上对, 返回 true
    • 若栈不为空, 表示右没配对的括号, 应返回 false

答案(用到了课堂案例中的 ArrayStack 类)

public boolean isValid(String s) {ArrayStack<Character> stack = new ArrayStack<>(s.length() / 2 + 1);for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);if (c == '(') {stack.push(')');} else if (c == '[') {stack.push(']');} else if (c == '{') {stack.push('}');} else {if (!stack.isEmpty() && stack.peek() == c) {stack.pop();} else {return false;}}}return stack.isEmpty();
}

E02. 后缀表达式求值-Leetcode 120

后缀表达式也称为逆波兰表达式,即运算符写在后面

  • 从左向右进行计算
  • 不必考虑运算符优先级,即不用包含括号

示例

输入:tokens = ["2","1","+","3","*"]
输出:9
即:(2 + 1) * 3输入:tokens = ["4","13","5","/","+"]
输出:6
即:4 + (13 / 5)

题目假设

  • 数字都视为整数
  • 数字和运算符个数给定正确,不会有除零发生

代码

public int evalRPN(String[] tokens) {LinkedList<Integer> numbers = new LinkedList<>();for (String t : tokens) {switch (t) {case "+" -> {Integer b = numbers.pop();Integer a = numbers.pop();numbers.push(a + b);}case "-" -> {Integer b = numbers.pop();Integer a = numbers.pop();numbers.push(a - b);}case "*" -> {Integer b = numbers.pop();Integer a = numbers.pop();numbers.push(a * b);}case "/" -> {Integer b = numbers.pop();Integer a = numbers.pop();numbers.push(a / b);}default -> numbers.push(Integer.parseInt(t));}}return numbers.pop();
}

E03. 中缀表达式转后缀

public class E03InfixToSuffix {/*思路1. 遇到数字, 拼串2. 遇到 + - * /- 优先级高于栈顶运算符 入栈- 否则将栈中高级或平级运算符出栈拼串, 本运算符入栈3. 遍历完成, 栈中剩余运算符出栈拼串- 先出栈,意味着优先运算4. 带 ()- 左括号直接入栈- 右括号要将栈中直至左括号为止的运算符出栈拼串|   ||   ||   |_____a+ba+b-ca+b*ca*b+c(a+b)*c*/public static void main(String[] args) {System.out.println(infixToSuffix("a+b"));System.out.println(infixToSuffix("a+b-c"));System.out.println(infixToSuffix("a+b*c"));System.out.println(infixToSuffix("a*b-c"));System.out.println(infixToSuffix("(a+b)*c"));System.out.println(infixToSuffix("a+b*c+(d*e+f)*g"));}/*** 将中缀表达式转换为后缀表达式。* 后缀表达式也称为逆波兰表达式,它使用栈的操作来实现运算符的优先级处理,有效地简化了计算过程。* * @param exp 中缀表达式字符串,包含数字、运算符和括号。* @return 后缀表达式字符串。*/static String infixToSuffix(String exp) {// 使用链表作为栈来存储运算符LinkedList<Character> stack = new LinkedList<>();// 使用StringBuilder来构建后缀表达式StringBuilder sb = new StringBuilder(exp.length());// 遍历中缀表达式的每个字符for (int i = 0; i < exp.length(); i++) {char c = exp.charAt(i);// 根据字符的不同类型进行处理switch (c) {case '*', '/', '+', '-' -> {// 处理运算符if (stack.isEmpty()) {stack.push(c);} else {if (priority(c) > priority(stack.peek())) {stack.push(c);} else {// 当当前运算符的优先级不高于栈顶运算符时,将栈顶运算符弹出到后缀表达式中while (!stack.isEmpty() && priority(stack.peek()) >= priority(c)) {sb.append(stack.pop());}stack.push(c);}}}case '(' -> {// 遇到左括号直接入栈stack.push(c);}case ')' -> {// 遇到右括号,将栈中的运算符依次弹出到后缀表达式中,直到遇到左括号while (!stack.isEmpty() && stack.peek() != '(') {sb.append(stack.pop());}// 弹出左括号,不加入到后缀表达式中stack.pop();}default -> {// 遇到数字直接加入到后缀表达式中sb.append(c);}}}// 将栈中剩余的运算符依次弹出到后缀表达式中while (!stack.isEmpty()) {sb.append(stack.pop());}// 返回构建好的后缀表达式return sb.toString();}/*** 计算运算符的优先级。* * @param c 运算符* @return 运算符的优先级* @throws IllegalArgumentException 如果运算符不合法,则抛出此异常*/
static int priority(char c) {// 使用switch表达式来根据运算符的类型返回对应的优先级return switch (c) {case '*' -> 2; // 乘法和除法具有相同的优先级case '/' -> 2;case '+' -> 1; // 加法和减法具有相同的优先级case '-' -> 1;case '(' -> 0; // 左括号具有最低优先级default -> throw new IllegalArgumentException("不合法的运算符:" + c);};
}}

返回结果

ab+c*
abc*+d-e*
abc+*

E04. 双栈模拟队列-Leetcode 232

给力扣题目用的自实现栈,可以定义为静态内部类

class ArrayStack<E> {private E[] array;private int top; // 栈顶指针@SuppressWarnings("all")public ArrayStack(int capacity) {this.array = (E[]) new Object[capacity];}public boolean push(E value) {if (isFull()) {return false;}array[top++] = value;return true;}public E pop() {if (isEmpty()) {return null;}return array[--top];}public E peek() {if (isEmpty()) {return null;}return array[top - 1];}public boolean isEmpty() {return top == 0;}public boolean isFull() {return top == array.length;}
}

参考解答,注意:题目已说明

  • 调用 push、pop 等方法的次数最多 100
package com.itheima.datastructure.stack;/*** 双栈模拟队列** <ul>*     <li>调用 push、pop 等方法的次数最多 100</li>* </ul>*/
public class E04Leetcode232 {/*队列头        队列尾b顶   底     底   顶s1              s2队列尾添加s2.push(a)s2.push(b)队列头移除先把 s2 的所有元素移动到 s1s1.pop()*/ArrayStack<Integer> s1 = new ArrayStack<>(100);ArrayStack<Integer> s2 = new ArrayStack<>(100);public void push(int x) { //向队列尾添加s2.push(x);}public int pop() { // 从对列头移除if (s1.isEmpty()) {while (!s2.isEmpty()) {s1.push(s2.pop());}}return s1.pop();}public int peek() { // 从对列头获取if (s1.isEmpty()) {while (!s2.isEmpty()) {s1.push(s2.pop());}}return s1.peek();}public boolean empty() {return s1.isEmpty() && s2.isEmpty();}}

E05. 单队列模拟栈-Leetcode 225

给力扣题目用的自实现队列,可以定义为静态内部类

public class ArrayQueue3<E> {private final E[] array;int head = 0;int tail = 0;@SuppressWarnings("all")public ArrayQueue3(int c) {c -= 1;c |= c >> 1;c |= c >> 2;c |= c >> 4;c |= c >> 8;c |= c >> 16;c += 1;array = (E[]) new Object[c];}public boolean offer(E value) {if (isFull()) {return false;}        array[tail & (array.length - 1)] = value;tail++;return true;}public E poll() {if (isEmpty()) {return null;}E value = array[head & (array.length - 1)];head++;return value;}public E peek() {if (isEmpty()) {return null;}return array[head & (array.length - 1)];}public boolean isEmpty() {return head == tail;}public boolean isFull() {return tail - head == array.length;}
}

参考解答,注意:题目已说明

  • 调用 push、pop 等方法的次数最多 100
  • 每次调用 pop 和 top 都能保证栈不为空
public class E05Leetcode225 {/*队列头     队列尾cba顶           底queue.offer(a)queue.offer(b)queue.offer(c)*/ArrayQueue3<Integer> queue = new ArrayQueue3<>(100);int size = 0;public void push(int x) {queue.offer(x);for (int i = 0; i < size; i++) {queue.offer(queue.poll());}size++;}public int pop() {size--;return queue.poll();}public int top() {return queue.peek();}public boolean empty() {return queue.isEmpty();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/385407.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[python游戏开发]用Python代码制作中国象棋游戏,适合新手小白练手

Pygame 做的中国象棋&#xff0c;一直以来喜欢下象棋&#xff0c;写了 python 就拿来做一个试试&#xff0c;水平有限&#xff0c;希望源码能帮助大家更好的学习 python。总共分为四个文件&#xff0c;chinachess.py 为主文件&#xff0c;constants.py 数据常量&#xff0c;pie…

新版海螺影视主题模板M3.1全解密版本多功能苹果CMSv10后台自适应主题

苹果CMS2022新版海螺影视主题M3.1版本&#xff0c;这个主题我挺喜欢的&#xff0c;之前也有朋友给我提供过原版主题&#xff0c;一直想要破解但是后来找了几个SG11解密的大哥都表示解密需要大几百大洋&#xff0c;所以一直被搁置了。这个版本是完全解密的&#xff0c;无需SG11加…

前端模块化CommonJS、AMD、CMD、ES6

在前端开发中&#xff0c;模块化是一种重要的代码组织方式&#xff0c;它有助于将复杂的代码拆分成可管理的小块&#xff0c;提高代码的可维护性和可重用性。CommonJS、AMD&#xff08;异步模块定义&#xff09;和CMD&#xff08;通用模块定义&#xff09;是三种不同的模块规范…

1、hadoop环境搭建

1、环境配置 ip(/etc/sysconfig/network-scripts) # 网卡1 DEVICEeht0 TYPEEthernet ONBOOTyes NM_CONTROLLEDyes BOOTPROTOstatic IPADDR192.168.59.11 GATEWAY192.168.59.1 NETMASK 255.255.255.0 # 网卡2 DEVICEeht0 TYPEEthernet ONBOOTyes NM_CONTROLLEDyes BOOTPROTOdh…

【React1】React概述、基本使用、脚手架、JSX、组件

文章目录 1. React基础1.1 React 概述1.1.1 什么是React1.1.2 React 的特点声明式基于组件学习一次,随处使用1.2 React 的基本使用1.2.1 React的安装1.2.2 React的使用1.2.3 React常用方法说明React.createElement()ReactDOM.render()1.3 React 脚手架的使用1.3.1 React 脚手架…

基于tkinter的学生信息管理系统之登录界面和主界面菜单设计

目录 一、tkinter的介绍 二、登陆界面的设计 1、登陆界面完整代码 2、部分代码讲解 3、登录的数据模型设计 4、效果展示 三、学生主界面菜单设计 1、学生主界面菜单设计完整代码 2、 部分代码讲解 3、效果展示 四、数据库的模型设计 欢迎大家进来学习和支持&#xff01…

从食堂采购系统源码到成品:打造供应链采购管理平台实战详解

本篇文章&#xff0c;笔者将详细介绍如何从食堂采购系统的源码开始&#xff0c;逐步打造一个完备的供应链采购管理平台&#xff0c;帮助企业实现采购流程的智能化和高效化。 一、需求分析与规划 一般来说&#xff0c;食堂采购系统需要具备以下基本功能&#xff1a; 1.供应商…

第15周 Zookeeper分布式锁与变种多级缓存

1. Zookeeper介绍 1.1 介绍 1.2 应用场景简介 1.3 zookeeper工作原理 1.4 zookeeper特点

AI的欺骗游戏:揭示多模态大型语言模型的易受骗性

人工智能咨询培训老师叶梓 转载标明出处 多模态大型语言模型&#xff08;MLLMs&#xff09;在处理包含欺骗性信息的提示时容易生成幻觉式响应。尤其是在生成长响应时&#xff0c;仍然是一个未被充分研究的问题。来自 Apple 公司的研究团队提出了MAD-Bench&#xff0c;一个包含8…

DLMS/COSEM中公开密钥算法的使用_椭圆曲线加密法

1.概述 椭圆曲线密码涉及有限域上的椭圆曲线上的算术运算。椭圆曲线可以定义在任何数字域上(实数、整数、复数)&#xff0c;但在密码学中&#xff0c;椭圆曲线最常用于有限素数域。 素数域上的椭圆曲线由一组实数(x, y)组成&#xff0c;满足以下等式: 方程的所有解的集合构成…

内网漏扫工具fscan

一、介绍&#xff1a; fscan是一款内网综合扫描工具&#xff0c;方便一键自动化、全方位漏扫扫描。支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。 …

Pytorch使用教学8-张量的科学运算

在介绍完PyTorch中的广播运算后&#xff0c;继续为大家介绍PyTorch的内置数学运算&#xff1a; 首先对内置函数有一个功能印象&#xff0c;知道它的存在&#xff0c;使用时再查具体怎么用其次&#xff0c;我还会介绍PyTorch科学运算的注意事项与一些实用小技巧 1 基本数学运算…

【高中数学/反比例函数/增减区间】从熟悉的y=1/x到陌生的y=x/(1-x)的演变

【题目】 求yx/(1-x)的递增区间&#xff1f; 【解答】 此问题只要能画出yx/(1-x)的大致图像就能解答&#xff0c;首先我们需要将分式化简&#xff1a; yx/(1-x)(x-11)/(1-x)-11/(1-x) 从新的函数式中我们可以判断这也是一个反比例函数&#xff0c;可以从y1/x演变过来。 下…

vue2和el-input无法修改和写入,并且不报错

文章目录 一. 业务场景描述二. 原因分析三.解决方案3.1 方案一 原生标签&#xff08;不建议&#xff09;3.2 方案二 父子传递&#xff08;不建议&#xff09;3.3 方案三 vuex&#xff0c;pinia 状态传值&#xff08;不建议&#xff09;3.4 方案四 vue初始化属性 &#xff08;建…

PyCharm2024 专业版激活设置中文

PyCharm2024 专业版激活设置中文 官网下载最新版&#xff1a;https://www.jetbrains.com/zh-cn/pycharm/download 「hack-jet激活idea家族.zip」链接&#xff1a;https://pan.quark.cn/s/4929a884d8fe 激活步骤&#xff1a; 官网下载安装PyCharm &#xff1b;测试使用的202…

javaEE-01-tomcat

文章目录 javaWebTomcat启动 Tomcat 服务器测试服务器是否成功停止tomcat服务器修改服务器的端口号 Idea整合tomcat服务器 javaWeb 所有通过 Java 语言编写可以通过浏览器访问的程序的总称,是基于请求和响应来开发的。 请求: 客户端给服务器发送数据(Request)响应: 服务器给客…

[极客大挑战 2019]BabySQL1

这是上一个SQL注入的升级版&#xff0c;首先打开靶机 有了上次的经验&#xff0c;我们直接联合查询&#xff1a;?usernameaaaunion select null,null,null#&password1234 看报错信息&#xff0c;null&#xff0c;null&#xff0c;null#有错误&#xff0c;猜测select被过滤…

spring常用注解有哪些

Spring框架使用了大量的注解来简化配置和开发&#xff0c;以下是一些常用的Spring注解&#xff1a; 1.Component&#xff1a;通用的构造型注解&#xff0c;用于标记一个类作为Spring管理的组件&#xff0c;通常用于自定义组件。 2.Autowired&#xff1a;用于自动装配Bean&#…

OCCT使用指南:Foundation Classes

1、介绍 本手册解释了如何使用Open CASCADE Technology (OCCT) Foundation Classes。它提供了关于基础类的基础文档。有关基础类及其应用的高级信息&#xff0c;请参阅我们的电子学习和培训产品。 基础类提供各种通用服务&#xff0c;如自动动态内存管理&#xff08;通过句柄操…

RT-Thread debug 卡死在Stm32_putc问题分析解决

问题和解决方法 找了块开发板玩RT-Thread&#xff0c;一顿骚操作之后&#xff0c;发现debug就卡死在Stm32_putc(不稳定&#xff0c;反复重新上下电&#xff0c;重来有时候卡死有时候不卡死)&#xff0c;卡死情况如下图&#xff1a; 先最后的解决方法&#xff1a;取消调默认的内…