1. 程式人生 > >遞迴解決全排列問題+詳細圖解遞迴執行

遞迴解決全排列問題+詳細圖解遞迴執行

問題描述:字串的排列

//輸入一個字串, 按字典序打印出該字串中字元的所有排列。
//例如輸入字串abc, 則打印出由字元a, b, c所能排列出來的所有字串abc, acb, bac, bca, cab和cba。
//結果請按字母順序輸出。
//長度不超過9(可能有字元重複), 字元只包括大小寫字母。

分析:

採用分治法,把一個字串看成兩部分:第一部分是它的第一個字元,第二部分是後面的所有字元。

(1)首先求所有可能出現在第一個位置的字元,也就是把第一個字元和後面的所有字元交換;


(2)把後面的字串看成一個新的字串,重複上面步驟。

程式碼:

void PermutationLocal(string str, vector<string>& ret, int index)
{
	if (index == str.length()-1)  //一次遞迴結束條件
	{
		ret.push_back(str);
	}

	else
	{
		for (size_t i = index; i < str.length(); ++i)
		{
			if(i != index && str[i] == str[index])
			{
				continue;
			}

			//std:swap(str[i], str[index]);     //交換
			char tmp = str[i];
			str[i] = str[index];
			str[index] = tmp;

			PermutationLocal(str, ret, index + 1);
		}
	}
}
vector<string> Permutation(string str) 
{
	vector<string> ret;
	int index = 0;
	if (!str.empty())
	{
		PermutationLocal(str, ret, index);
	}
	return ret;
}

測試:

void main()
{
	vector<string> v;
	v = Permutation("abc");

	for(auto i : v)
		cout << i.c_str() << endl;
}

遞迴詳解(除錯圖解):

(1)遞迴初始化:

(2)第一次PermutationLocal:

(3)第二次PermutationLocal:

如上圖,index = 2,本次遞迴將要結束,

ret插入了值。

(4)隨後本次遞迴被丟擲棧,直接跳轉到上次遞迴的“”斷點“”,開始繼續執行。其實我覺得理解遞迴,重點、關鍵是要理解“函式棧”、“儲存函式斷點”、“返回函式斷點”!


後面步驟不再截圖贅述,請自行除錯、觀察資料變化、堆疊變化、執行流程。