DFS將遞歸改為非遞歸這個方法的需求來自於一道三維積木組合的題目,還在苦苦調試中,暫且不提。
普通的認識對於遞歸向非遞歸的轉化無非是使用棧,但是結合到深度搜索如何將棧很好利用,如何很好保存現場,都不是很輕松(自身感覺)。
網上大部分轉化都是基於圖的搜索進行,總是引出鄰接點的概念,讓人越看越迷,畢竟不是每個DFS都是圖(不可否認都可以看成是圖)。
在眾多資料中看到了CSDN上的一個轉化方法很新穎(結構之法,算法之道):http://blog.csdn.net/v_july_v/article/details/6111353。
最后一點結合圖提出了用隊列棧來進行轉化,由於偽代碼和圖有關,而且用到標志什么的,並沒有細看,但是這個思想倒是啟發了我。於是我決定使用這個思想進行轉化嘗試。
全排列問題是一個典型的可利用DFS搜索出結果的題目,正巧我們學校的OJ上有這個題目的評測:http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1005
於是使用隊列棧來進行全排列,核心思想是:
1.使用每一個隊列表示深度搜索的同一層節點。
2.棧的關系表示的是父親和兒子的關系,不同層節點,且底部棧表示父親節點,上層棧表示兒子節點
整個非遞歸DFS過程如下:
1.初始化最底層棧
2.只要棧內還有隊列繼續循環(3-5):
3.將棧頂隊列彈出:
4.判斷棧頂隊列是否為空,若為空,進行恢復現場操作,並且往回回溯,若不為空,將棧頂隊列首元素出棧,為該元素生成下層節點,也為一個隊列,然后將該元素作為已經遍歷的一部分,記錄到結果中。
5.判斷生成的隊列是否為空,為空,說明已經到了搜索最底層,可輸出相應的解,若不為空,將此隊列入棧。
這里有兩個注意點:
1.恢復現場操作有兩處:一處在放置結果的時候,一處為棧頂隊列為空的時候
2.在第四步將棧頂隊列首元素出棧之后,這個隊列有可能為空,在這里不需要對這個隊列進行和第5步類似的操作。因為有可能出現該節點為空,而兒子並不為空的情況。

1 #include<iostream> 2 #include<stack> 3 #include<queue> 4 using namespace std; 5 int n; 6 int ans[12]; 7 int visited[12]={0}; 8 typedef struct point{ 9 int num; 10 }Point; 11 stack< queue<Point> > mainstack; 12 void DFS() 13 { 14 15 int cur=1; 16 queue<Point> oneq; 17 for(int i=1;i<=n;i++) 18 { 19 Point oneP; 20 oneP.num=i; 21 oneq.push(oneP); 22 } 23 mainstack.push(oneq); 24 while(!mainstack.empty()) 25 { 26 queue<Point> twoq; 27 twoq=mainstack.top();mainstack.pop(); 28 if(!twoq.empty()) 29 { 30 Point twoP=twoq.front();twoq.pop(); 31 int onenum=twoP.num; 32 visited[ans[cur]]=0;//1.如果要修改則將當前置為可用 33 ans[cur]=onenum; 34 visited[onenum]=1; 35 queue<Point> threeq;//該節點的子節點 36 for(int i=1;i<=n;i++) 37 { 38 if(visited[i]==0) 39 { 40 Point threep; 41 threep.num=i;//threep.flag=i; 42 threeq.push(threep); 43 } 44 } 45 //在這里直接加空判斷,會出現本節點兄弟為空,兒子不為空的情況 46 mainstack.push(twoq); 47 //沒有可擴展節點 48 if(threeq.empty()) 49 { 50 for(int i=1;i<=n;i++) 51 cout<<ans[i]<<" "; 52 cout<<endl; 53 } 54 else 55 { 56 mainstack.push(threeq); 57 cur++; 58 } 59 } 60 else 61 { 62 visited[ans[cur]]=0; 63 ans[cur]=0;//這里置0才能完全還原 64 cur--; 65 } 66 } 67 } 68 int main() 69 { 70 cin>>n; 71 DFS(); 72 return 0; 73 }
至於到全排序查重的地方,應該還有可以優化的地方,暫且不提,此代碼在XOJ上提交通過。
56 K
|
1072 MS
|
G++
|
Apple
|