圖-表示多對多的關系,一組頂點V(一個非空有限頂點集合),一組邊E(一個有限邊集合),邊上有權重稱為網絡。用鄰接矩陣(稠密圖)或者鄰接表(稀疏圖)表示一個圖。
一、鄰接矩陣表示:
在Graph_M.h中:
#include"iostream"
using namespace std;
/******************鄰接矩陣表示圖**************************/
#define MaxVertexNum 128
#define WeightType int
typedef int Vertex;
typedef struct GNode *PtrToGNode;
struct GNode {
int Nv; //頂點數
int Ne; //邊數
WeightType G[MaxVertexNum][MaxVertexNum]; //存儲頂點的資料
};
typedef PtrToGNode MGraph;
typedef struct ENode *PtrToENode;
struct ENode
{
Vertex V1, V2; //有向邊<V1,V2>
WeightType Weight; //權重
};
typedef PtrToENode Edge;
MGraph CreateGraph(int VertexNum);
void InsertEdge(MGraph Graph, Edge E);
MGraph BuildGraph();
void OutputGraph(MGraph Graph);
在Graph_M.cpp中:
#include"Graph_M.h"
/******************鄰接矩陣表示圖**************************/
MGraph CreateGraph(int VertexNum)
{
Vertex V, W;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (V = 0; V < Graph->Nv; V++)
for (W = 0; W < Graph->Nv; W++)
Graph->G[V][W] = 0;
return Graph;
}
void InsertEdge(MGraph Graph, Edge E)
{
Graph->G[E->V1][E->V2] = E->Weight;
/*若是無向圖,還要插入邊<V2,V1>*/
Graph->G[E->V2][E->V1] = E->Weight;
}
MGraph BuildGraph()
{
MGraph Graph; Edge E;
Vertex V; int Nv, i;
cout << "Input Nv:\n";
cin >> Nv;
Graph = CreateGraph(Nv);
cout << "Input Ne:\n";
cin >> Graph->Ne;
if (Graph->Ne !=0)
{
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i < Graph->Ne; i++)
{
cout << "Input Edge of V1,V2,weight:\n";
cin >> E->V1 >> E->V2 >> E->Weight;
InsertEdge(Graph, E);
}
}
/*如果頂點有資料的話,需要在這裡讀入資料*/
//for (V = 0; V < Graph->Nv; V++)
// cin >> Graph->Data[V];
return Graph;
}
void OutputGraph(MGraph Graph)
{
int i,j;
for (i = 0; i < Graph->Nv; i++)
for (j = 0; j < Graph->Nv; j++)
{
if (Graph->G[i][j] != 0)
cout << i << " " << j << "-" << Graph->G[i][j]<<"\n";
}
}
運作結果:
二、鄰接表表示
先引入隊列的實作,因為在廣度優先搜尋中需要隊列。
可參考本連載中隊列的實作:https://blog.csdn.net/qq_28821995/article/details/89447884
在Graph_T.h:
#include"iostream"
using namespace std;
/******************鄰接表表示圖**************************/
#define MaxVertexNum 128
#define WeightType int
typedef int Vertex;
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode {
Vertex AdjV; /* 鄰接點下标 */
WeightType Weight; /* 邊權重 */
PtrToAdjVNode Next;
};
typedef struct Vnode {
PtrToAdjVNode FirstEdge;
//DataType Data; /* 存頂點的資料 */
} AdjList[MaxVertexNum];
typedef struct ENode *PtrToENode;
struct ENode
{
Vertex V1, V2; //有向邊<V1,V2>
WeightType Weight; //權重
};
typedef PtrToENode Edge;
typedef struct GNode *PtrToGNode;
struct GNode
{
int Nv, Ne; //頂點數,邊數
int Visited[MaxVertexNum]; //周遊時用來标記各個頂點是否通路
AdjList G; //鄰接表
};
typedef PtrToGNode LGraph;
/* 以鄰接表方式存儲的圖類型 */
typedef struct GShort *PtrGSshort;
struct GShort
{
int path[MaxVertexNum], dist[MaxVertexNum]; //尋找最短路徑時要使用的
};
LGraph CreateGraph(int VertexNum);
void InsertEdge(LGraph Graph, Edge E);
LGraph BuildGraph();
void DFS(LGraph G, int i);
void BFS_0(LGraph G);
void BFS(LGraph G, int V);
void BFS_Unweighted(LGraph G, Vertex S);
在Graph_T.cpp中:
#include"Graph_T.h"
#include"QueueList.h"
/******************鄰接表表示圖**************************/
LGraph CreateGraph(int VertexNum)
{
Vertex V, W;
LGraph Graph;
Graph = (LGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
//頂點編号從0開始的 一直到Nv-1
for (V = 0; V < Graph->Nv; V++)
Graph->G[V].FirstEdge = NULL;
for (size_t i = 0; i < Graph->Nv; i++)
{
Graph->Visited[i] = 0;
}
return Graph;
}
void InsertEdge(LGraph Graph, Edge E)
{
PtrToAdjVNode NewNode;
/************************插入邊<V1,V2>************************/
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V2;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
/************************若是無向圖,還要插入邊<V2,V1>************************/
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V1;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V2].FirstEdge;
Graph->G[E->V2].FirstEdge = NewNode;
}
LGraph BuildGraph()
{
LGraph Graph; Edge E;
Vertex V; int Nv, i;
cout << "Input Nv:\n";
cin >> Nv;
Graph = CreateGraph(Nv);
cout << "Input Ne:\n";
cin >> Graph->Ne;
if (Graph->Ne != 0)
{
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i < Graph->Ne; i++)
{
cout << "Input Edge of V1,V2,weight:\n";
cin >> E->V1 >> E->V2 >> E->Weight;
InsertEdge(Graph, E);
}
}
/*如果頂點有資料的話,需要在這裡讀入資料*/
//for (V = 0; V < Graph->Nv; V++)
// cin >> Graph->Data[V];
return Graph;
}
void DFS(LGraph G, int i)
{
PtrToAdjVNode W;
cout << i << "-";
G->Visited[i] = 1;
for (W = G->G[i].FirstEdge; W; W = W->Next)
if (!G->Visited[W->AdjV])
DFS(G, W->AdjV);
return;
}
void BFS_0(LGraph G)
{
Queue Q = NULL;
PtrToAdjVNode W;
Q = MakeEmptyQ();
Vertex U, V;
for (U = 0; U<G->Nv; ++U)
if (!G->Visited[U]) //頂點未通路
{
G->Visited[U] = 1;
cout << U << "-";
AddQ(Q, U);
while (!IsEmptyQ(Q))
{
V = DeleteQ(Q); //出隊列
for (W = G->G[V].FirstEdge; W; W = W->Next)
if (!G->Visited[W->AdjV]) {
G->Visited[W->AdjV] = 1;
cout << W->AdjV << "-";
AddQ(Q, W->AdjV);
}
} //while
} //if
}
void BFS(LGraph G, int V)
{
Queue Q = NULL;
PtrToAdjVNode W;
Q = MakeEmptyQ();
G->Visited[V] = 1;
AddQ(Q, V);
while (!IsEmptyQ(Q))
{
V = DeleteQ(Q);
cout << V << "-";
for (W = G->G[V].FirstEdge; W; W = W->Next)
if (!G->Visited[W->AdjV]) {
G->Visited[W->AdjV] = 1;
AddQ(Q, W->AdjV);
}
}
}
void BFS_Unweighted(LGraph G, Vertex S)
{
int i;
Vertex V;
Queue Q = NULL;
PtrToAdjVNode W;
PtrGSshort GS;
GS = (PtrGSshort)malloc(sizeof(struct GShort));
for (i = 0; i < G->Nv; i++)
{
GS->dist[i] = -1; //S到W的最短路徑
GS->path[i] = 0; //S到W的路上經過的某頂點
}
GS->dist[S] = 0;
Q = MakeEmptyQ();
AddQ(Q, S);
while (!IsEmptyQ(Q))
{
V = DeleteQ(Q);
/*cout << V << "-";*/
for (W = G->G[S].FirstEdge; W; W = W->Next)
if (GS->dist[W->AdjV] == -1) {
GS->dist[W->AdjV] = GS->dist[V] + 1; //0-代表直接相連,1-代表中間隔一個頂點...
GS->path[W->AdjV] = V;
AddQ(Q, W->AdjV);
}
}
}
運作結果: