有向图和无向图的代码与存储方式和常见考法

存储方式:在这里介绍邻接表和邻接矩阵的结构,其他存储结构方式考的较少,不在这里一一赘述。

存储方式

邻接矩阵:

邻接矩阵即可存储无向图也可存储有向图,在稠密图中非常适用

结构体:

//邻接矩阵
struct MGraph{
	//储存的顶点表 
	char vex[MaxSize];
	//路径矩阵
	int edge[MaxSize][MaxSize];
	//存储顶点与边的个数
	int vexnum,arcnum;
};

带权结构体

//带权重的邻接矩阵
struct MGraphW{
	//储存的顶点表 
	char vex[MaxSize];
	//路径矩阵,只不过改成权重了 
	int weight[MaxSize][MaxSize];
	//存储顶点与边的个数
	int vexnum,arcnum;
};

邻接表:

邻接表既可存储有向图也可存储无向图,需要注意的是邻接表是不唯一的。因为链接到一个顶点的链表排序是可以不同的。

结构体:

//邻接表结构体
struct ArcNode{
   int adjvex; //指向顶点 
   struct archNode *next; //下一个节点位置 
   int weight; //权重 
};

struct VNode{
    char value; //顶点值 
	struct archNode *first; //指向的第一个节点 
};

struct AdGraph{
	VNode vertices[MaxSize]; //列表 
	int vexnum,arcnum; //顶点数和边数 
};

十字链表:

主要存储有向图,在这里不赘述,读者知道即可,感兴趣可以参考相关资料。

邻接多重表:

主要存储无相图,相关内容同上

使用邻接表和邻接矩阵创建图:

邻接矩阵存储有向图:

不带权重:

//创建有向图
MGraph createMGraphX(){
	//创建图 
	MGraph G;
	//输入边与顶点的个数
	scanf("%d,%d",&G.vexnum,&G.arcnum);
	//初始化邻接矩阵全部置零 
	for(int i=0;i<G.vexnum,i++){
		for(int j=0;j<G.vexnum,j++){
			G.edge[i][j] = 0;
		}
	} 
	//边的创立 
	int v1,v2;
	//输入有边的两个顶点 
	for(int i=0;i<G.arcnum;i++){
		scanf("%d,%d",&v1,&v2);
		G.edge[v1][v2] = 1;
	}
	return G;
} 

带权重:

//创建带权重的有向图
MGraphW createMGWX(){
	MGraphW G;
	scanf("%d,%d",&G.arcnum,&G.vexnum);
	for(int i=0;i<G.vexnum;i++){
		for(int j=0;j<G.vexnum;j++){
			G.weight[i][j] = INF;
		}
	}
	int a,b,w;
	for(int i=0;i<G.arcnum;i++){
		scanf("%d,%d,%d",&a,&b,&w);
		G.weight[a][b] = w;
	}
	return G;
} 

 邻接矩阵存储无向图:

不带权:

//创建无向图
MGraph createGraph(){
	MGraph G;
	scanf("%d,%d",&G.vexnum,&G.arcnum);
	for(int i=0;i<G.vexnum;i++){
		for(int j=0;j<G.vexnum;j++){
			G.edge[i][j]=0;
		}
	}
	int a,b;
	for(in i=0;i<G.arcnum;i++){
		scanf("%d,%d",&a,&b);
		G.edge[a][b] = 1;
		G.edge[b][a] = 1;
	}
	return G;
}

 带权:

//创建无向带权图 
MGraphW createMGW(){
	MGraphW G;
	scanf("%d,%d",&G.arcnum,&G.vexnum);
	for(int i=0;i<G.vexnum;i++){
		for(int j=0;j<G.vexnum;j++){
			G.weight[i][j] = INF;
		}
	}
	int a,b,w;
	for(int i=0;i<G.arcnum;i++){
		scanf("%d,%d,%d",&a,&b,&w);
		G.weight[a][b] = w;
		G.weight[b][a] = w; 
	}
	return G;
} 

邻接表(带权):

