有向圖(網)、無向圖(網)的構造以及遍歷
阿新 • • 發佈:2019-01-27
構造圖採用的是鄰接表的方法,然後採用深度和廣度優先進行遍歷。(博主第一次寫構造方法的時候花了很久寫的很冗雜,雖然也實現了,但是感覺到處都在打補丁,拼拼湊湊寫出來的,後來用了一分鐘重寫了一個,秒通過!!!欲哭無淚啊~原因主要是因為不同的輸入格式導致的,以後些其他程式碼的時候要慎重考慮輸入的格式問題)
下面貼程式碼!
根據書上的虛擬碼,寫出定義的結構
const int MAX_VERTEX_NUM = 20; bool visited[MAX_VERTEX_NUM]; //遍歷訪問標誌 typedef struct ArcNode{ int adjvex; //該弧所指向的頂點的位置 struct ArcNode *nextarc; //指向下一條弧(邊)的指標 int weight; //該弧(邊)的權值 }ArcNode; typedef struct VNode{ char data; //頂點資訊 ArcNode *firstarc; //指向第一條依附該頂點的弧(邊)的指標 }VNode,AdjList[MAX_VERTEX_NUM]; typedef struct{ AdjList vertices; int vexnum, arcnum; //圖的當前頂點數和弧(邊)數 int kind; }ALGraph;
根據書上的虛擬碼,寫出三個要用到的方法
//返回頂點v在圖G中的位置 int LocateVex(ALGraph G, char v) { for (int i = 0; i < G.vexnum; i++){ if (v == G.vertices[i].data) return i; } return -1; } //返回v的第一個鄰接頂點 int FirstAdjVex(ALGraph G, int v) { if (G.vertices[v].firstarc) return G.vertices[v].firstarc->adjvex; return -1; } //返回頂點v相對於鄰接點w的下一個鄰接點 int NextAdjVex(ALGraph G, int v, int w) { ArcNode *p; p = G.vertices[v].firstarc; if (p){ while (p){ if (w == p->adjvex){ if (nullptr == p->nextarc) return -1; else return p->nextarc->adjvex; } p = p->nextarc; } } return -1; }
下面是本體,一分鐘改寫出的構造圖的方法!
//採用鄰接表構造圖G void CreateGraph(ALGraph &G) { int i, j, weight; char v, v1, v2; ArcNode *p, *q = nullptr; cout << "請輸入圖型別的序號:\n1.DG(有向圖)\n2.DN(有向網\n3.UDG(無向圖)\n4.UDN(無向網)" << endl; cin >> G.kind; cout << "請輸入圖G的頂點數和弧(邊)數:"; cin >> G.vexnum >> G.arcnum; //構造鄰接表 for (i = 0; i < G.vexnum; i++){ cout << "請輸入頂點vex[" << i << "]的值:"; cin >> G.vertices[i].data; G.vertices[i].firstarc = nullptr; } cout << endl; for (j = 0; j < G.arcnum; j++){ cout << "請輸入第" << j << "條弧(邊)的兩個端點:"; cin >> v1 >> v2; q = G.vertices[LocateVex(G, v1)].firstarc; p = new ArcNode; p->adjvex = LocateVex(G, v2); p->nextarc = nullptr; if (1 == G.kind || 3 == G.kind) p->weight = 1; else{ cout << "請輸入該弧(邊)的權值:"; cin >> weight; p->weight = weight; } if (q){ while (q->nextarc) q = q->nextarc; q->nextarc = p; } else G.vertices[LocateVex(G, v1)].firstarc = p; if (3 == G.kind || 4 == G.kind){ q = G.vertices[LocateVex(G, v2)].firstarc; p = new ArcNode; p->adjvex = LocateVex(G, v1); p->nextarc = nullptr; if (1 == G.kind || 3 == G.kind) p->weight = 1; else{ p->weight = weight; } if (q){ while (q->nextarc) q = q->nextarc; q->nextarc = p; } else G.vertices[LocateVex(G, v2)].firstarc = p; } } }
根據書上的虛擬碼,寫出深度優先遍歷的遞迴方法
//深度優先遍歷(遞迴)
void DFS(ALGraph G, int v)
{
visited[v] = true;
cout << G.vertices[v].data << " ";
for (int i = FirstAdjVex(G, v); i >= 0; i = NextAdjVex(G, v, i)){
if (!visited[i])
DFS(G, i);
}
}
void DFSTraverse(ALGraph G)
{
int i;
cout << "深度優先結果:" << endl;
for (i = 0; i < G.vexnum; i++)
visited[i] = false;
for (i = 0; i < G.vexnum; i++){
if (!visited[i])
DFS(G, i);
}
cout << endl;
}
列印函式在測試的時候不可少
//列印鄰接表
void PrintALGraph(ALGraph G)
{
ArcNode *p;
for (int i = 0; i < G.vexnum; i++){
cout << G.vertices[i].data;
if (G.vertices[i].firstarc){
p = G.vertices[i].firstarc;
while (p){
if (3 == G.kind || 4 == G.kind)
cout << " - " << G.vertices[p->adjvex].data;
else
cout << "→" << G.vertices[p->adjvex].data;
p = p->nextarc;
}
}
cout << endl;
}
}
最後配上主函式
int main()
{
ALGraph graph;
CreateGraph(graph);
PrintALGraph(graph);
DFSTraverse(graph);
system("pause");
return 0;
}