圖的表示最長用的兩種方法是:
1)、鄰接矩陣表示法
2)、鄰接表表示
下面是兩種構造圖的方法
1)鄰接矩陣:
#include <iostream>
#include <vector>
using namespace std;
//枚舉類型,圖的種類 DG:有向圖;WDG:帶權值的有向圖;
//UDG: 無向圖;WUDG: 帶權值的無向圖
enum GraphKind {DG, WDG, UDG, WUDG};
//vertexType頂點類型,VRType:頂點之間的關係類型,InfoType:弧的信息類型
template <typename VertexType, typename VRType, typename InfoType>
class MGraph
{
public:
MGraph(int vexNum, GraphKind __kind) : vexnum(vexNum), arcnum(0), kind(__kind)
{
//分配頂點向量數組
vvec = new VertexType[vexnum];
//動態分配二維數組, 注意二維數組的動態分配
arcs = new ArcCell *[vexnum];
for (int i = 0; i < vexnum; i++)
{
//爲每一行動態分配空間
arcs[i] = new ArcCell[vexnum];
}
}
void Create()
{
switch (kind)
{
case DG:
{
CreateDG(); //構造一個有向圖
break;
}
case WDG:
{
CreateWDG(); //構造一個帶權有向圖
break;
}
case UDG:
{
CreateUDG(); //構造一個無向圖
break;
}
case WUDG:
{
CreateWUDG(); //構造一個帶權無向圖
break;
}
default:
return;
}
}
//初始化頂點數組和鄰接矩陣
void Init()
{
cout << "請輸入每個頂點的關鍵字:" << endl;
VertexType val;
for (int i = 0; i < vexnum; i++)
{
cin >> val;
vvec[i] = val;
}
for (int i = 0; i < vexnum; i++)
{
ArcCell ac;
ac.adj = 0;
ac.info = NULL;
for (int j = 0; j < vexnum; j++)
{
arcs[i][j] = ac;
}
}
}
//構造一個有向圖
void CreateDG()
{
Init();
int vhead, vtail;
cout << "請依次輸入每條邊的開始頂點和結束頂點:" << endl;
while (cin >> vhead >> vtail)
{
arcnum++;
arcs[vhead][vtail].adj = 1;
}
}
//構造一個帶權有向圖
void CreateWDG()
{
Init();
int vhead, vtail;
InfoType w;
cout << "請依次輸入每條邊的開始頂點和結束頂點和權值:" << endl;
while (cin >> vhead >> vtail >> w)
{
arcnum++;
arcs[vhead][vtail].adj = w;
}
}
//構造一個無向圖
void CreateUDG()
{
Init();
int vhead, vtail;
cout << "請依次輸入每條邊的開始頂點和結束頂點:" << endl;
while (cin >> vhead >> vtail)
{
arcnum += 2;
arcs[vhead][vtail].adj = 1;
arcs[vtail][vhead].adj = 1;
}
}
//構造一個帶權無向圖
void CreateWUDG()
{
Init();
int vhead, vtail;
InfoType w;
cout << "請依次輸入每條邊的開始頂點和結束頂點和權值:" << endl;
while (cin >> vhead >> vtail >> w)
{
arcnum += 2;
arcs[vhead][vtail].adj = w;
arcs[vtail][vhead].adj = w;
}
}
void displayGraph()
{
cout << "總共有" << vexnum << "個頂點,"
<< arcnum << "條邊" << endl;
for (int i = 0; i < vexnum; i++)
{
cout << "第" << i+1 << "個頂點是:" << vvec[i]
<< "相鄰的邊有: ";
for (int j = 0; j < vexnum; j++)
{
if (arcs[i][j].adj != 0)
cout << vvec[j] << "(" << arcs[i][j].adj << ") ";
}
cout << endl;
}
}
private:
struct ArcCell
{
VRType adj; //頂點關係類型。對於無權圖,用1或0表示
//表示相鄰與否;對帶權圖,爲權值類型
InfoType info; //該弧相關的信息的指針
};
VertexType *vvec; //頂點向量
ArcCell **arcs; //鄰接矩陣
int vexnum; //圖的當前頂點個數
int arcnum; //圖的弧數
GraphKind kind; //圖的種類標誌
};
int main()
{
cout << "構造無向圖:" << endl;
MGraph<char, int, int> udgGraph(8, UDG);
udgGraph.Create();
udgGraph.displayGraph();
cout << "構造帶權無向圖:" << endl;
MGraph<char, int, int> wudgGraph(9, WUDG);
wudgGraph.Create();
wudgGraph.displayGraph();
cout << "構造有向圖:" << endl;
MGraph<char, int, int> dgGraph(6, DG);
udgGraph.Create();
udgGraph.displayGraph();
cout << "構造帶權有向圖:" << endl;
MGraph<char, int, int> wdgGraph(6, WDG);
wdgGraph.Create();
wdgGraph.displayGraph();
system("pause");
return 0;
}
運行了一個帶權有向圖:
2)鄰接鏈表
#include <iostream>
using namespace std;
//枚舉類型,圖的種類 DG:有向圖;WDG:帶權值的有向圖;
//UDG: 無向圖;WUDG: 帶權值的無向圖
enum GraphKind {DG, WDG, UDG, WUDG};
template<typename VertexType, typename InfoType>
class ALGraph
{
public:
ALGraph(int verNum, GraphKind _kind)
: vexnum(verNum), arcnum(0), kind(_kind)
{
for (int i = 0; i < MAX_VERTEX_NUM; i++)
vertices[i].firstarc = NULL;
}
//構造圖,進行選擇
void Create()
{
switch (kind)
{
case DG:
{
CreateDG(); //構造一個有向圖
break;
}
case WDG:
{
CreateWDG(); //構造一個帶權有向圖
break;
}
case UDG:
{
CreateUDG(); //構造一個無向圖
break;
}
case WUDG:
{
CreateWUDG(); //構造一個帶權無向圖
break;
}
default:
return;
}
}
//打印鄰接鏈表
void displayGraph()
{
for (int i = 0; i < vexnum; i++)
{
cout << "第" << i+1 << "個頂點是:" << vertices[i].data
<< " 鄰接表爲: ";
ArcNode *arcNode = vertices[i].firstarc;
while (arcNode != NULL)
{
cout << " -> " << vertices[arcNode->adjvex].data
<< "(" << arcNode->info << ")";
arcNode = arcNode->nextarc;
}
cout << endl;
}
}
private:
//初始化鄰接鏈表的表頭數組
void InitVertics()
{
cout << "請輸入每個頂點的關鍵字:" << endl;
VertexType val;
for (int i = 0; i < vexnum; i++)
{
cin >> val;
vertices[i].data = val;
}
}
//插入一個表結點
void insertArc(int vHead, int vTail, InfoType w)
{
//構造一個表結點
ArcNode *newArcNode = new ArcNode;
newArcNode->adjvex = vTail;
newArcNode->nextarc = NULL;
newArcNode->info = w;
//arcNode 是vertics[vHead]的鄰接表
ArcNode *arcNode = vertices[vHead].firstarc;
if (arcNode == NULL)
vertices[vHead].firstarc = newArcNode;
else
{
while (arcNode->nextarc != NULL)
{
arcNode = arcNode->nextarc;
}
arcNode->nextarc = newArcNode;
}
arcnum++;
}
//構造一個有向圖
void CreateDG()
{
InitVertics();
int vhead, vtail;
cout << "請依次輸入每條邊的開始頂點和結束頂點:" << endl;
while (cin >> vhead >> vtail)
{
insertArc(vhead, vtail, 0);
}
}
//構造一個帶權有向圖
void CreateWDG()
{
InitVertics();
int vhead, vtail;
InfoType w;
cout << "請依次輸入每條邊的開始頂點和結束頂點和權值:" << endl;
while (cin >> vhead >> vtail >> w)
{
insertArc(vhead, vtail, w);
}
}
//構造一個無向圖
void CreateUDG()
{
InitVertics();
int vhead, vtail;
cout << "請依次輸入每條邊的開始頂點和結束頂點:" << endl;
while (cin >> vhead >> vtail)
{
insertArc(vhead, vtail, 0);
insertArc(vtail, vhead, 0);
}
}
//構造一個帶權無向圖
void CreateWUDG()
{
InitVertics();
int vhead, vtail;
InfoType w;
cout << "請依次輸入每條邊的開始頂點和結束頂點和權值:" << endl;
while (cin >> vhead >> vtail >> w)
{
insertArc(vhead, vtail, w);
insertArc(vtail, vhead, w);
}
}
//const數據成員必須在構造函數裏初始化
static const int MAX_VERTEX_NUM = 20; //最大頂點個數
struct ArcNode //表結點
{
int adjvex; //該弧所指向的頂點的位置
ArcNode *nextarc; //指向下一條弧的指針
InfoType info; //該弧相關信息的指針
};
struct VNode //頭結點
{
VertexType data; //頂點信息
ArcNode *firstarc; //指向第一條依附於該頂點的弧的指針
};
/*VNode AdjList[MAX_VERTEX_NUM];*/
/* AdjList[MAX_VERTEX_NUM] vertices;*/
VNode vertices[MAX_VERTEX_NUM];
int vexnum; //圖的當前頂點數
int arcnum; //圖的弧數
GraphKind kind; //圖的種類
};
int main()
{
cout << "構造一個8個頂點的無向圖:" << endl;
ALGraph<char, int> udgGraph(8, UDG);
udgGraph.Create();
udgGraph.displayGraph();
cout << "構造一個9個頂點的帶權無向圖:" << endl;
ALGraph<char, int> wudgGraph(9, WUDG);
wudgGraph.Create();
wudgGraph.displayGraph();
cout << "構造一個6個頂點的有向圖:" << endl;
ALGraph<char, int> dgGraph(6, DG);
dgGraph.Create();
dgGraph.displayGraph();
cout << "構造一個9個頂點的帶權有向圖:" << endl;
ALGraph<char, int> wdgGraph(9, WDG);
wdgGraph.Create();
wdgGraph.displayGraph();
system("pause");
return 0;
}