樹的追蹤目的是欲拜訪樹的每一節點一次, 可用的方法有中序, 前序與後序等三種. 而圖形追蹤定義如下 :
也就是從某一頂點V1 開始, 走訪可以經由V1 到達的頂點, 接著再走訪下一個頂點直到全部的頂點走訪完畢為止. 在走訪的過程中可能會重複過某些頂點及邊線. 經由圖形的走訪可以判斷圖形是否連通, 並找出連通單元及路徑. 圖形走訪的方法有兩種 : "先深後廣走訪" 及 "先廣後深走訪".
先深後廣法 :
先深後廣走訪的方式有點類似前序走訪. 是從圖形的某一頂點開始走訪, 被拜訪過的頂點就作上已拜訪的記號, 接著走訪此頂點的所有相鄰且未拜訪過的頂點中的任意一個頂點, 並做上已拜訪的記號, 再以該點為新的起點繼續進行先深後廣的搜尋.
這種圖形追蹤方法結合了遞迴與堆疊兩種資料結構的技巧, 由於不小心會造成無窮迴路, 所以必須加上一個變數, 判斷該節點是否已經走訪完畢.
底下我們以下圖來看看這個方法的走訪過程 :
步驟一 : 以頂點1 為起點, 將相鄰的頂點2及頂點5放入堆疊. (頂點1已拜訪)
步驟二 : 取出頂點2, 將頂點2相鄰且未拜訪過的頂點3及頂點4放入堆疊. (頂點1,2 已拜訪)
步驟三 : 取出頂點3, 將與頂點3相鄰且未拜訪過的頂點4 及頂點5放進堆疊. (頂點1,2,3 已拜訪)
步驟四 : 取出頂點4, 將與頂點4相鄰且未拜訪過的頂點5放入堆疊. (頂點1,2,3,4 已拜訪)
步驟五 : 取出頂點5, 將與頂點5相鄰且未拜訪過的頂點放入堆疊, 這裡與頂點5相鄰的頂點已經都拜訪過, 所以無須再放入堆疊. (頂點1,2,3,4,5 已拜訪)
步驟六 : 將堆疊內的值取出並判斷是否已經走訪過, 直到堆疊內無節點可走訪為止. 故先深後廣的走訪順序為 : 頂點1, 頂點2, 頂點3, 頂點4, 頂點5.
範例代碼 :
- #include
- using namespace std;
- class graphicPoint{
- public:
- int val;
- class graphicPoint *next;
- graphicPoint(){
- next = NULL;
- val = -1;
- }
- };
- int run[6] = {0};
- class graphicPoint head[6]; // 共有5個頂點
- void dfs(int current) {
- graphicPoint *ptr;
- run[current] = 1;
- cout << "[" << current << "] ";
- ptr = head[current].next;
- while(ptr!=NULL) {
- if(run[ptr->val]==0)
- dfs(ptr->val);
- ptr = ptr->next;
- }
- }
- void main(bool b) {
- if(b) {
- int data[14][2] = {{1,2}, {2,1}, {1,5}, {5,1}, {2,3}, {3,2}, {2,4}, {4,2}, {3,4}, {4,3}, {3,5}, {5,3}, {4,5}, {5,4}}; //圖形邊線陣列宣告
- for(int i=0; i<14; i++) {
- int tmpi = data[i][0];
- int tmpj = data[i][1];
- graphicPoint *npt = new graphicPoint;
- npt->val = tmpj;
- graphicPoint *pt = &head[tmpi];
- while(pt->next != NULL)
- pt = pt->next;
- pt->next = npt;
- }
- cout << "圖形鄰接串列內容 : " << endl;
- for(int i=1; i<6; i++) {
- graphicPoint *pt = head[i].next;
- cout << "頂點 " << i << "=>";
- while(pt!=NULL) {
- cout << "[" << pt->val << "] ";
- pt = pt->next;
- }
- cout << endl;
- }
- cout << "深度優先走訪頂點 :" << endl;
- for(int i=0; i<6; i++) { // 初始化run 陣列
- run[i] = 0;
- }
- dfs(1); // 以頂點1為起點
- printf("\n");
- }
- }
補充說明 :
* [ 資料結構 小學堂 ] 圖形結構 : 圖形表示法
沒有留言:
張貼留言