邻接矩阵求有向图各顶点的入度和出度 (图论基础)

要求一个有向图各顶点的入度和出度:

先用一个二维数组Edge存储表示邻接矩阵,输入文件中顶点的序号是从1开始,当输入一条有向边<u, v>时,将Edge[u-1][v-1] = 1就得啦;

第i+1个顶点的出度等于邻接矩阵中第i行所有元素中元素值为1的个数,把第i行所有元素值累加起来,得到的结果也是该顶点的出度,同理,在计算第i+1个顶点的入度时,也只需要将第i列所有元素值累加起来就可以了;


n, m 分别表示有向图的顶点个数和有向边,n = m = 0时处理文件结束; (0 < n, m <= 100)


测试样例:

7 9

1 2

2 3

2 5

2 6

3 5

4 3

5 2

5 4

6 7

0 0


运行结果:

该有向图各顶点的入度分别为:1 3 1 1 2 1 0
该有向图各顶点的出度分别为:0 2 2 1 2 1 1


简单代码如下:(邻接矩阵实现)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 105
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;

int n, m, Edge[MAXN][MAXN];  //顶点数,有向边数,邻接矩阵;
int Mc, Md, u, v;  //入度,出度,边的起点,终点;

void Init()  //初始化;
{
	RST(Edge);
	for(int i=1; i<=m; i++) {  //添加有向边;
		scanf("%d %d", &u, &v);
		Edge[u-1][v-1] = 1;
	}
}

void Print_In_Degree()  //输出有向图各顶点的入度;
{
	printf("该有向图各顶点的入度分别为:");
	for(int i=0; i<n; i++) {
		Mc = 0;
		for(int j=0; j<n; j++) Mc += Edge[i][j];
		printf("%d", Mc);
		i == n-1 ? printf("\n") : printf(" ");
	}
}

void Print_Out_Degree()  //输出有向边各顶点的出度;
{
	printf("该有向图各顶点的出度分别为:");
	for(int i=0; i<n; i++) {
		Md = 0;
		for(int j=0; j<n; j++) Md += Edge[j][i];
		printf("%d", Md);
		i == n-1 ? printf("\n") : printf(" ");
	}
}

int main()
{
	freopen("data.in", "r", stdin);
	freopen("data.out", "w", stdout);
	while(~scanf("%d %d", &n, &m) && n || m) {
		Init();
		Print_In_Degree(), Print_Out_Degree();
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

邻接表实现:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 105
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;

struct ArcNode   //边节点; 
{
	int rvex;   //有向边的另一个邻接点的序号; 
	ArcNode *nextarc;   //指向下一个边节点的指针; 
};

struct VNode   //顶点; 
{
	int data;    //定点信息; 
	ArcNode *head1; // 出边表的表头指针; 
	ArcNode *head2; // 入边表的表头指针; 
};

struct LGraph   //图的邻接表存储结构; 
{
	VNode vertex[MAXN];  //顶点数组; 
	int VexNum, ArcNum;  //顶点数和边数; 
};

int u, v;   //有向边的前后顶点; 
LGraph Lg;  //图; 

void Init()  //初始化; 
{
	for(int i=0; i<Lg.VexNum; i++) {  //初始化表头指针为空; 
		Lg.vertex[i].head1 = Lg.vertex[i].head2 = NULL;
	}
}

void creatLG()  //采用邻接表存储表示,构造有向图G; 
{
	ArcNode *pi;   //用来构造边链表的边节点指针; 
	for(int i=0; i<Lg.ArcNum; i++) {
		scanf("%d %d", &u, &v);   //输出一条边的前后节点; 
		u--, v--;
		//将新节点插入出度链表; 
		pi = new ArcNode;   //为pi分配空间(如果有足够空间) 
		pi->rvex = v;
		pi->nextarc = Lg.vertex[u].head1;   //插入出边链表; 
		Lg.vertex[u].head1 = pi;
		//将新节点插入入度链表; 
		pi = new ArcNode;
		pi->rvex = u;
		pi->nextarc = Lg.vertex[v].head2;  //插入入边链表; 
		Lg.vertex[v].head2 = pi;
	}
}

void IN_DEGREE()   //输出每个顶点的出度; 
{
	ArcNode *pi;
	for(int i=0; i<Lg.VexNum; i++) {
		int res = 0;
		pi = Lg.vertex[i].head1;
		while(pi != NULL) {  //统计各顶点的出度; 
			res++;
			pi = pi->nextarc;
		}
		printf("%d", res);
		printf(i == Lg.VexNum-1 ? "\n" : " ");
	}	
}

void OUT_DEGREE()  //输出每个顶点的入度; 
{
	ArcNode *pi;
	for(int i=0; i<Lg.VexNum; i++) {
		int res = 0;
		pi = Lg.vertex[i].head2;
		while(pi != NULL) {  //统计各顶点的入度; 
			res++;
			pi = pi->nextarc;
		}
		printf("%d", res);
		printf(i == Lg.VexNum-1 ? "\n" : " ");
	}
}
//释放图G邻接表各顶点的边链表中所有边节点所占的存储空间;
void DeleteLG()   
{
	ArcNode *pi;   //用来指向边链表中各边节点的指针; 
	for(int i=0; i<Lg.VexNum; i++) {
		pi = Lg.vertex[i].head1;
		while(pi != NULL) {
			Lg.vertex[i].head1 = pi->nextarc;
			delete pi;    //释放第i个顶点的出边表各边节点所占的空间; 
			pi = Lg.vertex[i].head1;
		}
		pi = Lg.vertex[i].head2;
		while(pi != NULL) {
			Lg.vertex[i].head2 = pi->nextarc;
			delete pi;   //释放第i个顶点的入边表各边节点所占的空间; 
			pi = Lg.vertex[i].head2;
		}
	}
	return ;
}

int main()
{
	while(~scanf("%d %d", &Lg.VexNum, &Lg.ArcNum) && Lg.VexNum||Lg.ArcNum) {
		Init(), creatLG();
		IN_DEGREE(), OUT_DEGREE();
		DeleteLG(); 
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值