----------------2023.8.24---------------
1.汉诺塔问题
1.1 问题分析
汉诺塔问题大意,有三个圆柱,在第一个圆柱上套着n个圆环,圆环从下到上直径变小,现在需要将第一个圆柱上的n个圆环移动到第三个圆柱上,移动过程中有三条规则:每次只能动一个圆环;圆环可以在三个柱任意一个;任何时刻,直径较大的圆环都必须在直径较小圆环的下方。
下面对题目进行分析,我们对问题反过来考虑,例如有三个圆环,直径分别为1、2、3,移动到目标位置,最下层一定是最大的圆环,也就是大圈环一定是最先进目标位置的,再明确一个点,大圆环移动到目标位置时,另外两个圆环一定是在第二根柱子上,并且排列正确,这样才能保证大圆环能顺利移动到目标柱。
为了分析清楚,我们给三个柱子分别叫做初始柱,辅助柱,目标柱,分别用ABC柱来代替,在上一步中,我们明确了两点:1.一定要将最大的圆环先移动到c柱。2.第一点的前提,是其他所有的圆环都在b柱上。
有了以上基础,我们就可以对b柱上的两个圆环进行相同的思维考虑,如何将b柱上两个圆环移动到目标柱c上,第一步,肯定是直径为2的圆环先移动到c柱。第二部,其他所有的圆环不能压着这个直径为2的圆环,必须在另一个柱子,也就是a柱上。
通过以上两部的总结,我们大致有了一个模糊的思路:要想移动最大的圆环,必须让他上面的其他圆环在辅助柱上,这样才能移动,而要让其他圆环在辅助柱上,又需要递归这个思想,行成套娃。
1.2 代码实现
//将a塔上的圆环移动到目标塔c,用b来当辅助塔
void Hanoi(int n,char A,char B,char C){
if(n==1) move(A,1,C);//将编号为1的圆环从A移动到C
else{
Hanoi(n-1,A,C,B);//将最大圆环上的所有圆环移动到B上,此时C为辅助塔
move(A,n,C);//将刚才最大的圆环n移动到目标塔C
Hanoi(n-1,B,A,C);//把1-n-1的圆环移动到C,A做辅助塔
}
}
int m = 0; //搬动次数
void move(char A,int n,char C){
cout<<++m<<","<<n<<","<<A<<","<<C<<endl;//移动次数,移动编号,移动位置
}
2.数制的转换
将一个十进制整数转化为二进制数,在计算过程中,将数字模2,将得到的结果压入栈中,再将数字除2,继续上述操作,当n为0时,将栈中的数字依次弹出即可。
void conversion(int n,){
InitStack(S);
while(n){
Push(S,n%2);
n = n/2;
}
while(!StackEmpty(S)){
Pop(S,e);
cout<<e;
}
}
3.括号匹配的检验
当我们遇到左括号时,我们压入与左括号相匹配的右括号入栈,当遇到右括号时,弹出栈顶元素,如果与当前右括号不同,则直接匹配失败,如果遍历完所有括号而栈不为空,则匹配失败,如果有 括号没有匹配而栈为空,则匹配失败;否则则匹配成功。
bool Matching(char *s){
int n = strlen(s);
char stack[n+1];
int top = 0;
for(int i = 0;i<n;i++){
if(s[i] == '{') char[top++] = '}';
if(s[i] == '[') char[top++] = ']';
if(s[i] == '(') char[top++] = ')';
char topElem = char[--top];
if(!char[top]) return false;
else if(s[i] != topElem) return false;
}
return top==0;
}
4.中缀表达式转后缀表达式
在中->后这个过程中,通过手动模拟,我们可以发现各个数字的相对顺序是不变的,我们首先对运算符进行一个等级划分,括号优先级最高,乘除次之,加减最低。
按照AB-(C+D)/E这个例子进行分析,首先我们依次进行遍历,A,不做处理,,压入栈中,下一个B,不做处理,下一个-,这时栈中已经有一个运算符*,且乘除的优先级更高,所以将弹出,减号压入栈,遇到左括号,直接压入栈中,下一个C不做处理,加法压入栈中,D不做处理,当遇到右括号时,已经可以确定括号中的操作顺序了,按照优先级处理,此时只有一个加法运算,于是弹出+,此时表达式已经为ABCD+,继续进行处理,除号压入栈中,E不做处理,此时已经遍历完成,弹出栈内元素即可。