目录
1.有关术语说明
adjacency n.领接
Matrix n.矩阵
Graph n.图
Directed Graph 有向图DG
Undirected Graph 无向图UDG
Directed Net 有向网(有向带权图)DN
Undirected Net 无向网(无向带权图)UDN
arc n.弧(边)
vertex n.顶点
infinity n.无穷
2.Graph 结构体定义
typedef enum{DG,UDG,DN,UDN} Graphkind;
typedef struct {
int vexnum; //点数
int arcnum; //边数
char vexs[MAX]; //点集
int arcs[MAX][MAX]; //边集
Graphkind kind; //图种类
}AMGraph;
对于一个完整的图,其属性有顶点数目、边数目、存储顶点信息的数组、存储边信息的数组,也可以再加上表示图种类的信息,共五个属性。存储顶点信息的数组用一维即可,但由于边是由其两边顶点所确定,所以要用二维数组来存储。表示图种类的信息可用枚举类型定义,例如enum kind { value1,value2,value3,...};该语句定义了一个枚举类型变量kind,当kind值为0时,此时kind表示value1,值为1时表示value2,以此类推。
3.创建 Graph
void CreateGraph(AMGraph &G){ switch(G.kind){ case DG:CreateDG(G);break; case UDG:CreateUDG(G);break; case DN:CreateDN(G);break; case UDN:CreateUDN(G);break; } }
用switch case 语句来进行不同种类的图的创建:
int LocateVex(AMGraph G,char v){ for(int i=0;i<G.vexnum;i++)if(G.vexs[i]==v)return i; return -1; }
根据传入的顶点名称(字符v)确定顶点在顶点数组中的下标(i),进而确定两顶点所确定的边,并进行赋值。
3.1 CreateDG 创建有向图
void CreateDG(AMGraph &G){
int i,j,k;
char v1,v2;
//输入点数、边数
printf("输入点数、边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
getchar();
//输入点集————
printf("输入点:");
for(i=0;i<G.vexnum;i++){
scanf("%c",&G.vexs[i]);
getchar();}
//初始化边集为无穷
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)G.arcs[i][j]=INFINITY;
//赋值边集
for(k=0;k<G.arcnum;k++){
printf("输入第%d条边的顶点v1,v2:",k+1);
scanf("%c %c",&v1,&v2);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);
G.arcs[i][j]=1;
}
}
在函数体CreateDG()中实参列表传入了一个我们结构体定义的AMGraph类型的变量G,这里用了C++的引用类型&G以保证函数结束后对G进行的操作依然会保留。
scanf()函数遇空格或换行结束一次输入,但空格或换行符会写入缓存区被下一次字符类型输入读取,所以每次scanf()输入后都要加一个getchar()读掉缓存区的空格或换行符,保证不会读入异常数据,当然若都是int类型的输入则不需要考虑。
3.2 CreateUDG 创建无向图
void CreateUDG(AMGraph &G){
int i,j,k;
char v1,v2;
//输入点数、边数
printf("输入点数、边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
getchar();
//输入点集————
printf("输入点:");
for(i=0;i<G.vexnum;i++){
scanf("%c",&G.vexs[i]);
getchar();}
//初始化边集为无穷
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)G.arcs[i][j]=INFINITY;
//赋值边集
for(k=0;k<G.arcnum;k++){
printf("输入第%d条边的顶点v1,v2:",k+1);
scanf("%c %c",&v1,&v2);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);
G.arcs[i][j]=G.arcs[j][i]=1;
}
}
与1操作差不多,除了在最后的赋值边集时将对称位置上的边值一同赋值为1。
3.3 CreateDN 创建有向带权图
void CreateDN(AMGraph &G){
int i,j,k,w;
char v1,v2;
//输入点数、边数
printf("输入点数、边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
getchar();
//输入点集————
printf("输入点:");
for(i=0;i<G.vexnum;i++){
scanf("%c",&G.vexs[i]);
getchar();}
//初始化边集为无穷
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)G.arcs[i][j]=INFINITY;
//赋值边集
for(k=0;k<G.arcnum;k++){
printf("输入第%d条边的顶点v1,v2和权值w:",k+1);
scanf("%c %c %d",&v1,&v2,&w);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);
G.arcs[i][j]=w;
}
}
与1、2操作差不多,新增定义一个int类型变量w,用来在赋值边集时读取权值。
3.4 CreateUDN 创建无向带权图
void CreateUDN(AMGraph &G){
int i,j,k,w;
char v1,v2;
//输入点数、边数
printf("输入点数、边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
getchar();
//输入点集————
printf("输入点:");
for(i=0;i<G.vexnum;i++){
scanf("%c",&G.vexs[i]);
getchar();}
//初始化边集为无穷
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)G.arcs[i][j]=INFINITY;
//赋值边集
for(k=0;k<G.arcnum;k++){
printf("输入第%d条边的顶点v1,v2和权值w:",k+1);
scanf("%c %c %d",&v1,&v2,&w);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);
G.arcs[i][j]=G.arcs[j][i]=w;
}
}
与3操作差不多,除了在最后的赋值边集时将对称位置上的边值一同赋值为读取的权值w。
4.打印矩阵
void print(AMGraph G){//以矩阵形式输出图
int i,j;
switch(G.kind){
case DG:printf("打印有向图:\n");break;
case UDG:printf("打印无向图:\n");break;
case DN:printf("打印有向带权图:\n");break;
case UDN:printf("打印无向带权图:\n");break;
}
for(i=0;i<G.vexnum;i++){
printf("%c-",G.vexs[i]);
for(j=0;j<G.vexnum;j++){
if(G.arcs[i][j]==INFINITY)printf("%4s","∞");
else printf("%4d",G.arcs[i][j]);
}
printf("\n");
}
}
5.main()主函数
int main(){
AMGraph G;
printf("请输入你要创建图的类型—0.有向图 1.无向图 2.有向带权图 3.无向带权图:");
scanf("%d",&G.kind);
CreateGraph(G);
print(G);
return 0;
}