注:若有错误或要改善的地方请告之,谢谢,新手上路,有些函数还是很冗余的,慢慢改进。
头文件:
#define MAXSIZE 100
typedef enum
{
NN,
NY,
YN,
YY
}MGragh_type;
/*************结构体************/
/*邻接矩阵*/
typedef struct
{
char vex[MAXSIZE]; //顶点表
int edge[MAXSIZE][MAXSIZE]; //边表
int vexnum,arcnum;
int MGragh_type;
}MGragh;
/*************图的操作****************/
/*初始化图*/
MGragh *init_MGragh()
{
MGragh *m;
m=(MGragh*)malloc(sizeof(MGragh));
m->arcnum=m->vexnum=0;
printf("请输入选择的图的类型 1、无向图 2、无向网 3、有向图 4、有向网:");
scanf("%d",&m->MGragh_type);
memset(m->edge,0,sizeof(m->edge));
memset(m->vex,'#',sizeof(m->vex));
return m;
}
/*返回结点在结点表的编号*/
int return_vexno(MGragh m,char e)
{
int i;
for(i=0;i<m.vexnum;i++)
{
if(m.vex[i]==e)
{
return i;
}
}
return -1;
}
/*返回结点的出度*/
int return_vex_out(MGragh m,char a)
{
int an=return_vexno(m,a);
int i,num=0;
for(i=0;i<m.vexnum;i++)
{
if(m.edge[an][i]>0)
{
num++;
}
}
return num;
}
/*判断结点是否在结点表中*/
bool if_vex_in(MGragh m,char e)
{
int i;
for(i=0;i<m.vexnum;i++)
{
if(m.vex[i]==e)
{
return true;
}
}
return false;
}
/*判断边是否已经存在*/
bool if_arc_in(MGragh m,int xn,int yn) //xn,yn是结点在结点表的编号
{
if(m.edge[xn][yn]>0)
{
return true;
}
return false;
}
/*创建无向图*/
void create_MGragh_NN(MGragh *m)
{
int V,E,i,xn,yn;
char x,y;
printf("创造无向图\n请输入结点数与边数:");
scanf("%d%d",&V,&E);
printf("请依次输入头尾结点:\n");
for(i=0;i<E;i++)
{
fflush(stdin);
scanf("%c %c",&x,&y);
fflush(stdin);
if(!if_vex_in(*m,x))
{
m->vex[m->vexnum++]=x;
}
if(!if_vex_in(*m,y))
{
m->vex[m->vexnum++]=y;
}
xn=return_vexno(*m,x);
yn=return_vexno(*m,y);
if(if_arc_in(*m,xn,yn)||if_arc_in(*m,yn,xn))
{
continue;
}
m->edge[xn][yn]=m->edge[yn][xn]=1;
m->arcnum++;
}
}
/*创建无向网*/
void create_MGragh_NY(MGragh *m)
{
int V,E,i,xn,yn,c;
char x,y;
printf("创造无向网\n请输入结点数与边数:");
scanf("%d%d",&V,&E);
printf("请依次输入头尾结点与权值:\n");
for(i=0;i<E;i++)
{
fflush(stdin);
scanf("%c %c %d",&x,&y,&c);
fflush(stdin);
if(!if_vex_in(*m,x))
{
m->vex[m->vexnum++]=x;
}
if(!if_vex_in(*m,y))
{
m->vex[m->vexnum++]=y;
}
xn=return_vexno(*m,x);
yn=return_vexno(*m,y);
if(if_arc_in(*m,xn,yn)||if_arc_in(*m,yn,xn))
{
continue;
}
m->edge[xn][yn]=m->edge[yn][xn]=c;
m->arcnum++;
}
}
/*创建有向图*/
void create_MGragh_YN(MGragh *m)
{
int V,E,i,xn,yn;
char x,y;
printf("创造有向图\n请输入结点数与边数:");
scanf("%d%d",&V,&E);
printf("请依次输入头尾结点:\n");
for(i=0;i<E;i++)
{
fflush(stdin);
scanf("%c %c",&x,&y);
fflush(stdin);
if(!if_vex_in(*m,x))
{
m->vex[m->vexnum++]=x;
}
if(!if_vex_in(*m,y))
{
m->vex[m->vexnum++]=y;
}
xn=return_vexno(*m,x);
yn=return_vexno(*m,y);
if(if_arc_in(*m,xn,yn))
{
continue;
}
m->edge[xn][yn]=1;
m->arcnum++;
}
}
/*创建有向网*/
void create_MGragh_YY(MGragh *m)
{
int V,E,i,xn,yn,c;
char x,y;
printf("创造有向网\n请输入结点数与边数:");
scanf("%d%d",&V,&E);
printf("请依次输入头尾结点与权值:\n");
for(i=0;i<E;i++)
{
fflush(stdin);
scanf("%c %c %d",&x,&y,&c);
fflush(stdin);
if(!if_vex_in(*m,x))
{
m->vex[m->vexnum++]=x;
}
if(!if_vex_in(*m,y))
{
m->vex[m->vexnum++]=y;
}
xn=return_vexno(*m,x);
yn=return_vexno(*m,y);
if(if_arc_in(*m,xn,yn))
{
continue;
}
m->edge[xn][yn]=c;
m->arcnum++;
}
}
/*创造图*/
void create_MGragh(MGragh *m)
{
switch(m->MGragh_type)
{
case 1:create_MGragh_NN(m);break;
case 2:create_MGragh_NY(m);break;
case 3:create_MGragh_YN(m);break;
case 4:create_MGragh_YY(m);break;
}
}
/*输出图*/
void print_MGragh(MGragh m)
{
int i,j;
printf("该图的邻接矩阵为:\n");
for(i=0;i<m.vexnum;i++)
{
for(j=0;j<m.vexnum;j++)
{
printf("|%d|",m.edge[i][j]);
}
printf("\n");
}
printf("该图的顶点表为:");
for(i=0;i<m.vexnum;i++)
{
printf("%c",m.vex[i]);
}
printf("\n");
printf("该图的顶点数为%d,边数为%d\n",m.vexnum,m.arcnum);
}
图的应用:
#include<stdlib.h>
#include<stdio.h>
#include<string>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<ctype.h>
#include"../../头文件/image_seq.h"
using namespace std;
int tohead[MAXSIZE]; //祖先数组,tohead[x]=y,编号为y的字符是编号为x的字符的祖先
bool visited[MAXSIZE][MAXSIZE]; //visited[][]为边访问标记
bool visited_node[MAXSIZE]; //为结点的标记
/******************公共函数********************/
/*初始化visited_node[]*/
void init_visited_node(MGragh m)
{
int i;
for(i=0;i<m.vexnum;i++)
{
visited_node[i]=false;
}
}
/*判断图是否还有未被访问的与其连接的下一结点*/
/*若存在,则返回权值最小权值的头尾结点的编号(xn,yn)与权值min_*/
bool if_exist_next_node(MGragh m,int &xn,int &yn,int &min_)
{
int i,j;
min_=INT_MAX;
for(i=0;i<m.vexnum;i++)
{
for(j=0;j<m.vexnum;j++)
{
if(m.edge[i][j]>0&&m.edge[i][j]<min_&&!visited_node[j]&&visited_node[i]) //j要未访问过,i要访问过
{
min_=m.edge[i][j];
xn=i;
yn=j;
}
}
}
if(min_!=INT_MAX)
{
return true;
}
else
{
xn=yn=min_=0;
return false;
}
}
/*初始化visited[][]*/
void init_visited()
{
memset(visited,false,sizeof(visited)); //false为未访问
}
/*寻找权值最小且未访问的结点的编号*/
void min_edge(MGragh m,int &xn,int &yn) //需预先初始化visited[][]
{
int i,j,min_=INT_MAX;
for(i=0;i<m.vexnum;i++)
{
for(j=0;j<m.vexnum;j++)
{
if(m.edge[i][j]<min_&&!visited[i][j]&&m.edge[i][j]>0)
{
xn=i;
yn=j;
min_=m.edge[i][j];
}
}
}
visited[xn][yn]=true;
}
/*输出访问标记边*/
void print_visited(MGragh m)
{
int i,j;
printf("该图的访问标记为:\n");
for(i=0;i<m.vexnum;i++)
{
for(j=0;j<m.vexnum;j++)
{
printf("|%d|",visited[i][j]);
}
printf("\n");
}
}
/******************并查集*******************/
/*初始化tohead[]*/
/*初始化设置各个结点的祖先为自己*/
void init_tohead()
{
int i;
for(i=0;i<MAXSIZE;i++)
{
tohead[i]=i;
}
}
/*找出结点的祖先*/
int find_(int x) //x为结点的编号
{
if(tohead[x]==x)
{
return x;
}
else
{
return tohead[x]=find_(tohead[x]);
}
}
/*将两结点的祖先合并*/
void union_(int x,int y)
{
x=find_(x);
y=find_(y);
tohead[x]=y;
}
/********************最小生成树(MST)**********************/
/*Kruskal*/
/*选边*/
int Kruskal(MGragh m) //使用并查集
{
init_tohead();
init_visited(); //为min_edge()设定的
int xn,yn,i,vil=0;
for(i=0;i<m.arcnum;i++)
{
min_edge(m,xn,yn);
if(find_(xn)!=find_(yn))
{
vil+=m.edge[xn][yn];
union_(xn,yn);
}
}
printf("(kruskal)该图的最小生成树的权值为%d\n",vil);
print_visited(m);
return vil;
}
/*prim*/
/*选点*/
int prim(MGragh m) //不使用并查集
{
init_visited_node(m);
int vexnum=1,headnum=0,i,j,xn,yn,vilue,num=0,min_=INT_MAX;
for(headnum=0;headnum<m.vexnum;headnum++)
{
visited_node[headnum]=true;
while(vexnum<m.vexnum)
{
if(!if_exist_next_node(m,xn,yn,vilue))
{
break;
}
num+=vilue;
visited_node[yn]=true;
vexnum++;
}
if(vexnum>=m.vexnum)
{
min_=min(min_,num);
}
num=0;
vexnum=1;
init_visited_node(m);
}
printf("(prim)该图的最小生成树权值为%d\n",min_);
return min_;
}
/***********************最短路径***************************/
/*dijkstra*/
/*单源最短路径*/
void dijkstra(MGragh m,char x) //x为头结点
{
printf("(dijkstra)该图从%c到其余各点的最短路径为:\n",x);
int xn=return_vexno(m,x);
int i,j;
for(i=0;i<m.vexnum;i++)
{
for(j=0;j<m.vexnum;j++)
{
if(m.edge[xn][j]>(m.edge[xn][i]+m.edge[i][j])&&m.edge[xn][j]>0&&m.edge[xn][i]>0&&m.edge[i][j]>0)
{
m.edge[xn][j]=m.edge[xn][i]+m.edge[i][j];
}
}
}
print_MGragh(m);
}
/*floryd*/
/*多源最短路径*/
void floryd(MGragh m) //不改变图
{
printf("(floryd)该图的最短路径为:\n");
int i,j,k; //k为插入的结点
for(k=0;k<m.vexnum;k++)
{
for(i=0;i<m.vexnum;i++)
{
for(j=0;j<m.vexnum;j++)
{
if(m.edge[i][j]>(m.edge[i][k]+m.edge[k][j])&&m.edge[i][j]>0&&m.edge[i][k]>0&&m.edge[k][j]>0)
{
m.edge[i][j]=m.edge[i][k]+m.edge[k][j];
}
}
}
}
print_MGragh(m);
}
int main()
{
MGragh *m;
m=init_MGragh();
create_MGragh(m);
print_MGragh(*m);
prim(*m);
return 0;
}
/*
a c 3
a d 8
a b 5
c d 10
d a 7
d b 20
a c
a d
a b
c d
d a
d b
*/