您的位置:首页 > 其它

考研复试系列——第十二节 后缀表达式&约瑟夫环

2017-03-14 09:07 344 查看

考研复试系列——第十二节 后缀表达式&约瑟夫环

前言 

后缀表达式是一个经常被提及的话题,出题的频率很高,在学习数据结构,算法以及编译原理中,后缀表达式都曾经出现。写后缀表达式的程序
关键是搞懂算法的过程,然后就比较简单了。约瑟夫问题在数据结构的链表中出现过,这个比较简单,知道方法就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;
}


关于约瑟夫环还可以得出递推公式,进而直接使用数学方法解决。而且如果能够从递推公式得出通项公式,那求解就更加方便了,就是一个带入参数求函数值的问题了。
比如我们熟悉的斐波那契数列,就可以得出通项公式,直接求解。感兴趣的同学可以去参照组合数学。这里只需要掌握一种方法就足以应对机试了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息