圖的表示方法主要有鄰接矩陣和鄰接表。其中鄰接表最爲經常使用,所以這裏便以鄰接表爲例介紹一下圖的建立及遍歷方法。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說明圖片中的樹)