图的邻接矩阵表示法
图常用的存储方法又邻接表表示法以及邻接矩阵表示法,邻接表适合稀疏矩阵的存储,但是缺点是稍微复杂一点,并且插入操作或者说更新图的操作实际上是比较复杂的,而邻接矩阵更加简单,再存储密集矩阵的时候更加合适,下面使用c++实现一个简单的邻接矩阵。
由于图一般简单的分为几种:1. 无向图 2.有向图 3.带权无向图 4.带权有向图 下面可以构造的时候分别选择这几种方式来实现:
下面所提到的VType表示的是顶点的类型,一般设置成char或者string用于表示比较合适,ArcType表示的是弧的值类型,对于无权图用0,1分别表示非邻接以及邻接,而有全权图表示权重大小。
所有的private数据如下所示:
1 struct ArcCell{ 2 ArcType adj; //顶点对间关系类型,无权图为0或者1,表明相邻或者是不相邻,有权图代表的就是权值的大小 3 }; 4 VType *vvec; //用于表示顶点的信息,例如char或者string等 5 ArcCell ** arcs; //邻接矩阵 6 int vecNum; //顶点数目 7 int arcNum; //弧数目 8 GraphKind kind; //图的种类,非别可以为带权有向图,无向图,不带权有向,无向图。
default constructor:
1 Graph(int _vexNum = 0, GraphKind _kind = DG) : 2 vecNum(_vexNum), arcNum(0), kind(_kind) 3 { 4 vvec = new VType[vecNum]; 5 arcs = new ArcCell *[vecNum]; 6 for (int i = 0; i < vecNum; ++i){ 7 arcs[i] = new ArcCell[vecNum]; 8 } 9 }
destructor是non-trivial的,实际还是需要自己写一个的,代码如下:
1 ~Graph() 2 { 3 for (int i = 0; i < vecNum; ++i){ 4 delete[] arcs[i]; 5 } 6 delete[] arcs; 7 delete[] vvec; 8 }
下面是初始化所有的顶点信息:
1 void Init() 2 { 3 cout << "请输入每个顶点的关键字:" << endl; 4 VType val; 5 for (int i = 0; i < vecNum; ++i){ 6 cin >> vvec[i]; 7 } 8 ArcCell ac; 9 ac.adj = 0; 10 for (int i = 0; i < vecNum; ++i){ 11 for (int j = 0; j < vecNum; ++j){ 12 arcs[i][j] = ac; 13 } 14 } 15 }
下面是根据不同类型来进行图的创建:
有向图:
1 void createDG() 2 { 3 Init(); 4 int vhead, vtail; 5 cout << " 请依次输入每条边的开始节点以及结束结点: " << endl; 6 while (cin >> vhead >> vtail){ 7 arcNum++; 8 arcs[vhead][vtail].adj = 1; 9 } 10 }
带权有向图:
1 void createWDG() 2 { 3 Init(); 4 int vhead, vtail; 5 ArcType w; 6 cout << " 请输入每条弧的开始顶点,结束顶点以及权值: " << endl; 7 while (cin >> vhead >> vtail >> w){ 8 arcNum++; 9 arcs[vhead][vtail].adj = w; 10 } 11 }
无向图:
1 void createUDG() 2 { 3 Init(); 4 int vhead, vtail; 5 cout << "请输入每条弧的开始顶点,结束顶点: " << endl; 6 while (cin >> vhead >> vtail){ 7 arcNum+=2; 8 arcs[vhead][vtail].adj = 1; 9 arcs[vtail][vhead].adj = 1; 10 } 11 }
带权无向图:
1 void createWUDG() 2 { 3 Init(); 4 int vhead, vtail; 5 ArcType w; 6 cout << "请输入每条弧的开始顶点,结束顶点以及弧的权重(总共的顶点数为: " << vecNum << ".)" << endl; 7 while (cin >> vhead >> vtail >> w){ 8 arcNum+=2; 9 arcs[vhead][vtail].adj = w; 10 arcs[vtail][vhead].adj = w; 11 } 12 }
图的显示部分:
1 void displayGraph() 2 { 3 cout << "顶点的总数为: " << vecNum << "个。" << endl; 4 cout << "弧的总数为: " << arcNum << "条。" << endl; 5 for (int i = 0; i < vecNum; ++i){ 6 cout << "第" << i + 1 << "个顶点为" << vvec[i] 7 << ",相邻的边为: "; 8 for (int j = 0; j < vecNum; ++j){ 9 if (arcs[i][j].adj != 0){ 10 cout << ", (" << arcs[i][j].adj << ", " << vvec[j] << ")"; 11 } 12 } 13 cout << endl; 14 } 15 }
大致上就是这样,有时间再来写一下图的dfs,bfs以及邻接链表表示法,下面贴一张生成图的截图: