圖的深度優先遍歷非遞歸實現—C++

思路:
利用棧非遞歸實現深度優先遍歷(DFS)圖。先把起始頂點訪問併入棧;然後每次取棧頂元素,找到一個與棧頂頂點連接並且未被訪問的頂點,隨即訪問此頂點,並將此頂點入棧;直到某一頂點沒有出邊(針對有向圖)或者所有連接的頂點都已經被訪問過了,刪除棧頂元素;循環上述步驟,直到棧爲空,深度優先遍歷結束。

注:深度優先遍歷到所有頂點的前提是此圖爲連通圖;若此圖爲兩個連通圖組成的圖,則需要兩次深度優先遍歷,每次都取其中一個連通圖任一點作爲起始頂點。

代碼:

#include <iostream>
#include<vector>
#include<queue>
#include<stack>

using namespace std;

typedef int T;                    //頂點的值類型 int, char, double and so on
struct Node
{
    T value;                      //頂點值
    int numbers;                  //頂點編號
    bool operator==(const Node &other)
    {
        if((this->numbers==other.numbers)&&(this->value==other.value))
            return true;
        else
            return false;
    }
    Node(int a1=0,int a2=0)
    {
        numbers=a1;
        value=a2;
    }
};

struct Edge
{
    int num1;                     //起始頂點
    int num2;                     //終止頂點
    int weight;                   //邊所對應的權值
};

class Graph
{
private:
    int vertex_nums;               //頂點數
    int edge_nums;                 //邊數
    vector<Node> vertex;           //頂點表,強制設爲編號從0開始
    vector<Edge> edge;             //邊表
    vector<vector<int> > edge_maze;    //鄰接矩陣,存儲各個頂點連接關係
public:
    Graph(int n1=10,int n2=10)
    {
        vertex_nums=n1;
        edge_nums=n2;
        for(int i=0;i<vertex_nums;i++)
        {
            Node a;
            a.numbers=i;
            a.value=0;
            vertex.push_back(a);
        }

        for(int i=0;i<vertex_nums;i++)    //鄰接矩陣初始化
        {
            vector<int> temp(vertex_nums,0);
            edge_maze.push_back(temp);
        }

        cout<<"please input the edges about the graph: vertex_number1 vertex_number2 weight"<<endl;
        int x,y,z;
        for(int i=0;i<edge_nums;i++)
        {
            cin>>x>>y>>z;
            Edge temp_edge;
            temp_edge.num1=x;
            temp_edge.num2=y;
            temp_edge.weight=z;
            edge.push_back(temp_edge);
            edge_maze[x][y]=1;
            edge_maze[y][x]=1;
        }
    }

    void print_edge_maze()
    {
        cout<<endl;
        cout<<"輸出鄰接矩陣"<<endl;
        cout<<"   ";
        for(int i=0;i<vertex_nums;i++)
            cout<<"v"<<i<<" ";
        cout<<endl;

        for(int i=0;i<vertex_nums;i++)
        {
            cout<<"v"<<i<<"  ";
            for(int j=0;j<vertex_nums;j++)
            {
                cout<<edge_maze[i][j]<<"  ";
            }
            cout<<endl;
        }
    }

    void print_edge_vec()
    {
        cout<<endl;
        cout<<"輸出邊表:"<<endl;
        cout<<"起始頂點-->結束頂點  邊權值"<<endl;
        for(int i=0;i<edge_nums;i++)
        {
            cout<<"   v"<<edge[i].num1<<"   -->"<<"   v"<<edge[i].num2<<"        "<<edge[i].weight<<endl;
        }
    }

