圖的建立和遍歷(BFS/DFS)

     圖的表示方法主要有鄰接矩陣和鄰接表。其中鄰接表最爲經常使用,所以這裏便以鄰接表爲例介紹一下圖的建立及遍歷方法。node

 

     建立圖用到的結構有兩種:頂點及弧ios

struct ArcNode
    {
        int vertexIndex;        //該弧指向的頂點位置
        struct ArcNode* next;    //指向下一個弧
        InfoType info;            //該弧的相關信息,如權重等
    };

    struct Vertex
    {
        VertexType data;    //頂點信息
        ArcNode* firstArc;    //指向第一條依附該節點弧的指針
        ColorType color;    //訪問狀況
    };

  其中ColorType是一個枚舉,遍歷的時候纔會用到。圖的建立比較簡單,直接看代碼很容易理解,這裏再也不詳細說了。 圖的深度和廣度遍歷直接看算法導論中的兩張圖就明白了 :算法

 

//結點顏色表明遍歷狀況
enum ColorType
{
    WHITE,    //未訪問
    GRAY,    //正在訪問,鄰接點還沒訪問完
    BLACK    //訪問完畢
};

 

 
代碼:
  1 #include <queue>
  2 #include <stack>
  3 #include <iostream>
  4 using namespace std;
  5 
  6 
  7 enum GraphType
  8 {    
  9     UNDIR_UNWEIGHT_GRAPH,        //無向無權圖
 10     UNDIR_WEIGHT_GRAPH,            //無向帶權圖
 11     DIR_UNWEIGHT_GRAPH,            //有向無權圖
 12     DIR_WEIGHT_GRAPH            //有向帶權圖    
 13 };
 14 
 15 //結點顏色表明遍歷狀況
 16 enum ColorType
 17 {
 18     WHITE,    //未訪問
 19     GRAY,    //正在訪問,鄰接點還沒訪問完
 20     BLACK    //訪問完畢
 21 };
 22 
 23 template<typename VertexType,typename InfoType>
 24 class Graph
 25 {
 26 public:
 27     Graph(int vertexNum, GraphType type) :m_vertexNum(vertexNum), m_type(type), m_arcNum(0)
 28     {
 29         for (int i = 0; i < MAX_VERTEX_NUM; ++i)
 30         {
 31             m_vertices[i].firstArc = nullptr;
 32         }
 33     }
 34 
 35     void Create()
 36     {
 37         switch (m_type)
 38         {
 39         case UNDIR_UNWEIGHT_GRAPH:
 40             CreateUndirUnweightGraph();
 41             break;
 42         case UNDIR_WEIGHT_GRAPH:
 43             CreateUndirWeightGraph();
 44             break;
 45         case DIR_UNWEIGHT_GRAPH:
 46             CreateDirUnweightGraph();
 47             break;
 48         case DIR_WEIGHT_GRAPH:
 49             CreateDirWeightGraph();
 50             break;
 51         default:
 52             break;
 53         }
 54     }
 55 
 56     //輸出圖的信息
 57     void Display()
 58     {
 59         for (int i = 0; i < m_vertexNum; ++i)
 60         {
 61             cout << "" << i + 1 << "個結點爲" << m_vertices[i].data << " 鄰接表爲:";
 62             ArcNode* node = m_vertices[i].firstArc;
 63             while (node)
 64             {
 65                 cout << "->" << m_vertices[node->vertexIndex].data << "(" << node->info << ")";
 66                 node = node->next;
 67             }
 68             cout << endl;
 69         }
 70     }
 71 
 72     void BFS()
 73     {
 74         for (int i = 0; i < m_vertexNum; ++i)
 75         {
 76             m_vertices[i].color = WHITE;
 77         }
 78         cout << "圖的廣度優先遍歷爲:";
 79         BFS(&m_vertices[0]);
 80         cout << endl;
 81     }
 82 
 83     void DFS()
 84     {
 85         for (int i = 0; i < m_vertexNum; ++i)
 86         {
 87             m_vertices[i].color = WHITE;
 88         }
 89         cout << "圖的深度優先遍歷爲:";
 90         DFS(&m_vertices[0]);
 91         cout << endl;
 92     }
 93 private:
 94     struct ArcNode
 95     {
 96         int vertexIndex;        //該弧指向的頂點位置
 97         struct ArcNode* next;    //指向下一個弧
 98         InfoType info;            //該弧的相關信息,如權重等
 99     };
100 
101     struct Vertex
102     {
103         VertexType data;    //頂點信息
104         ArcNode* firstArc;    //指向第一條依附該節點弧的指針
105         ColorType color;    //訪問狀況
106     };
107 
108     //最大頂點數
109     static const int MAX_VERTEX_NUM = 20;
110     Vertex m_vertices[MAX_VERTEX_NUM];    //頂點列表
111     int m_vertexNum;    //當前頂點數量
112     int m_arcNum;        //當前弧數量
113     GraphType m_type;    //圖類型:有向無權圖、有向帶權圖、無向無權圖、無向無權圖
114 private:
115     //初始化頂點列表
116     void InitVertices()
117     {
118         cout << "請輸入每一個頂點的關鍵字" << endl;
119         VertexType data;
120         for (int i = 0; i < m_vertexNum; ++i)
121         {
122             cin >> data;
123             m_vertices[i].data = data;
124         }
125     }
126     //插入一個表結點
127     void Insert(int headVertex, int tailVertex, InfoType info)
128     {
129         //構造一個鄰接表結點,即建立一條弧
130         ArcNode* newNode = new ArcNode;
131         newNode->info = info;
132         newNode->next = nullptr;
133         newNode->vertexIndex = tailVertex;
134 
135         //找到鄰接表的最後一個節點
136         ArcNode* lastNode = m_vertices[headVertex].firstArc;
137         if (lastNode == nullptr)
138             m_vertices[headVertex].firstArc = newNode;
139         else
140         {
141             while (lastNode->next)
142             {
143                 lastNode = lastNode->next;
144             }
145             lastNode->next = newNode;
146         }
147         ++m_arcNum;
148     }
149 
150     //建立無向無權圖
151     void CreateUndirUnweightGraph()
152     {
153         InitVertices();
154         cout << "請分別輸入每條邊的起始結點:" << endl;
155         int head, tail;
156         while (cin >> head >> tail)
157         {
158             //無向圖head->tail tail->head插入兩次
159             Insert(head, tail, 0);
160             Insert(tail, head, 0);
161         }
162     }
163     //建立無向有權圖
164     void CreateUndirWeightGraph()
165     {
166         InitVertices();
167         cout << "請分別輸入每條邊的起始結點和權值:" << endl;
168         int head, tail;
169         InfoType weight;
170         while (cin >> head >> tail >> weight)
171         {
172             Insert(head, tail, weight);
173             Insert(tail, head, weight);
174         }
175     }
176     //建立有向無權圖
177     void CreateDirUnweightGraph()
178     {
179         InitVertices();
180         cout << "請分別輸入每條邊的起始結點值:" << endl;
181         int head, tail;
182         while (cin >> head >> tail)
183         {
184             Insert(head, tail,0);
185         }
186     }
187     //建立有向帶權圖 
188     void CreateDirWeightGraph()
189     {
190         InitVertices();
191         cout << "請分別輸入每條邊的起始結點和權值:" << endl;
192         int head, tail;
193         InfoType weight;
194         while (cin >> head >> tail >> weight)
195         {
196             Insert(head, tail, weight);
197         }
198     }
199 
200     void BFS(Vertex* vertex)
201     {
202         vertex->color = GRAY;
203         queue<Vertex*> vertices;
204         vertices.push(vertex);
205         while (!vertices.empty())
206         {
207             Vertex* curVertex = vertices.front();
208             vertices.pop();
209             cout << curVertex->data << "->";
210             ArcNode* node = curVertex->firstArc;
211             while (node)
212             {
213                 Vertex* tmpVertex = &m_vertices[node->vertexIndex];
214                 if (tmpVertex->color == WHITE)
215                 {
216                     tmpVertex->color = GRAY;
217                     vertices.push(tmpVertex);
218                 }
219                 node = node->next;
220             }
221             curVertex->color = BLACK;
222         }
223     }
224 
225     void DFS(Vertex* vertex)
226     {
227         vertex->color = GRAY;
228         stack<Vertex*> vertices;
229         vertices.push(vertex);
230         while (!vertices.empty())
231         {
232             Vertex* curVertex = vertices.top();
233             vertices.pop();
234             cout << curVertex->data << "->";
235             ArcNode* node = curVertex->firstArc;
236             while (node)
237             {
238                 Vertex* tmp = &m_vertices[node->vertexIndex];
239                 if (tmp->color == WHITE)
240                 {
241                     tmp->color = GRAY;
242                     vertices.push(tmp);
243                 }
244                 node = node->next;
245             }
246             curVertex->color = BLACK;
247         }                
248     }
249 };
250 
251 int main()
252 {
253     int  vertexNum;
254     cout << "請輸入要建立的圖的結點數:";
255     cin >> vertexNum;
256     Graph<char, int> g(vertexNum,GraphType::UNDIR_UNWEIGHT_GRAPH);
257     g.Create();
258     g.Display();
259     g.BFS();
260     g.DFS();
261 }
 
運行結果:(建立的樹爲算法導論BFS說明圖片中的樹)
相關文章
相關標籤/搜索