数据结构:不带权有向图的邻接矩阵和邻接表储存及求出入度实现

14.假设不带权有向图采用邻接矩阵G存储,设计实现以下功能的算法。

(1) 求出图中每个顶点的入度。

(2)求出图中每个顶点的出度。

(3)求出图中出度为0的顶点数。

15. 假设不带权有向图采用邻接表G存储,设计实现以下功能的算法。

(1) 求出图中每个顶点的入度。

(2)求出图中每个顶点的出度。

(3)求出图中出度为0的顶点数。

#include <stdio.h>
#include <stdlib.h>

#define MAX_V 5
#define INF  2147483647

//图的邻接矩阵结构
typedef struct
{
	int No;                    //顶点编号
	char info;                 //顶点信息,这里用作顶点名
} Ver;
typedef struct                 //图的邻接矩阵结构
{
	int adjMat[MAX_V][MAX_V];  //邻接矩阵
	int v;                     //点的个数
	int e;                     //边的个数
	Ver ver[MAX_V];            //顶点数组用于盛放顶点信息
} MatGraph;

//图的邻接表结构
typedef struct edgeNode     //邻接表边节点
{
	int adjVNo;             //邻接点编号∵题目规定为不带权图∴不设权值的空间
	struct edgeNode *next;  //下一条边的指针
} ENode;
typedef struct
{
	char info;              //顶点信息,这里用作顶点名
	ENode * first;          //邻接表中边节点链表的头指针,指向第一个边节点
} VNode;                    //邻接表头结点,也是顶点类型
typedef struct 
{
	VNode Ver[MAX_V];       //邻接表头结点数组,也是顶点数组
	int v;                  //点的个数
	int e;                  //边的个数
} AdjGraph;

void CreateMat(MatGraph *&G,int A[MAX_V][MAX_V],int v,int e)  //创建图的邻接矩阵
{
	int i,j;
	G=(MatGraph*)malloc(sizeof(MatGraph));
	for(i=0;i<v;i++)
	{
		G->ver[i].No=i;        //给节点编号
		G->ver[i].info='A'+i;  //这里节点信息域作为节点名,赋上A,B,C...字母
	}
	for(i=0;i<v;i++)
		for(j=v-1;j>=0;j--)
			G->adjMat[i][j]=A[i][j];
	G->e=e;
	G->v=v;
}

void CreateAdj(AdjGraph *&G,int A[MAX_V][MAX_V],int v,int e)  //创建图的邻接表
{
	int i,j;
	ENode* p=NULL;
	G=(AdjGraph*)malloc(sizeof(AdjGraph));
	for(i=0;i<v;i++)
	{
		G->Ver[i].first=NULL;
		G->Ver[i].info='A'+i;  //这里节点信息域作为节点名,赋上A,B,C...字母
	}
	for(i=0;i<v;i++)
		for(j=v-1;j>=0;j--)
			if(A[i][j]!=0 && A[i][j]!=INF)
			{
				p=(ENode*)malloc(sizeof(ENode));
				p->adjVNo=j;
				p->next=G->Ver[i].first;       //头插法
				G->Ver[i].first=p;
			}
	G->e=e;
	G->v=v;
}

void DispAdj(AdjGraph *G)     //图的邻接表存储方式输出
{
	int i;
	ENode *p;
	printf("图的邻接表存储\n");
	for(i=0;i < G->v;i++)
	{
		p=G->Ver[i].first;
		printf("编号%d的顶点%c:",i,G->Ver[i].info);
		while(p!=NULL)
		{
			printf("%d→",p->adjVNo);  //没有权,这里的链表只输出邻接顶点编号
			p=p->next;
		}
		printf("NULL\n");
	}

}



void DispMat(MatGraph *G)  //图的邻接矩阵存储方式输出
{
	int i,j;
	printf("\n图的邻接矩阵存储\n");
	for(i=0;i < G->v;i++)
	{
		printf("编号%d的顶点%c:",G->ver[i].No,G->ver[i].info);
		for(j=0;j < G->v;j++)
			printf("%d ",G->adjMat[i][j]);  //没有权,这里的链表只输出邻接顶点编号
		printf("\n");
	}
}

