考研複試系列——第十二節 後綴表達式&約瑟夫環

考研複試系列——第十二節 後綴表達式&約瑟夫環

前言 


後綴表達式是一個經常被提及的話題,出題的頻率很高,在學習數據結構,算法以及編譯原理中,後綴表達式都曾經出現。寫後綴表達式的程序
關鍵是搞懂算法的過程,然後就比較簡單了。約瑟夫問題在數據結構的鏈表中出現過,這個比較簡單,知道方法就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;
}

關於約瑟夫環還可以得出遞推公式,進而直接使用數學方法解決。而且如果能夠從遞推公式得出通項公式,那求解就更加方便了,就是一個帶入參數求函數值的問題了。
比如我們熟悉的斐波那契數列,就可以得出通項公式,直接求解。感興趣的同學可以去參照組合數學。這裏只需要掌握一種方法就足以應對機試了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章