1. 程式人生 > >C++ STL練習(2)

C++ STL練習(2)

題目1:反片語

思路:

由於有了上篇部落格題目中的經驗,遇到不區分大小寫,那就在判斷時用臨時變數儲存呼叫tolower()函式轉變成小寫形式的字串

1.可以寫一個函式對每個單詞標準化:全部轉化為小寫字母,然後再對字母排序

2.用map統計標準化每個單詞出現的次數,標準化之後題目中能通過字母重排的單詞相同

3.儲存單詞出現次數為1的原單詞

4.對儲存的單詞進行字典排序,然後打印出來

程式碼實現:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;
//定義關聯陣列map用於統計每個單詞出現的次數
map<string,int> timesOfWord;
//定義一個可變陣列用於儲存原單詞
vector<string> words;
//標準化每個單詞
	/*   注意:這個函式的定義不能直接返回引用,因為題目要求最終輸出要保留輸入中的大小寫
	void standardizeWord(string &word)
	 */
//所以我們可以傳入引用,在函式內部進行拷貝,然後返回拷貝的string物件
string standardizeWord(const string &word)
{
	//定義變數儲存標準化的單詞
	string standardWord = word;
	//遍歷單詞的每個字元,將每個字元轉換成小寫
	for(unsigned int i=0;i < word.length();i++)
	{
		tolower(standardWord[i]);
	}
	//對單詞內的字元進行排序
	sort(standardWord.begin(),standardWord.end());
	return standardWord;
}

int main() {
	//定義一個變數用於儲存使用者輸入的單詞    注意:這道題目要求使用者輸入的是單詞,所以除過結束字元'#'和字母字元沒有其他字元
	string inputText;
	//執行一次迴圈cin每次讀取多少字元?用什麼標識來決定?
	//迴圈結束的標誌:EOF   Unix和Linux:ctrl+D   windows:ctrl+Z和Enter
	//迴圈讀取使用者輸入的單詞
	while(cin >> inputText)
	{
		//遇到使用者輸入的結束符‘#’就結束迴圈
		if(inputText[0] == '#')
			break;
		//將單詞儲存在vector當中,用於最後進行輸出
		words.push_back(inputText);
		//將接受到的單詞進行標準化
		string standardWord = standardizeWord(inputText);
		//這裡的判斷是必要的,因為我們會在下面直接通過索引訪問map,但是我們訪問時必須保證我們所訪問的鍵存在
		if(!timesOfWord.count(standardWord))
			timesOfWord[standardWord] = 0;
		//讓標準化後的字串統計數+1
		timesOfWord[standardWord]++;
	}
	//定義儲存要輸出單詞的陣列
	vector<string> savePrintStr;
	//將統計次數為1的字串儲存到savePrintStr
	for(unsigned int i=0;i < words.size();i++)
	{
		if(timesOfWord[standardizeWord(words[i])]==1)
		{
			savePrintStr.push_back(words[i]);
		}
	}
	//對要輸出的字串排序
	sort(savePrintStr.begin(),savePrintStr.end());
	//列印結果
	for(vector<string>::iterator it =savePrintStr.begin();it!=savePrintStr.end();it++)
		cout<<*it<<endl;
	return 0;
}

eclipse下執行結果:

知識點詳細用法補充:(待補充)

while(cin >> inputText)中執行一次迴圈cin每次讀取多少字元?用什麼標識來決定?
 

 

題目2:集合棧計算機(後續補充)

思路:

 

程式碼實現:

 

eclipse下執行結果:

 

知識點詳細用法補充:

 

題目3:團體佇列

思路:本題沒有使用書中原來的思路,通過參考作者思路和自己思考,使用了類似作業系統當中多級頁表的原理

1. 定義兩種佇列:團隊內部佇列陣列(這個陣列可以使用關聯陣列,鍵:團隊編號,值:團隊佇列),團隊編號佇列
2.入隊:
        我們先判斷該團隊佇列編號是否在團隊編號佇列中,
        如果在,我們對應到團隊佇列陣列中可以用O(1)的時間複雜度找到對應團隊編號的佇列,將它插入到其中
         如果不在,我們將該團隊編號入團隊編號佇列,同時新建該團隊佇列所對應的關聯陣列,將該編號入隊

3.出隊:
        我們直接到團隊編號佇列的隊首元素,然後對應到map中相應的佇列的隊首元素出隊,
        同時判斷出隊後,佇列是否為空,如果為空,釋放該map元素的記憶體

程式碼實現:

#include <iostream>
#include <queue>
#include <map>
using namespace std;

