1. 程式人生 > >圖——基本的圖演算法(二)圖的遍歷

圖——基本的圖演算法(二)圖的遍歷

圖——基本的圖演算法(二)圖的遍歷

1. 基本概念

圖的遍歷指的是從圖中的某個頂點出發訪問圖中其餘的頂點,且每個頂點只被訪問一次的這個過程。通常來說,圖的遍歷次序有兩種:深度優先遍歷(Depth first Search, DFS)廣度優先遍歷(Breadth First Search, BFS)。下面就分別來進行介紹。

2. 深度優先遍歷

2.1 總體思想

深度優先遍歷,也叫深度優先搜尋,其基本思想是從圖中的某個頂點V出發,訪問這個頂點,然後從V的未被訪問的鄰接點出發繼續對圖進行深度優先遍歷,直至圖中所有和V有路徑相通的頂點都被訪問。需要注意的是,對於非連通圖,需要對它的分聯通分量分別進行深度優先搜尋,也就是說在從某個頂點出發進行了深度優先搜尋後,如果圖中還存在尚未被訪問的頂點,就要選取其中一個還沒被訪問的頂點作為起點來進行深度優先搜尋遍歷。

2.2 具體實現

(1)圖採用鄰接連結串列來表示

#define Maximum 1000
map<int, int>visited;

typedef struct EdgeListNode{
    int adjId;
    int weight;
    EdgeListNode* next;
};

typedef struct VertexListNode{
    int data;
    EdgeListNode* firstadj;
};

typedef struct GraphAdjList{
    int vertexnumber;
    int edgenumber;
    VertexListNode vertextlist[Maximum];
};

void DFS(GraphAdjList g, int node) {
    cout<<node<<"  "<<g.vertextlist[node].data<<endl;
    int i;
    EdgeListNode* j = g.vertextlist[node].firstadj;
    while(j!=NULL) {
        if(visited.count(j->adjId) == 0) {
            visited[j->adjId] = 1;
            DFS(g, j->adjId);
        }
        j = j->next;
    }
}

void DFS_VISIT(GraphAdjList g) {
    visited.clear();
    int i;
    //對每個連通分量分別進行DFS
    for(i=0; i<g.vertexnumber; i++) {
        if(visited.count(i) == 0) {
            visited[i] = 1;
            DFS(g, i);
        }
    }
}

(2)圖採用矩陣來表示

#define Maximum 1000
typedef int VexType;
typedef int MatrixType;

map<int, int>visited;

typedef struct GraphAdjMatrix {
    VexType vertexlist[Maximum];
    MatrixType matrix[Maximum][Maximum];
    int vertexnumber;
    int edgenumber;
};

void DFS(GraphAdjMatrix g, int node) {
    cout<<node<<"  "<<g.vertexlist[node];
    int i;
    for(i=1; i<=g.vertexnumber; i++) {
        if(g.matrix[node][i] && visited.count(i)==0) {
            visited[i] = 1;
            DFS(g, i);
        }
    }
}

void DFS_VISIT(GraphAdjMatrix g) {
    int i;
    visited.clear();
    for(i=1; i<=g.vertexnumber; i++) {
        if(visited.count(i) == 0) {
            visited[i] = 1;
            DFS(g, i);
        }
    }
    
}

(3)綜合分析
一個有v個頂點和e條邊的圖,如果用鄰接連結串列表示,那麼查詢每個頂點的鄰接點所需的時間取決於頂點數和邊數,因此時間複雜度為O(v+e);如果用鄰接矩陣來表示,那麼查詢每個頂點的鄰接點需要訪問據正在的所有元素,因此時間複雜度為O(n^2)。

3. 廣度優先搜尋

3.1 總體思想

廣度優先搜尋的基本思想是,給定圖中的一個頂點V,訪問它,並把它丟進一個佇列裡,然後依此訪問與它相鄰且還未被訪問過的頂點,並扔入佇列裡,當所有相鄰的點都訪問完了,就將頂點V出列;然後取出佇列最前邊的頂點,重複上述操作,直至所有頂點被訪問完。

3.2 具體實現

(1)圖採用鄰接連結串列來表示

#define Maximum 1000

typedef struct EdgeListNode{
    int adjId;
    int weight;
    EdgeListNode* next;
};

typedef struct VertexListNode{
    int data;
    EdgeListNode* firstadj;
};

typedef struct GraphAdjList{
    int vertexnumber;
    int edgenumber;
    VertexListNode vertextlist[Maximum];
};

void BFS(GraphAdjList g) {
    queue<int>q;
    map<int, int>visited;

    visited.clear();
    while(!q.empty()) {
        q.pop();
    }

    int temp, i;
    EdgeListNode *j;


    for(i=1; i<=g.vertexnumber; i++) {
        if(visited.count(i) == 0) {
            q.push(i);
            visited[i] = 1;
            while(q.empty()==0) {
                temp = q.front();
                q.pop();
                cout<<temp<<"  "<<g.vertextlist[temp].data<<endl;
                j = g.vertextlist[temp].firstadj;
                while(j != NULL) {
                    if(visited.count(j->adjId) == 0) {
                        visited[j->adjId] = 1;
                        q.push(j->adjId);
                    }
                    j = j->next;
                }
            }
        }
    }
}

(2)圖採用鄰接矩陣來表示

#define Maximum 1000
typedef int VexType;
typedef int MatrixType;

typedef struct GraphAdjMatrix {
    VexType vertexlist[Maximum];
    MatrixType matrix[Maximum][Maximum];
    int vertexnumber;
    int edgenumber;
};

void BFS(GraphAdjMatrix g) {
    map<int, int>visited;
    queue<int>q;

    visited.clear();
    while(!q.empty()) {
        q.pop();
    }

    int i, j, temp;
    for(i=1; i<=g.vertexnumber; i++) {
        if(visited.count(i) == 0) {
            visited[i] = 1;
            q.push(i);
            while(q.empty() == 0) {
                temp = q.front();
                q.pop();
                cout<<temp<<"  "<<g.vertexlist[temp]<<endl;
                for(j=1; j<=g.vertexnumber; j++) {
                    if(g.matrix[i][j] && visited.count(j)==0) {
                        visited[j] = 1;
                        q.push(j);
                    }
                }
            }
        }
    }
}