图的存储结构(1):数组表示法
2014-05-17 22:53
316 查看
引言:图是一种较线性表和树更为复杂的数据结构。在线性表中,数据元素之间仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继;在树形结构中,数据元素之间有明显的层次关系,每一层的数据元素只能与下一层的多个元素相关,但只能和上一层中的一个元素相关;而在图形结构中,结点之间的关系可以是任意的,图中任意两个数据元素之间都有可能相关。因此这对于刚掌握c语言的学生来说掌握图这种数据结构,并且可以用完整的代码实现还是有一定困难的!特别是数据结构(严蔚敏版)!但是随着时间的推移,越发觉得严蔚敏老师写的程序实在是精妙!以下程序是根据数据结构上严蔚敏老师算法片段而写的完整的数组表示法!
例子:
![](http://img.blog.csdn.net/20140517230653781?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDcyMTA3OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20140517231403265?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDcyMTA3OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
数组表示法的特点:
1、用二维数组存储有n个顶点的图时,需要存放n个顶点信息和n^2个弧的信息。若图是无向图,根据无向图的邻接矩阵的对称性,则可采用压缩存储的方式只存入矩阵的下三角或上三角元素。
2、根据邻接矩阵容易判定任意两个顶点之间是有边(或弧)相连,并且容易求得各个顶点的度。
3、对于无向图,顶点vi的度是邻接矩阵中第i行(或第i列)的元素之和。
4、对于有向图,顶点vi的出度是邻接矩阵中第i行的元素之和。
有向图运行效果:
例子:
数组表示法的特点:
1、用二维数组存储有n个顶点的图时,需要存放n个顶点信息和n^2个弧的信息。若图是无向图,根据无向图的邻接矩阵的对称性,则可采用压缩存储的方式只存入矩阵的下三角或上三角元素。
2、根据邻接矩阵容易判定任意两个顶点之间是有边(或弧)相连,并且容易求得各个顶点的度。
3、对于无向图,顶点vi的度是邻接矩阵中第i行(或第i列)的元素之和。
4、对于有向图,顶点vi的出度是邻接矩阵中第i行的元素之和。
#include <iostream> using std::cin; using std::cout; using std::endl; #include<string.h> #define INFINITY 0 //两个顶点之间无边或弧时的数值 #define MAX_VERTEX_NUM 26 //最大顶点个数 #define MAX_INFO 10 //弧相关信息的字符串的最大长度 #define TRUE 1 #define FALSE 0 #define ERROR 0 #define OK 1 typedef int Status; typedef int VRType; //顶点关系类型 typedef char InfoType; typedef char VertexType[MAX_VERTEX_NUM]; //顶点类型 enum GraphKind{DG,DN,UDG,UDN}; //有向图,有向网,无向图,无线网 typedef struct { VRType adj; // VRType是顶点关系类型,对无权图,用1或0 //表示相邻否,对带权图,则为权值类型 InfoType *info; // 该弧相关信息的指针 }ArcCell, AdjMartix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct { VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 AdjMartix arcs; //邻接矩阵 int vexnum,arcnum; //图的当前顶点个数和弧数 GraphKind kind; //图的种类标志 }MGraph; int LocateVex(MGraph G,VertexType u) //若图中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息 { for(int i = 0; i < G.vexnum; ++i) if(strcmp(u,G.vexs[i]) == 0) return i; return -1; } Status CreateDG(MGraph &G) //采用数组(邻接矩阵)表示法,构造有向图 { int i,j,k,l,IncInfo; char a[MAX_INFO]; VertexType va,vb; cout << "**********************************有向图*************************************" << endl; cout << "请输入有向图的顶点数,边数,以及边是否含有其它信息(是:1,否:0):" << endl; cout << "请输入顶点数: "; cin >> G.vexnum; cout << "请输入弧数: " << endl; cin >> G.arcnum ; cout << "请输入边是否含有其它信息(是:1,否:0): " << endl; cin >> IncInfo; cout << "开始构造有向图:\n" << "逐一输入顶点向量" << endl; for(i = 0;i < G.vexnum;++i) { cout << "请输入第"<<i+1<<"个顶点的向量: "<<endl; cin >> G.vexs[i] ; } for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵 for(j = 0; j < G.vexnum; ++j) { G.arcs[i][j].adj = INFINITY; //有向图 G.arcs[i][j].info = NULL; } cout << "请输入" << G.arcnum << "条弧的弧头和弧尾" << endl; for(k = 0; k < G.arcnum; ++k) { cout << "请输入第" << k + 1 << "条弧的弧尾:" << endl; cin >> va ; cout << "请输入第" << k + 1 << "条弧的弧头:" << endl; cin >> vb; i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = 1; //有向图 if(IncInfo) { cout << "请输入该边的相关信息(" << MAX_INFO << "个字符)"; cin >> a; l = strlen(a); if(l) { G.arcs[i][j].info = (char *)malloc( (l+1)*sizeof(char) ); //有向图 strcpy(G.arcs[i][j].info,a); } } } G.kind = DG; return OK; } Status CreateDN(MGraph &G) //采用数组(邻接矩阵),构造有向网 { int i, j, k, w, IncInfo; char a[MAX_INFO]; VertexType va,vb; cout << "**********************************有向网*************************************" << endl; cout << "请输入有向网的顶点数,弧数、权值以及边是否含有其它信息(是:1,否:0):" << endl; cout << "请输入顶点数: "; cin >> G.vexnum; cout << "请输入弧数: " << endl; cin >> G.arcnum ; cout << "请输入边是否含有其它信息(是:1,否:0): " << endl; cin >> IncInfo; cout << "开始构造有向网: \n" << "逐一输入顶点向量" << endl; for(i = 0;i < G.vexnum;++i) { cout << "请输入第"<<i+1<<"个顶点的向量: "<<endl; cin >> G.vexs[i] ; } for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵 for(j = 0; j < G.vexnum; ++j) { G.arcs[i][j].adj = INFINITY; //有线网 G.arcs[i][j].info = NULL; } cout << "请输入" << G.arcnum << "条弧的弧尾、弧头和权值" << endl; for(k = 0; k < G.arcnum; ++k) { cout << "请输入第" << k + 1 << "条弧的弧尾:" << endl; cin >> va ; cout << "请输入第" << k + 1 << "条弧的弧头:" << endl; cin >> vb; cout << "请输入该弧的权值: " << endl; cin >> w; i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = w; //有向网 if(IncInfo) { cout << "请输入该边的相关信息(" << MAX_INFO << "个字符)"; cin >> a; w = strlen(a); if(w) { G.arcs[i][j].info = (char *)malloc((w+1)*sizeof(char)); //有向网 strcpy(G.arcs[i][j].info,a); } } } G.kind = DN; return OK; } Status CreateUDG(MGraph &G) //用数组(邻接矩阵)表示法,构造无向图 { int i,j,k,l,IncInfo; char a[MAX_INFO]; VertexType va,vb; cout << "**********************************无向图*************************************" << endl; cout << "请输入无向图的顶点数,边数,以及边是否含有其它信息(是:1,否:0):" << endl; cout << "请输入顶点数: "; cin >> G.vexnum; cout << "请输入边数: " << endl; cin >> G.arcnum ; cout << "请输入边是否含有其它信息(是:1,否:0): " << endl; cin >> IncInfo; cout << "开始构造无向图: \n" << "逐一输入顶点向量……" << endl; for(i = 0;i < G.vexnum;++i) { cout << "请输入第"<<i+1<<"个顶点的向量: "<<endl; cin >> G.vexs[i] ; } for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵 for(j = 0; j < G.vexnum; ++j) { G.arcs[i][j].adj = INFINITY; G.arcs[i][j].info = NULL; } for (k = 0; k < G.arcnum; ++k) { cout << "请输入第" << k + 1 << "条边的第一个顶点:" << endl; cin >> va ; cout << "请输入第" << k + 1 << "条边的第二个顶点:" << endl; cin >> vb; i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = G.arcs[j][i].adj = 1; // 无向图 if(IncInfo) { cout << "请输入该边的相关信息(" << MAX_INFO << "个字符)"; cin >> a; l = strlen(a); if (l) { G.arcs[i][j].info = G.arcs[j][i].info = (char *)malloc( (l + 1)*sizeof(char) ); //给相关信息分配内存空间 strcpy(G.arcs[i][j].info,a); } //无向图,两个指针指向同一个信息 } } G.kind = UDG; return OK; } Status CreateUDN(MGraph &G) //采用数组(邻接矩阵)表示法,构造无向网 { int i,j,k,w,IncInfo; char a[MAX_INFO]; VertexType va,vb; cout << "**********************************无向网*************************************" << endl; cout << "请输入无向网的顶点数、边数和权值,以及边是否含有其它信息(是:1,否:0):" << endl; cout << "请输入顶点数: "; cin >> G.vexnum; cout << "请输入边数: " << endl; cin >> G.arcnum ; cout << "请输入边是否含有其它信息(是:1,否:0): " << endl; cin >> IncInfo; cout << "开始构造无向网: \n" << "逐一输入顶点向量" << endl; for(i = 0;i < G.vexnum;++i) { cout << "请输入第"<<i+1<<"个顶点的向量: "<<endl; cin >> G.vexs[i] ; } for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵 for(j = 0; j < G.vexnum; ++j) { G.arcs[i][j].adj = INFINITY; //无线网 G.arcs[i][j].info = NULL; } for (k = 0; k < G.arcnum; ++k) { cout << "请输入第" << k + 1 << "条边的第一个顶点:" << endl; cin >> va ; cout << "请输入第" << k + 1 << "条边的第二个顶点:" << endl; cin >> vb; cout << "请输入该边的权值: " << endl; cin >> w; i =LocateVex(G,va); j =LocateVex(G,vb); G.arcs[i][j].adj = G.arcs[j][i].adj = w; //无向网 if (IncInfo) { cout << "请输入该边的相关信息(" << MAX_INFO << "个字符)"; cin >> a; w = strlen(a); if (w) { G.arcs[i][j].info = G.arcs[j][i].info = (char *)malloc((w+1)*sizeof(char)); //无向网,两个指针指向同一个信息 strcpy(G.arcs[i][j].info,a); } } } G.kind = UDN; return OK; } Status CreateGraph(MGraph &G) { cout << "请输入图G的类型\n" << "有向图:0\n" << "有向网:1\n" << "无向图:2\n" << "无向网:3\n"; scanf("%d",&G.kind); switch(G.kind) { case DG: CreateDG(G); //有向图 break; case DN: CreateDN(G); //有向网 break; case UDG: CreateUDG(G); //无向图 break; case UDN: CreateUDN(G); //无向网 break; } return OK; } Status DestroyGraph(MGraph &G) //若图存在,则销毁图G { int i,j,k = 0; if(G.kind % 2) // 网 k = INFINITY; // K为两顶点之间无边或无弧时邻接矩阵元素的值 for(i = 0; i < G.vexnum; ++i) if(G.kind < 2) //有向 { for(j = 0; j < G.vexnum; ++j) if(G.arcs[i][j].adj != k) //两顶点之间有弧 if(G.arcs[i][j].info) { free(G.arcs[i][j].info); G.arcs[i][j].info = NULL; } } else { for (j = i + 1; j < G.vexnum; ++j) { if (G.arcs[i][j].adj != k) if(G.arcs[i][j].info) { free(G.arcs[i][j].info); G.arcs[i][j].info = G.arcs[j][i].info = NULL; } } } G.vexnum = 0; G.vexnum = 0; return OK; } void Display(MGraph &G) { for(int i = 0; i < G.vexnum; ++i) for(int j = 0; j < G.vexnum; ++j) { cout << G.arcs[i][j].adj << ' '; if((j+1)%G.vexnum == 0) cout << endl; } } int main() { int i,j,k,n; MGraph G; CreateGraph( G); Display(G); DestroyGraph(G); return 0; }
有向图运行效果:
相关文章推荐
- 图的存储结构之数组表示法
- 数据结构之---C语言实现图的数组(邻接矩阵)存储表示
- 图(网)的存储结构(数组存储表示即邻接矩阵、邻接表)
- 图(网)的存储结构(数组存储表示即邻接矩阵、邻接表)
- 【数据结构】算法7.1-7.2 图的存储结构-数组表示法
- 图的存储结构(1):数组表示法
- 数组的顺序存储表示和实现-数据结构
- 6.33③ 假定用两个一维数组L[1..n]和R[1..n]作为 有n个结点的二叉树的存储结构, L[i]和R[i]分别指 示结点i的左孩子和右孩子,0表示空。试写一个算法 判别结点u是否为结点v的
- 数组顺序存储表示和实现
- C语言多维数组的存储表示和实现
- 数组的顺序存储表示
- 【数据结构】线性表的单链表存储结构表示和实现
- 线性结构 -- 连续存储(数组), 1个简单的c语言代码实现.
- 用数组存储和创建图结构
- 数组的顺序结构表示和实现
- 数据结构数据存储表示---图
- 数据结构线性结构之连续存储---数组
- 二维数组存储结构
- 树的存储结构--双亲表示法
- 顺序表是线性表基于数组的存储表示