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

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

前言 


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

关于约瑟夫环还可以得出递推公式,进而直接使用数学方法解决。而且如果能够从递推公式得出通项公式,那求解就更加方便了,就是一个带入参数求函数值的问题了。
比如我们熟悉的斐波那契数列,就可以得出通项公式,直接求解。感兴趣的同学可以去参照组合数学。这里只需要掌握一种方法就足以应对机试了。



猜你喜欢

转载自blog.csdn.net/cassiepython/article/details/61912691