//创建邻接表
AdGraph createAdGraph(){
	//创建图 
	AdGraph G;
	//p代表前一个结点 q代表工作结点 
	ArcNode *p,*q;
	//三个变量 n代表节点的边数的个数 a代表顶点下标 w代表权重 
	int n,a,w;
	//输入总顶点数与边数
	scanf("%d,%d",&G.vexnum,&G.arcnum);
	//遍历输入
	for(int i=0;i<G.vexnum;i++){
		//输入点的值和此点的边数 
		scanf("%c,%d",&G.vertices[i].value,n);
		//设置起始顶点置空 
		G.vertices[i].first = NULL;
		//顶点链上边 
		for(int j=0;j<n;j++){
			q = (ArcNode*)malloc(sizeof(ArcNode));
			//输入指向的顶点 权重 
			scanf("%d,%d",&a,&w);
			q->adjvex = a;
			q->weight = w;
			//挂载结点 
			if(!G.vertices[i].first){
				G.vertices[i].first = q;
				p = q;
			}else{
				p->next = q;
				p = q;
			}
		}
		//置空工作节点,留给下一个结点
		p = NULL; 
	} 
	return G;
}

常见考法:

邻接矩阵求出度入度:

//求解顶点的入度与出度
int getInDegree(MGraph g,int v){
	int degree=0;
	for(int i=0;i<g.vexnum;i++){
		if(g.edge[i][v]!=0){
			degree++;
		}
	}
} 

int getOutDegree(MGraph g,int v){
	int degree=0;
	for(int i=0;i<g.vexnum;i++){
		if(g.edge[v][i]!=0)degree++;
	}
	return degree;
}

求邻接矩阵的边数:

//求解有向图的边数
int getEdgeNums(MGraph g){
	int edges = 0;
	for(int i=0;i<g.vexnum;i++){
		for(int j=0;j<g.vexnum;j++){
			if(g.edge[i][j]!=1)edges++;
		}
	}
	return edges;
} 

求邻接表的出度入度:

//求出度
int getOutDegreeFromAdGraph(AdGraph g,int v){
	int degree = 0;
	ArcNode *p = g.vertices[v].first;
	while(p){
		p = p->next;
		degree++;
	}
	return degree;
}

//求入度 
int getInDegreeFromAdGraph(AdGraph g,int v){
	int degree = 0;
	ArcNode *p = NULL;
	for(int i=0;i<g.vexnum;i++){
		p = g.vertices[i].first;
		while(p){
			if(p->adjvex == v)degree++;
			p = p->next;
		}
	}
	return degree;
}

邻接矩阵与邻接表之间的转化:

//邻接表 -> 邻接矩阵
MGraph AtoM(AdGraph g){
	MGraph m;
	m.arcnum = g.arcnum;
	m.vexnum = g.vexnum;
	for(int i=0;i<m.vexnum;i++){
		for(int j=0;j<m.vexnum;j++){
			m.edge[i][j] = 0;
		}
	}
	ArcNode *p = NULL;
	for(int i=0;i<vexnum;i++){
		p = g.vertices[i].first;
		while(p){
			int v = p->adjvex;
			m.edge[i][v]=1;
			p = p->next;
		}
	}
	return m;
}
//矩阵->表
AdGraph MtoA(MGraph g){
	AdGraph a;
	ArcNode *p,*q;
	a.arcnum = g.arcnum;
	a.vexnum = g.vexnum;
	for(int i=0;i<g.vexnum;i++){
		a.vertices[i].value = g.vex[i];
		a.vertices[i].first = NULL;
		for(int j=0;j<g.vexnum;j++){
			if(g.edge[i][j]!=0){
				q = (ArcNode*)malloc(sizeof(ArchNode));
				q->next = NULL;
				q->adjvex = g.vex[j];
				//权重
				q->weight = g.edge[i][j]; 
				if(a.vertices.first[i]==NULL){
					a.vertices.first[i] = q;
					p = q;
				}else{
					p->next = q;
					p = q
				}
			}
		}
	}
	return a;
} 

2012统考真题,是否存在EL路径:

int isExistEl(MGraph G){
	int n = 0,degree = 0;
	for(int i=0;i<G.vexnum;i++){
		degree = 0;
		for(int j=0;j<G.vexnum;j++){
			if(G.edge[i][j]!=0){
				degree++;
			}
		}
		if(degree%2!=0)n++;
	}
	if(n==0 || n==2)return 1;
	else return 0;
} 

以上代码仅供参考,如有错误恳请指正!谢谢~

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值