    //基於DFS非遞歸遍歷圖
    void DFS_Graph_noniterator(int start_vertex_num=0)
    {
        vector<int> if_output(vertex_nums,0);     //指示頂點是否被遍歷
        Node first(start_vertex_num);
        stack<Node> s;

        cout<<endl;
        cout<<"遍歷頂點路徑如下"<<endl;
        cout<<"v"<<first.numbers<<"---->";
        if_output[start_vertex_num]=1;            //標記已被訪問
        s.push(first);

        while(!s.empty())
        {
            Node temp=s.top();
            int i;
            for(i=0;i<edge_nums;i++)
            {
                if((edge[i].num1==temp.numbers)&&(if_output[edge[i].num2]==0))
                {
                    cout<<"v"<<edge[i].num2<<"---->";
                    if_output[edge[i].num2]=1;            //標記已被訪問
                    Node push_node(edge[i].num2);
                    s.push(push_node);
                    break;
                }
                else if((edge[i].num2==temp.numbers)&&(if_output[edge[i].num1]==0))
                {
                    cout<<"v"<<edge[i].num1<<"---->";
                    if_output[edge[i].num1]=1;            //標記已被訪問
                    Node push_node(edge[i].num1);
                    s.push(push_node);
                    break;
                }
                else
                    continue;
            }
            if(i==edge_nums)
                s.pop();
        }
        cout<<"end"<<endl;
    }


    //基於BFS非遞歸遍歷圖
    void BFS_Graph_nonrecursive(int start_vertex_num=0)
    {
        vector<int> if_output(vertex_nums,0);     //指示頂點是否被遍歷
        Node first(start_vertex_num);
        queue<Node> qu;
        qu.push(first);
        if_output[start_vertex_num]=1;            //入隊即表示即將被遍歷
        cout<<endl;
        cout<<"遍歷頂點路徑如下"<<endl;
        while(!qu.empty())
        {
            Node temp=qu.front();
            qu.pop();
            cout<<"v"<<temp.numbers<<"---->";

            //遍歷所有邊,找到與隊列頭結點連接的頂點,將所有與頭頂點連接的頂點加入隊列
            for(int i=0;i<edge_nums;i++)
            {
                if(edge[i].num1==temp.numbers)
                {
                    if(if_output[edge[i].num2]==0)           //未被遍歷
                    {
                        Node temp_node(edge[i].num2);        //將連接點加入隊列
                        qu.push(temp_node);
                        if_output[edge[i].num2]=1;           //入隊即表示即將被遍歷
                    }
                }
                else if(edge[i].num2==temp.numbers)
                {
                    if(if_output[edge[i].num1]==0)           //未被遍歷
                    {
                        Node temp_node(edge[i].num1);        //將連接點加入隊列
                        qu.push(temp_node);
                        if_output[edge[i].num1]=1;
                    }
                }
                else
                    continue;
            }
        }
        cout<<"end"<<endl;
        cout<<"遍歷結束"<<endl;

    }
};

int main()
{
    Graph graph(8,10);
    graph.print_edge_vec();
    graph.print_edge_maze();
    //graph.BFS_Graph_nonrecursive();
    graph.DFS_Graph_noniterator();
    return 0;
}

輸出:

please input the edges about the graph: vertex_number1 vertex_number2 weight
0 1 0
1 2 1
2 3 2
3 4 3
4 5 4
5 6 5
6 7 6
7 3 7
7 4 8
6 4 9

輸出邊表:
起始頂點-->結束頂點  邊權值
   v0   -->   v1        0
   v1   -->   v2        1
   v2   -->   v3        2
   v3   -->   v4        3
   v4   -->   v5        4
   v5   -->   v6        5
   v6   -->   v7        6
   v7   -->   v3        7
   v7   -->   v4        8
   v6   -->   v4        9

輸出鄰接矩陣
   v0 v1 v2 v3 v4 v5 v6 v7
v0  0  1  0  0  0  0  0  0
v1  1  0  1  0  0  0  0  0
v2  0  1  0  1  0  0  0  0
v3  0  0  1  0  1  0  0  1
v4  0  0  0  1  0  1  1  1
v5  0  0  0  0  1  0  1  0
v6  0  0  0  0  1  1  0  1
v7  0  0  0  1  1  0  1  0

遍歷頂點路徑如下
v0---->v1---->v2---->v3---->v4---->v5---->v6---->v7---->end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章