为了方便读者的阅读,我们先介绍图中一些常用的术语:
1.图按照有无方向分为有向图和无向图,无向图有边和顶点构成,有向图由顶点和弧构成,弧有弧尾和弧头构成。
2.图按照边或弧的多少分为稀疏图和稠密图。如果任意两个顶点之间都存在边,叫完全图;有向的叫有向完全图。若无重复的边或顶点到自身的边则叫简单图。
3.图中的边或弧上的带权则称为网。
4.无向图中连通且n个顶点n -1条边叫生成树。有向图中一顶点的入度为0其余顶点入度为1的叫有向树。一个又向图由若干颗有向树构成生成森林。
在考试的时候有的同学可能遇到这样的问题,请使用邻接矩阵法建立一个图。相信大家的思路很多,那么下来小编介绍一种自己建立图的方法:先输入顶点数和边数,然后建立有顶点没有边的图,之后将邻接矩阵进行初始化,最后读入所有的边,这样就完成了图的建立。代码如下:
typedef struct { VertexType vexs[MAXVEX]; /* 顶点表 */ EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */ int numNodes, numEdges; /* 图中当前的顶点数和边数 */ }MGraph; /* 建立无向网图的邻接矩阵表示 */ void CreateMGraph(MGraph *G) { int i,j,k,w; printf("输入顶点数和边数:\n"); scanf("%d,%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */ for(i = 0;i <G->numNodes;i++) /* 读入顶点信息,建立顶点表 */ scanf(&G->vexs[i]); for(i = 0;i <G->numNodes;i++) for(j = 0;j <G->numNodes;j++) G->arc[i][j]=INFINITY; /* 邻接矩阵初始化 */ for(k = 0;k <G->numEdges;k++) /* 读入numEdges条边,建立邻接矩阵 */ { printf("输入边(vi,vj)上的下标i,下标j和权w:\n"); scanf("%d,%d,%d",&i,&j,&w); /* 输入边(vi,vj)上的权w */ G->arc[i][j]=w; G->arc[j][i]= G->arc[i][j]; /* 因为是无向图,矩阵对称 */ } }
讯享网
我们不能一直使用这种最基本的方式来进行图的建立操作,这种方法的弊端很多,而且不易进行后续的各种操作,不过考试进行使用倒是可以,接下来我们使用一种较为正规的方法来进行图的建立。
我们采用这样一种思路来进行图的建立:首先建立一个没有边的图,然后将图的边进行插入,这样就可以得到一个完整的图。
步骤如下:
1.顶点的建立:顶点的建立很简单,我们建立一个二维数组即可,二维数组的大小由顶点数来决定,为了操作方便,我们要将图的边数与顶点数和二维数组捆绑起来,因此,我们可以将他们打包成一个结构体进行操作,结构体定义如下:
讯享网//建立顶点结构体 struct Gnode{ int NV; //顶点数 int Ne; //边数 weighttype G[maxvertexnum][maxvertexnum]; //二维数组大小由图中的顶点数决定 datatype data[maxvertexnum]; //存储顶点的数据 }; typedef struct Gnode *ptrtoGnode: //指向顶点结构体的指针 typedef struct ptrtoGnode Mgraph; //邻接矩阵存储的图的类型,利用指针的话在向函数中传递参数的时候比较方便
如果顶点有数据,因此我们可以在建立一个一维数组来存储顶点的数据。小编在建立结构体之后会习惯性的建立一个指向该结构体的指针,这在后续的函数传参过程中会有很大帮助;试想,我们是直接传一个结构体方便还是传一个指针方便呢?
2.初始化一个没有边的图:首先我们给邻接矩阵进行内存申请操作,将顶点数设置为已知的顶点数,边数设置为0。然后将二维矩阵的所有数据都初始化为0,我们很简单的用到了二重循环进行初始化,最后将建立好的图进行返回。
Mgraph creat_graph(int vertexnum) { Vertex V, W; //将V,W定义为定点类型 Mgraph graph; graph = (Mgraph)malloc(sizeof(struct Gnode)); //给邻接矩阵申请空间 graph -> NV = vertexnum; //有顶点数 graph -> Ne = 0; //边数为0 //我们将V,W视作顶点而不是两个整形数 for(V = 0;V < graph -> NV;V++) for(W = 0;W < graph -> NV;w++) graph -> [V][W] = 0; //邻接矩阵的任意一个顶点得到V,W都定义为0,表示他们之间没有边 return graph; //将建立好的图返回 }
我们在循环中使用的是V,W,他们对应的是顶点类型(一般为整形,可以根据实际情况自行更改)
3.建立边结构体:
我们知道一个边是由两个顶点所决定的,如果是有权图的话,我们还要加上他的权重,这样边结构体的定义就完成了。建立代码如下:
讯享网//建立边结构体 struct enode{ Vertex v1, v2; //一个边由两个节点决定 从<v1, v2> 无权图的话,这样就可以了 weighttype weight; //权重 }; typedef struct enode *ptrtoenode; //指向边结构体的指针 typedef ptrtoenode edge;
4.插入边:
我们将边上的权重赋值给二位数组的元素,这样就完成了边的插入,如果是无向图的话,我们还需要将权值再次进行赋值。这样就完成了边的插入。
void inert_edge(Mgraph Graph, edge e) { //插入边 Graph -> G[e -> v1][e -> v2] = e -> weight; //若为无向图,还需要插入边<v2, v1> Graph -> G[e -> v2][e -> v1] = e -> weight; } 完成了上述的步骤之后,我们就可以进行一个图的建立了,首先,我们读入顶点数,调用函数进行没有边的图的建立,然后向图中插入边。
最终的完整版代码如下:
讯享网#include<stdio.h> //邻接矩阵表示图 #include<malloc.h> typedef int weighttype; typedef int datatype; typedef int Vertex; //建立顶点结构体 struct Gnode{ int NV; //顶点数 int Ne; //边数 weighttype G[maxvertexnum][maxvertexnum]; //二维数组大小由图中的顶点数决定 datatype data[maxvertexnum]; //存储顶点的数据 }; typedef struct Gnode *ptrtoGnode: //指向顶点结构体的指针 typedef struct ptrtoGnode Mgraph; //邻接矩阵存储的图的类型,利用指针的话在向函数中传递参数的时候比较方便 //建立边结构体 struct enode{ Vertex v1, v2; //一个边由两个节点决定 从<v1, v2> 无权图的话,这样就可以了 weighttype weight; //权重 }; typedef struct enode *ptrtoenode; //指向边结构体的指针 typedef ptrtoenode edge; //初始化一个有顶点没有边的图 Mgraph creat_graph(int vertexnum) { Vertex V, W; //将V,W定义为定点类型 Mgraph graph; graph = (Mgraph)malloc(sizeof(struct Gnode)); //给邻接矩阵申请空间 graph -> NV = vertexnum; //有顶点数 graph -> Ne = 0; //边数为0 //我们将V,W视作顶点而不是两个整形数 for(V = 0;V < graph -> NV;V++) for(W = 0;W < graph -> NV;w++) graph -> [V][W] = 0; //邻接矩阵的任意一个顶点得到V,W都定义为0,表示他们之间没有边 return graph; //将建立好的图返回 } //向建立好的图插入边 //方法:将相应的权重赋值给相应的邻接矩阵即可 void inert_edge(Mgraph Graph, edge e) { //插入边 Graph -> G[e -> v1][e -> v2] = e -> e -> weight; //若为无向图,还需要插入边<v2, v1> Graph -> G[e -> v2][e -> v1] = e -> e -> weight; } Mgraph build_graph() { Mgraph Graph; Edge E; Vertex V; int NV. i; scanf("%d", &Nv); Graph = creat_graph(Nv); scanf("%d", &(Graph -> Ne)); //直接使用创建好的图来进行边的操作 if(Graph -> Ne != 0) //如果没有边的话 { E = (edge)malloc(sizeof(struct enode)); //建立临时的边界点,存储这个边 for(i = 0;i < Graph -> Ne;i++) { scanf("%d %d %d", &E -> v1, &E -> v2, &E -> weight); //读入边的信息 insert_edge(Graph, E); //插入边的信息 } } //如果有数据的话,要进行数据的读入 for(V = 0;V < Graph -> Nv;V++) scanf("%c", (Graph -> data[V])); return Graph; } //输入格式 //Nv Ne 顶点数,边数 //v1 v2 weight 顶点,权重

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/117927.html