void MatInDegree(MatGraph *G) //图的邻接矩阵存储方式求各顶点入度
{
	int i,j,count;            //count为顶点的人度
	for(i=0;i < G->v;i++)
	{
		count=0;
		printf("编号%d的顶点%c的入度为:",G->ver[i].No,G->ver[i].info);
		for(j=0;j < G->v;j++)
			if(G->adjMat[j][i]==1)
				count++;
		printf("%d\n",count);
	}
}

void MatOutDegree(MatGraph *G)  //图的邻接矩阵存储方式求各顶点出度
{
	int i,j,count;              //count为顶点的出度
	for(i=0;i < G->v;i++)
	{
		count=0;
		printf("编号%d的顶点%c的出度为:",G->ver[i].No,G->ver[i].info);
		for(j=0;j < G->v;j++)
			if(G->adjMat[i][j]==1)
				count++;
		printf("%d\n",count);
	}
}

void MatZeroOutDegree(MatGraph *G)  //图的邻接矩阵存储方式求出度为0的顶点个数
{
	int i,j,count=0;          //count为出度顶点的个数
	for(i=0;i < G->v;i++)
	{
		for(j=0;j < G->v;j++)
			if(G->adjMat[i][j]==1)
				break;
		if(j==G->v)           //j==G->v说明邻接矩阵该行没有为1的值,既出度为0
			count++;
	}
	printf("出度为0的顶点个数为%d\n",count);
}

void AdjInDegree(AdjGraph *G) //图的邻接表存储方式求各顶点入度
{
	int i,j,count;            //count为顶点的人度
	ENode *p;
	for(i=0;i < G->v;i++)     //共G->v个节点
	{
		count=0;
		printf("编号%d的顶点%c入度为:",i,G->Ver[i].info);
		for(j=0;j < G->v;j++) //对每个节点都要遍历图的所有边
		{
			p=G->Ver[j].first;
			while(p!=NULL)
			{
				if(p->adjVNo==i)  //如果边节点的邻接顶点为现在要找的顶点,既当前正在遍历的顶点为该边终点时
					count++;      //则入度+1
				p=p->next;
			}
		}
		printf("%d\n",count);
	}
}

void AdjOutDegree(AdjGraph *G)   //图的邻接表存储方式求各顶点出度
{
	int i,count;       //count为顶点的出度
	ENode *p;
	for(i=0;i < G->v;i++)
	{
		p=G->Ver[i].first;
		count=0;
		printf("编号%d的顶点%c出度为:",i,G->Ver[i].info);
		while(p!=NULL)
		{
			count++;
			p=p->next;
		}
		printf("%d\n",count);
	}
}

void AdjZeroOutDegree(AdjGraph *G)   //图的邻接表存储方式求出度为0的顶点个数
{
	int i,count=0;    //count为出度顶点的个数
	ENode *p;
	for(i=0;i < G->v;i++)
	{
		if(G->Ver[i].first==NULL)
			count++;
	}
	printf("出度为0的顶点个数为%d\n",count);
}




