考研复试系列——第十二节 后缀表达式&约瑟夫环
前言
后缀表达式是一个经常被提及的话题,出题的频率很高,在学习数据结构,算法以及编译原理中,后缀表达式都曾经出现。写后缀表达式的程序
关键是搞懂算法的过程,然后就比较简单了。约瑟夫问题在数据结构的链表中出现过,这个比较简单,知道方法就OK了。
后缀表达式
后缀表达式的算法讲解太多了而且人家写的太好,自认为不及就不再造轮子了,这里给出我的实现代码:
#include<iostream> #include<string> #include<vector> #include<stack> using namespace std; int priority(char ch)//定义优先级 { switch(ch) { case '(': return 0; case '+': case '-': return 1; case '*': case '/': return 2; default: return -1; } } void convert(string str) { stack<char> mstack; vector<char> mvec; int i = 0; int length = str.length(); while(i < length)//用i标记扫描的字符 { if(isdigit(str[i]) || str[i] == '.')//对于数字和小数点直接进入输出队列 mvec.push_back(str[i]); else if(mstack.empty())//如果栈为空,将符号直接加入栈 mstack.push(str[i]); else if(str[i] == '(')//对于左括号直接入栈 mstack.push(str[i]); else if(str[i] == ')')//对于右括号则依次出栈到输出队列直到左括号 { while(mstack.top() != '(') { mvec.push_back(mstack.top()); mstack.pop(); } mstack.pop();//弹出左括号 } else if(priority(str[i]) > priority(mstack.top()))//如果栈顶符号优先级小于输入符号优先级 mstack.push(str[i]);//直接将输入符号入栈 else//如果栈顶符号优先级大于等于输入符号优先级 { while(!mstack.empty() && priority(mstack.top()) >= priority(str[i]))//依次出栈到输出队列,注意栈判空,调试了半天才发现这个错误 { mvec.push_back(mstack.top()); mstack.pop(); } mstack.push(str[i]);//将输入符号入栈 } i++; } while(!mstack.empty())//最后将栈中所有元素依次入输出队列 { mvec.push_back(mstack.top()); mstack.pop(); } for(i=0;i<mvec.size();i++)//输出结果 cout<<mvec[i]; cout<<endl; } int main() { string str; while(cin>>str) { convert(str); } return 0; }
约瑟夫环
问题描述:n个人(编号1~n),从1开始报数,报到m的退出,剩下的人继续从1开始报数,以此类推。求胜利者的编号。前面说过约瑟夫环是我们在学习数据结构的循环链表
时引入到,所以我们先考虑使用循环链表解决。
#include<iostream> using namespace std; typedef struct Node { int num;//编号 Node *next;//指向下一个 }ListNode,*List; int main() { int n,m;//n个人,报数为m cin>>n>>m; List pHead = new ListNode();//初始化 pHead->num = 1; pHead->next = NULL; ListNode *pCurrentNode = pHead;//当前节点为头结点 int i; for(i=2;i<=n;i++) { ListNode *newNode = new ListNode(); newNode->num = i; newNode->next = NULL; pCurrentNode->next = newNode; pCurrentNode = newNode; } pCurrentNode->next = pHead;//构成循环链表 ListNode *pLastNode = pCurrentNode;//为了实现删除操作 pCurrentNode = pHead;//pCurrentNode指向头结点 while(pCurrentNode->next != pCurrentNode)//如果不是只剩一个节点 { for(i=1;i<m;i++) { pLastNode = pCurrentNode; pCurrentNode = pCurrentNode->next; } //删除报数为m的节点 pLastNode->next = pCurrentNode->next; delete pCurrentNode; pCurrentNode = pLastNode->next; } int result = pCurrentNode->num; delete pCurrentNode; cout<<result<<endl; return 0; }
关于约瑟夫环还可以得出递推公式,进而直接使用数学方法解决。而且如果能够从递推公式得出通项公式,那求解就更加方便了,就是一个带入参数求函数值的问题了。
比如我们熟悉的斐波那契数列,就可以得出通项公式,直接求解。感兴趣的同学可以去参照组合数学。这里只需要掌握一种方法就足以应对机试了。