1. 程式人生 > 實用技巧 >DFS 深度優先搜尋

DFS 深度優先搜尋



#include "DFS.h"
#include <list>
#include <stack>
using namespace std;

DFS::DFS(int vertexCount) {
    this->v = vertexCount;
    this->adj = new list<int>[v];
}


list<int> DFS::searchByStack(int s, int t){
    //最短路徑結果集
    list<int> resultList;
    //鄰接表訪問標識,為true標識此index的鄰接表已經遍歷過了,不需要重複訪問
    bool started[v];
    //每個頂點到起點可能連線,的前一個頂點(不一定是最短的連線)
    int prev[v];
    stack<int> startVertexStack;

    //初始化全域性變數
    for (int i = 0; i < this->v; ++i) {
        started[i] = false;
        prev[i] = -1;
    }
    startVertexStack.push(s);

    while(!startVertexStack.empty()){
        //這裡先top不pop,是因為還需要進行回溯,如果這個節點的所有相關節點都已經start過了,那麼就可以進行pop了
        int adjStartIndex = startVertexStack.top();

        started[adjStartIndex] = true;
        list<int>::iterator it;
        bool needToPop = true;
        for(it = adj[adjStartIndex].begin(); it != adj[adjStartIndex].end(); it++){

            if (!started[*it]){
                needToPop = false;
                startVertexStack.push(*it);
                prev[*it] = adjStartIndex;
                if (*it == t){

                    int index = t;
                    resultList.push_front(t);
                    while (prev[index] != -1){
                        resultList.push_front(prev[index]);
                        index = prev[index];
                    }
                    return resultList;
                }
                //只要push了一個就立即跳出for迴圈,因為這裡要進行深度搜索,不需要現在就沿著鄰接表去遍歷所有
                break;
            }

        }
        if(needToPop){
            //這裡pop的,其實就是adjStartIndex,因為,只有一次push都沒的情況下才會進這裡
            startVertexStack.pop();
        }
    }
    return resultList;
}





list<int> DFS::search(int s, int t) {
    //最短路徑結果集
    list<int> resultList;
    //鄰接表訪問標識,為true標識此index的鄰接表已經遍歷過了,不需要重複訪問
    bool started[v];
    //每個頂點到起點可能連線,的前一個頂點(不一定是最短的連線)
    int prev[v];

    //初始化全域性變數
    for (int i = 0; i < this->v; ++i) {
        started[i] = false;
        prev[i] = -1;
    }


    cursiveSearch(s, t, &resultList, started, prev);

    return resultList;

}

void DFS::cursiveSearch(int start, int end, list<int> *resultList, bool *started, int *prev){

    started[start] = true;
    list<int> thisRoundAdjList = this->adj[start];
    list<int>::iterator it;

    for(it = thisRoundAdjList.begin(); it != thisRoundAdjList.end(); ++it){
        if(!resultList->empty()){
            return;
        }

        if (!started[*it]){
            if (*it == end){
                //此點是目的地
                prev[end] = start;
                int index = end;
                resultList->push_front(end);
                while (prev[index] != -1){
                    resultList->push_front(prev[index]);
                    index = prev[index];
                }
                return;
            } else {
                //此點不是目的地,以此點為出發點繼續尋找
                prev[*it] = start;
                cursiveSearch(*it, end, resultList, started, prev);
            }
        }
    }
}