int main()
{
	int adj_mat[MAX_V][MAX_V]=
	{                      //图的形状:
		{0,1,0,1,0},       //        1
		{0,0,1,1,0},       //     ↙↓↖
		{0,0,0,1,1},       //    2→ 3←0
		{0,0,0,0,0},       //     ↘↑↗
		{1,0,0,1,0}        //        4
	};
	int v=5,e=8;	
	MatGraph* MG=NULL;
	AdjGraph* AG=NULL;
	CreateMat(MG,adj_mat,v,e);
	CreateAdj(AG,adj_mat,v,e);
	DispAdj(AG);
	DispMat(MG);
	printf("\n14.图的邻接矩阵存储方式");
	printf("  (1)\n    ");
	MatInDegree(MG);
	printf("  (2)\n    ");
	MatOutDegree(MG);
	printf("  (3)\n    ");
	MatZeroOutDegree(MG);
	printf("\n15.图的邻接表存储方式");
	printf("  (1)\n    ");
	AdjInDegree(AG);
	printf("  (2)\n    ");
	AdjOutDegree(AG);
	printf("  (3)\n    ");
	AdjZeroOutDegree(AG);
	return 0;
}





  • 13
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"一、实验目的和要求 " "(1)掌握图的相关概念,包括图,有向图,无向图,完全图,子图,连通图,度,入 " "度,度,简单回路和环等定义。 " "(2)重点掌握图的各种存储结构,包括邻接矩阵邻接表等。 " "(3)重点掌握图的基本运算,包括创建图,输图,深度优先遍历,广度优先遍历等 " "。 " "(4)掌握图的其他运算 ,包括最小生成树,最短路径,拓扑排序和关键路径等算法。" "(5)灵活运用图这种数据结构解决一些综合应用问题。 " "二、实验内容和方法 " "(1)实验内容: " "1、编写一个程序algo8-1.cpp,实现不带权图和带权图的邻接矩阵邻接表的相互转换" "算法、输邻接矩阵邻接表的算法,并在此基础上设计一个程序exp8-1.cpp实现如下" "功能: " " 建立如图1所示有向图G的邻接矩阵,并输; " " 由有向图G的邻接矩阵产生邻接表,并输; " " 再由 的邻接表产生对应的邻接矩阵,并输。 " " " " " " " " " " " " " " " " " "图1 " " " " " "2、编写一个程序algo8-2.cpp,实现图的遍历运算,并在此基础上设计一个程序exp8-2" ".cpp完成如下功能: " " 输图1所示有向图G从顶点0开始的深度优先遍历序列(递归算法); " " 输图1所示有向图G从顶点0开始的深度优先遍历序列(非递归算法); " " 输图1所示有向图G从顶点0开始的广度优先遍历序列。 " " " "3、设计一个程序exp8-3.cpp,采用邻接表存储图,并输图8.1(a)中从指定顶点1 " "发的所有深度优先遍历序列。 " " " "(2)实验方法: " "1、综合运用课本所学的知识,用不同的算法实现在不同的程序功能。 " "2、结合指导老师的指导,解决程序中的问题,正确解决实际中存在的异常情况,逐步 " "改善功能。 " "3、根据实验内容,编译程序。 " " " "三、实验环境: " "Windows 7,Visual C++6.0 " "三、实验过程描述 " "文件graph.h中定义了图的邻接矩阵表示类型和邻接表表示类型,该头文件在以下三个 " "实验中都会使用到。其代码如下: " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "实验 " "源程序。 " "一、输入如下所示程序; " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "二、编译并链接程序; " " " "三、运行程序,结果如下图: " " " " " "实验 " "源程序 " "一、输入如下所示程序; " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
好的,我很乐意回答你的问题。首先,让我们来了解一下有向图邻接矩阵邻接表存储结构。 有向图邻接矩阵存储结构是用一个二维数组来表示图中各个顶点之间的关系。其中,数组的行和列坐标对应于图中的各个顶点,数组元素的值表示两个顶点之间是否存在一条有向边,也可以表示边的权值。如果顶点 i 和顶点 j 之间存在一条边,则数组元素 a[i][j] 的值为 1 或非零值;如果不存在一条边,则 a[i][j] 的值为 0。 有向图邻接表存储结构是利用链表来存储图中各个顶点之间的关系。具体来说,每个顶点对应一个链表链表中存储该顶点所指向的顶点列表。这个过程可以用一个数组和多个链表实现,其中数组中的每个元素都对应一个链表。 接下来,让我们来实现两种遍历运算和简单路径求解: 1. 深度优先遍历(DFS):从起点发,尽可能深地探索每一个分支,直到该路径不能继续为止。然后回溯到前一个节点,继续探索其他分支。 2. 广度优先遍历(BFS):从起点发,按照距离由近及远的顺序依次访问每个顶点,直到遍历完所有的顶点为止。 3. 简单路径求解:在有向图中,简单路径是指不包含重复边和重复顶点的路径。简单路径求解算法可以使用深度优先遍历或广度优先遍历来实现。 以上就是有关有向图邻接矩阵邻接表存储结构以及遍历运算和简单路径求解的一些基本知识和算法。希望这能对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值