栈应用:进制转换
看完你能亲手用栈把除基取余的倒序余数变成正序输出,并写出实现
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
栈应用:进制转换
看完你能亲手用栈把除基取余的倒序余数变成正序输出,并写出实现
回顾:进制与余数
上一页我们知道了栈擅长「后进先出」。那进制转换为什么用得上它?先回忆小学做过的事:把十进制数不断除以 2,记下每一步的余数——但为什么余数要倒着读?
剥下最外层对应最低位,最后剥到的核心才是最高位
为什么需要栈
上一页我们用短除法把 13 转成二进制:依次除 2 取余。可你有没有注意到,最先算出来的余数排在最低位,最后算出的反而排在最高位?产生顺序和输出顺序刚好相反。
后洗好的餐盘放在最上层、先被取走,对应后算出的余数先被输出
算法流程图
从上往下读:循环中每次取余入栈,n 变 0 后进入出栈输出阶段。菱形是判断分支。
用顺序栈实现转换
用 C 实现核心函数 convert:余数依次入栈,再逆序出栈打印,完成进制转换。
convert 中:n%base 的余数依次入栈;n/=base 更新商;栈空后逐个出栈打印,天然实现低位到高位的逆序。
逐行走读代码
逐行走读转换代码,跟踪 1348→2504 过程中栈的每一步变化。
两个循环怎么写
同样是转换算法,while 和 do-while 只差在循环条件判断的时机,n=0 这个边界直接暴露区别。
- 先判断条件,再执行入栈
- n=0 时不进循环,栈为空
- 必须单独处理 n=0,否则输出为空
- 先执行入栈,再判断条件
- n=0 也至少入栈一次余数 0
- 天然覆盖 n=0,无需特判
大于十进制怎么办
前页代码里余数直接当数字打印,转二进制、八进制都没问题。可一旦换成十六进制,余数会出现 10~15——总不能打印「13」冒充一位数,得有办法表示这六种新「数字」。
代码 11 代表北京,同样用编号查表换出真实含义
自测:栈顶是谁
把 n=13 转为二进制:13÷2 余 1,6÷2 余 0,3÷2 余 1,1÷2 余 1。余数依次入栈后,第一个出栈的元素是?
要点收束
- ✓进制转换本质:不断除基取余,逆序输出
- ✓余数产生顺序与输出顺序天然相反,正是栈的形状
- ✓顺序栈把这个'逆序'变成数组下标问题
- ✓边界在余数≥10与n=0,而非算法本身
- ✓'逆序输出需求→栈'是可迁移的识别模式
课后思考
先合上讲义自己想五分钟,再对照下面的参考思路。
参考答案效果等价。数组倒序遍历和栈的弹出都是逆序,栈的价值在于它把这个「后进先出」的动作封装成了固定接口,不必自己维护下标。
参考答案不直接成立。商和余数的定义会变:要保证余数非负,需调整商(如 c = -⌈n / d⌉ 这类修正)。压栈-弹出的框架不变,变的是取余规则。
参考答案凡是处理顺序与产出顺序相反的场景:递归调用的调用栈、括号匹配、函数返回地址、浏览器后退。识别出「逆序需求」,就找到了栈的用武之地。