//构造有、无向图,有、无向网的入口函数intCreatGraph_M(MGraph* G){printf("Please select the kind of Graph:");scanf("%d",&G->kind);switch(G->kind){case DG:returnCreatDG_M(G);case DN:returnCreatDN_M(G);case UDG:returnCreatUDG_M(G);case UDN:returnCreatUDN_M(G);default:break;}}
三:定义顶点v在顶点数组中的位置(下标)
/**
* 确定顶点v在顶点数组中的位置
* @param G
* @param v 顶点数据
* @return 顶点在顶点数组中的下标
*/intLocateVex(MGraph G,VertexType v){for(int i =0; i < G.vexs;++i){if(v == G.vexs[i]){return i;}}return-1;}
四:创建有向图
//创建有向图intCreatDG_M(MGraph* G){//输入图的顶点个数vex,边数arcprintf("Please input the number of vex and arc:");scanf("%d,%d",&(G->vexnum),&(G->arcnum));getchar();//依次输入顶点数据本身printf("Please input the vex:\n");for(int i =0; i < G->vexnum;++i){scanf("%d",&(G->vexs[i]));getchar();}//初始化二维矩阵数组,全为0for(int i =0; i < G->vexnum;++i){for(int j =0; j < G->vexnum;++j){
G->arcs[i][j].adj =0;
G->arcs[i][j].info =NULL;//目前没有指针所指代的内容}}//在二位数组中添加数据for(int i =0; i < G->arcnum;++i){
VertexType v1;//弧尾
VertexType v2;//弧头//输入弧尾与弧头printf("Please input trail and front:");scanf("%d,%d",&v1,&v2);//定位int trail =LocateVex(*G,v1);//弧尾int front =LocateVex(*G,v2);//弧头//若有顶点不在图中if(front==-1||trail ==-1){printf("No find vertex!!");return0;}//将正确的弧数据加入到邻接矩阵中
G->arcs[trail][front].adj =1;}return1;}
五:创建有向网
/**
* 创建有向网
* 有向网与有向图的区别在与有向图中没有权值或者说权值为1
* 简而言之有向网为带权值的有向图
* @param G
* @return
*/intCreatDN_M(MGraph* G){//输入图中顶点个数与边的个数printf("Please input the num of vexs and arc:");scanf("%d,%d",&(G->vexnum),&(G->arcnum));getchar();//输入顶点数据printf("Please input the data of vex:");for(int i =0; i < G->vexnum;++i){scanf("%d",&(G->vexs[i]));getchar();}//初始化邻接矩阵为0for(int i =0; i < G->vexnum;++i){for(int j =0; j < G->vexnum;++j){
G->arcs[i][j].adj = INFINITY;
G->arcs[i][j].info =NULL;}}//确定头尾和边上的权值for(int i =0; i < G->arcnum;++i){
VertexType v1,v2;//v1为尾,v2为头
VRType m;//表示当前以v1为尾,v2为头的弧上面的权值printf("Please input the trail , head and value:");scanf("%d,%d,%d",&v1,&v2,&m);int row =LocateVex(*G,v1);//尾int col =LocateVex(*G,v2);//头//判断是否存在if(row ==-1||col ==-1){return0;}
G->arcs[row][col].adj = m;}return1;}
六:创建无向图
intCreatUDG_M(MGraph* G){//输入图的顶点个数vex,边数arcprintf("Please input the number of vex and arc:");scanf("%d,%d",&(G->vexnum),&(G->arcnum));getchar();//依次输入顶点数据本身printf("Please input the vex:\n");for(int i =0; i < G->vexnum;++i){scanf("%d",&(G->vexs[i]));getchar();}//初始化二维矩阵数组,全为0for(int i =0; i < G->vexnum;++i){for(int j =0; j < G->vexnum;++j){
G->arcs[i][j].adj =0;
G->arcs[i][j].info =NULL;//目前没有指针所指代的内容}}//在二位数组中添加数据for(int i =0; i < G->arcnum;++i){//在无向图中没有规定谁是弧头谁是弧尾
VertexType v1;
VertexType v2;//输入弧尾与弧头printf("Please input trail and front:");scanf("%d,%d",&v1,&v2);//定位int trail =LocateVex(*G,v1);int front =LocateVex(*G,v2);//若有顶点不在图中if(front==-1||trail ==-1){printf("No find vertex!!");return0;}//将正确的弧数据加入到邻接矩阵中,并且无向图是对称矩阵
G->arcs[trail][front].adj =1;
G->arcs[front][trail].adj =1;}return1;}
七:创建无向网
intCreatUDN_M(MGraph* G){//输入图中顶点个数与边的个数printf("Please input the num of vexs and arc:");scanf("%d,%d",&(G->vexnum),&(G->arcnum));getchar();//输入顶点数据printf("Please input the data of vex:\n");for(int i =0; i < G->vexnum;++i){scanf("%d",&(G->vexs[i]));getchar();}//初始化邻接矩阵为0for(int i =0; i < G->vexnum;++i){for(int j =0; j < G->vexnum;++j){
G->arcs[i][j].adj = INFINITY;
G->arcs[i][j].info =NULL;}}//确定头尾和边上的权值for(int i =0; i < G->arcnum;++i){
VertexType v1,v2;//v1为尾,v2为头
VRType m;//表示当前以v1为尾,v2为头的弧上面的权值printf("Please input the trail , head and value:");scanf("%d,%d,%d",&v1,&v2,&m);int row =LocateVex(*G,v1);//尾int col =LocateVex(*G,v2);//头//判断是否存在if(row ==-1||col ==-1){return0;}
G->arcs[row][col].adj = m;
G->arcs[col][row].adj = m;}return1;}
八:获取第n个顶点的值
/**
* 返回第n个结点的值
* @param G
* @param order
* @return
*/
VertexType GetVexValue_M(MGraph G,int order){if(order>=1&& order<=G.vexnum){//图中的结点是从1开始的return G.vexs[order-1];//在数组中需要进行减一操作}return-1;}
九:对顶点v进行赋值
/**
* 对顶点v进行赋值操作
* @param G
* @param v 顶点值为v
* @param value 待赋的值
* @return
*/intPutVex_M(MGraph* G,VertexType v,VertexType value){//遍历图中存储节点的数组for(int i =0; i < G->vexnum;++i){if(G->vexs[i]= v){
G->vexs[i]= value;return1;}}return0;}
十:将顶点v插入到图中(但是没有插入弧或边)
/**
* 将顶点v插入到图中
* @param G
* @param v
* @return
*/intInsertVex_M(MGraph* G,VertexType v){//判断顶点的数量是否已经到达最大值if(G->vexnum >= MAX_VERTEX_NUM){return0;}//判断是图还是网int sign;if(G->kind%2==1){
sign = INFINITY;//网}else{
sign =0;}//将顶点v加入到顶点数组中
G->vexnum++;
G->vexs[G->vexnum-1]= v;//给邻接矩阵加一行和一列for(int i =0; i < G->vexnum;++i){
G->arcs[G->vexnum-1][i].adj = sign;
G->arcs[i][G->vexnum-1].adj = sign;}return1;}
十一:删除顶点v
/**
* 删除顶点v
* 思路:
* 删除顶点主要有三部分操作
* 操作顶点数组,当删除完顶点之后要将后面顶点前移一位
* 操作邻接矩阵,对应行和列上的数据要清除并将后续行列的数据前移
* 修改顶点数和边数
* 注意区分有向图和无向图边数的修改
* @param G
* @param v
* @return
*/intDeleteVex_M(MGraph* G,VertexType v){int index =LocateVex(*G,v);if(index ==-1){return0;//待删顶点不在图中}//删除顶点for(int i = index; i <G->vexnum-1;++i){
G->vexs[i]= G->vexs[i+1];}//顶点数组的最后一位置为0
G->vexs[G->vexnum-1]=0;//统计与待删除结点相接的边数int rowcount =0;int colcount =0;int sign;if(G->kind%2==1){
sign = INFINITY;//网}else{
sign =0;}for(int i =0; i < G->vexnum;++i){if(G->arcs[index][i].adj != sign){
rowcount++;}}for(int i =0; i < G->vexnum;++i){if(G->arcs[i][index].adj != sign){
colcount++;}}int adjsnum;if(G->kind ==0|| G->kind){//如果是有向图或者是有向网
adjsnum = rowcount+colcount;}elseif(G->kind ==2|| G->kind ==3){//因为无向图或者无向网的邻接矩阵是对称的,所以需要除2
adjsnum =(rowcount+colcount)/2;}//处理行for(int j = index; j < G->vexnum-1;++j){for(int i =0; i < G->vexnum;++i){
G->arcs[j][i]= G->arcs[j+1][i];}}//处理列for(int i = index; i < G->vexnum-1;++i){for(int j =0; j < G->vexnum;++j){
G->arcs[j][i]= G->arcs[j][i+1];}}//顶点数减一,边数减少
G->vexnum--;
G->arcnum = G->arcnum - adjsnum;return1;}
十二:深度优先遍历
/**
* 寻找第一个与下标为index的顶点相邻的顶点的下标
* @param G
* @param index
* @return 相邻顶点在数组中的下标
*/intFirstAdjVex(MGraph G,int index){int sign;if(G.kind%2==1){//表示网,有权值
sign = INFINITY;}else{
sign =0;}for(int i =0; i < G.vexnum;++i){if(sign!=G.arcs[index][i].adj){return i;}}return-1;}/**
*
* @param G
* @param indexV 访问顶点的下标
* @param indexW 相对顶点的下标
* @return
*/intNextAdjVex(MGraph G,int indexV,int indexW){int sign;if(G.kind%2==1){
sign = INFINITY;}else{
sign =0;}for(int i = indexW+1; i <G.vexnum ;++i){if(G.arcs[indexV][i].adj != sign){return i;}}return-1;}voidvisitVex(MGraph G,int index){printf("%d\t",G.vexs[index]);}//全局变量
bool visited[MAX_VERTEX_NUM];//访问标志数组/**
* 深度优先遍历思想为:
* 从图中的某起始顶点v开始,访问与v相邻但是并未被访问的下一顶点w1,在访问与w1相邻但是未被访问的顶点
* w2。。。。重复上述过程,当不能够将继续向下访问的时候,则依次回退到最近被访问的顶点,若它还有邻接
* 顶点没有被访问,则从该顶点开始继续上述搜索。直到图中的所有顶点都被访问
* 显然这是一个递归的过程,那么在遍历过程中要容易辨别定点是否被访问,则需要设置一个全局变量标志数组visited,
* 来表示该顶点是否已经被访问。
*
* @param G
*/voidDFSTraverse(MGraph G){//首先初始化访问表示数组for(int i =0; i < G.vexnum;++i){
visited[i]= false;//初始为false,表示没有被访问}for(int i =0; i < G.vexnum;++i){if(!visited[i]){//如果尚未被访问DFS(G,i);}}}/**
* 深度优先遍历核心算法
* @param G
* @param v //顶点在数组中的下标
*/voidDFS(MGraph G,int v){//访问当前顶点
visited[v]= true;visitVex(G,v);int w;for(w =FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){//这边需要想明白if(!visited[w]){DFS(G,w);}}}
十三:广度优先遍历
/**
* 寻找第一个与下标为index的顶点相邻的顶点的下标
* @param G
* @param index
* @return 相邻顶点在数组中的下标
*/intFirstAdjVex(MGraph G,int index){int sign;if(G.kind%2==1){//表示网,有权值
sign = INFINITY;}else{
sign =0;}for(int i =0; i < G.vexnum;++i){if(sign!=G.arcs[index][i].adj){return i;}}return-1;}/**
*
* @param G
* @param indexV 访问顶点的下标
* @param indexW 相对顶点的下标
* @return
*/intNextAdjVex(MGraph G,int indexV,int indexW){int sign;if(G.kind%2==1){
sign = INFINITY;}else{
sign =0;}for(int i = indexW+1; i <G.vexnum ;++i){if(G.arcs[indexV][i].adj != sign){return i;}}return-1;}voidvisitVex(MGraph G,int index){printf("%d\t",G.vexs[index]);}//全局变量
bool visited[MAX_VERTEX_NUM];//访问标志数组/**
* 广度优先遍历
* @param G
*/voidBFSTraverse(MGraph G){//初始化标记数组for(int i =0; i < G.vexnum;++i){
visited[i]= false;}int queue[20];//用来模仿队列int rear =0;int top =0;for(int v =0; v < G.vexnum;++v){if(!visited[v]){
visited[v]= true;visitVex(G,v);//访问
queue[rear]= G.vexs[v];//将顶点加入到队列中
rear =(rear+1)%20;while(rear-top !=0){//当队列不为空时int u = queue[top];
top =(top+1)%20;//出队列一个顶点
u =LocateVex(G,u);//获取顶点在数组中的下标for(int w =FirstAdjVex(G,u); w >=0; w =NextAdjVex(G,u,w)){if(!visited[w]){
visited[w]= true;visitVex(G,w);
queue[rear]= G.vexs[w];
rear =(rear+1)%20;}}}}}}