//函式宣告
void q_enqueue();
void q_dequeue();
//這裡使用vector可以嗎?這樣就可以不把陣列長度寫死,使用vector,array和內建陣列有什麼區別
//用於儲存團隊佇列陣列的最大團隊數
const int arrSizeOfTeam=1000;
//儲存每個團隊成員資訊,用鍵值對儲存每個隊員的編號和他所屬隊的編號,鍵:隊員編號(唯一)    值:所屬團隊編號
map<int,int> teamMemInfo;

//團隊編號佇列
queue<int> numQueue;
//團隊佇列陣列
map<int,queue<int>> queueMap;

//****************************************獲取使用者輸入的指令,並執行相應的操作**************************
    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%下列思路類似於多級頁表的原理%%%%%%%%%%%%%%%%%%%%%%%%%%
		//定義兩種佇列:團隊內部佇列陣列(這個陣列可以使用關聯陣列,鍵:團隊編號,值:團隊佇列),團隊編號佇列
		//入隊:
		//我們先判斷該團隊佇列編號是否在團隊編號佇列中,
		//	如果在,我們對應到團隊佇列陣列中可以用O(1)的時間複雜度找到對應團隊編號的佇列,將它插入到其中
		//  如果不在,我們將該團隊編號入團隊編號佇列,同時新建該團隊佇列所對應的關聯陣列,將該編號入隊
		//出隊:
		//我們直接到團隊編號佇列的隊首元素,然後對應到map中相應的佇列的隊首元素出隊,
		//   同時判斷出隊後,佇列是否為空,如果為空,釋放該map元素的記憶體
void q_enqueue()
{
	queue<int> temp;//queue預設初始化時,佇列中有元素嗎?
	//獲取使用者輸入的隊員編號
	int mNum;
	cin>>mNum;
	//獲取使用者所在團隊號
	int tNum= teamMemInfo[mNum];
	//團隊佇列map中是否有該團隊號(鍵)
	if(!queueMap.count(tNum))
	{//沒有該鍵的話,我們動態申請新建一個佇列
		//queueMap[tNum] = new queue<int>();
		queueMap[tNum] = temp;
		numQueue.push(tNum);
	}
	queueMap[tNum].push(mNum);
}
void q_dequeue()
{
	//獲取佇列編號的隊頭編號
	int numDequeue = numQueue.front();
	//列印要出隊的隊員
	cout<<queueMap[numDequeue].front()<<endl;
	//找到隊頭編號佇列,執行出棧
	queueMap[numDequeue].pop();
	//判斷該對列是否為空,為空的話釋放記憶體
	if(queueMap[numDequeue].empty())   //c++中map怎麼刪除元素,釋放記憶體呢?
	{
		//將編號隊列出隊
		numQueue.pop();
		//delete queueMap[numDequeue];
		//c++中map怎麼刪除元素,釋放記憶體呢?

	    for(map<int,queue<int>>::iterator it=queueMap.begin();it != queueMap.end();it++)
	    {
	    	if(it->first == numDequeue)
	    	{
	    		//delete it->second;
	    	    //it->second=NULL;
	    		//怎麼釋放一個queue的記憶體->STL容器的各種型別是如何釋放記憶體的?
	    		queueMap.erase(it);
	    		break;
	    	}
	    }
	}
}

int main() {
	int scen = 0;//場景模擬的次數
	int teamNum = 0;//團隊的數量

	while((cin>>teamNum)&&teamNum)    //獲取使用者輸入的團隊數量,並且保證團隊數量不為0執行下面的操作才有意義
	{
		//每當執行迴圈的都是一次新的場景模擬,我們按照樣例輸出區分不同場景
		cout<<"Scenario #"<<++scen<<endl;
//****************************************獲取使用者輸入的團隊資訊*****************************
		for(int i=0;i < teamNum;i++)
		{
			//獲取使用者輸入的團隊的成員數量
			int memNum;
			cin>>memNum;

			int tempMem;//用於接受使用者臨時儲存的隊員編號
			//記錄使用者輸入的隊員資訊
			while(memNum--)
			{
				cin>>tempMem;
				teamMemInfo[tempMem]= i;
			}
		}

//判斷使用者輸入的指令,執行相應的操作
		while(true)
		{
			//獲取使用者輸入的指令
			string instruction;
			cin>>instruction;
			//判斷使用者輸入的指令型別
			if(instruction[0] == 'S')//工程中這麼判斷缺乏安全性,在這裡我們假設使用者的輸入都是合法輸入
				break;
			else if(instruction[0] == 'D')
				q_dequeue();
			else if(instruction[0] == 'E')
				q_enqueue();
		}

		cout<<"第"<<scen<<"次模擬結束"<<endl;
	}

	return 0;
}

eclipse下執行結果:

知識點詳細用法補充:

1.STL容器記憶體釋放?

2.map

3.queue

 

題目4:醜數(後續補充)

思路:

 

程式碼實現:

 

eclipse下執行結果:

 

知識點詳細用法補充: