数据结构--实验三:图的出度入度

一、使用邻接矩阵

#include <stdio.h>
#include <stdlib.h>
#define INFINITY 65535  //∞设为65535
#define MAXVERTEXNUM 100  //最大顶点数设为100 

typedef struct GNode *PtrToGNode;
struct GNode{
	int Nv;   //顶点数 
	int Ne;   //边数 
	int G[MAXVERTEXNUM][MAXVERTEXNUM];  //邻接矩阵
	char Data[MAXVERTEXNUM]; 
}; 
typedef PtrToGNode MGraph; //以邻接矩阵存储的图类型

MGraph BuildGraph()
{
	MGraph Graph;
	int i,j,k,weight;
	char a,b;
	 
	Graph = (PtrToGNode)malloc(sizeof(struct GNode));
	
	printf("请输入顶点数和边数:");
	scanf("%d %d",&Graph->Nv,&Graph->Ne);
	
	for(i = 0;i < Graph->Nv; i++)
	{
	    getchar();  //getchar()函数是输入一个字符,用此函数将scanf()未处理的量进行释放;
	    printf("请输入第%d个顶点,数组位置为%d:",i+1,i);
	    scanf("%c",&Graph->Data[i]);  //输入顶点数据 
	}
	
	for(i = 0;i < Graph->Nv; i++)
	   for(j = 0;j < Graph->Nv; j++)
	        Graph->G[i][j] = INFINITY;  //初始化邻接矩阵
			
	for(k = 0;k < Graph->Ne ; k++)
	{
	    printf("请输入第%d条边的顶点信息与边的权值(格式为:起点数据 终点数据 权重):",k+1);
	    getchar();
	    scanf("%c %c %d",&a,&b,&weight);
	       
	    for( i = 0; Graph->Data[i] != a;i++) 
		   ;   //找到顶点a在邻接矩阵中的下标 
	    for( j = 0; Graph->Data[j] != b;j++) 
		   ;   //找到顶点b在邻接矩阵中的下标
	       
	    Graph->G[i][j] = weight;
	    Graph->G[j][i] = weight;
	}
	return Graph; 
 } 

//统计边的个数 
int NeNum(MGraph Gr){
	int number=0;
	
	for(int i=0;i<Gr->Nv;i++){
		for(int j=0;j<Gr->Nv;j++){
			if(Gr->G[i][j]!=INFINITY){
				number++;
			}
		}
	}
	return number/2;
}

//统计图中各顶点的度并输出
void PrintDeg(MGraph Gr){
	
	for(int i=0;i<Gr->Nv;i++){
		int number=0;
		for(int j=0;j<Gr->Nv;j++){

			if(Gr->G[i][j]!=INFINITY){
				number++;
			}	
		}
		
		printf("顶点%c的度为%d\n",Gr->Data[i],number);
	}
} 
//统计网图的总权重 
int MTWeight(MGraph Gr){
	int number=0;
	
	for(int i=0;i<Gr->Nv;i++){
		for(int j=0;j<Gr->Nv;j++){
			if(Gr->G[i][j]!=INFINITY){
				number+=Gr->G[i][j];
			}
		}
	}
	return number/2;
}
//统计度为n的顶点个数
int WeightN(MGraph Gr,int N){
	int number=0;
	
	for(int i=0;i<Gr->Nv;i++){
		for(int j=0;j<Gr->Nv;j++){
			if(Gr->G[i][j]==N){
				number++;
			}
		}
	}
	return number;
} 

int main(){
	MGraph Gr=BuildGraph();
	
	int n; 
	n=NeNum(Gr);
	printf("该图的边数为:%d\n",n);
	PrintDeg(Gr);
	
	n= MTWeight(Gr);
	printf("该图的总权重为:%d\n",n);
	
	 
	int m;
	printf("输入度:");
	scanf("%d",&m);
	n=WeightN(Gr,m);
	printf("度为%d的顶点为:%d\n",m,n);
}

二、使用邻接表

#include <stdio.h>
#include <stdlib.h>
#define MAXVERTEXNUM 100 

//枚举图的种类 DG表示有向图, AG为无向图 
typedef enum { DG=1,AG} GraphKind ;

//邻接点的定义
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
	int AdjV;  //邻接点的下标
    PtrToAdjVNode Next;   //指向下一个邻接点的指针 
}; 

//顶点表头结点的定义
typedef struct VNode{
	char Data;  //顶点数据 
	PtrToAdjVNode FisrtEdge;  //边表头指针 
}AdjList[MAXVERTEXNUM];   //AdjList是邻接表类型 

typedef struct GNode *PtrToGNode;
struct GNode{
	GraphKind kind;
	int Nv;  //顶点数 
	int Ne;  //边数
	AdjList G;  //邻接表 
};

typedef PtrToGNode LGraph;  //以邻接表方式存储的图类型

LGraph BuildGraph()
{
	int v,i,k,j;
	LGraph Graph;
	PtrToAdjVNode NewNode;
	
	Graph = (LGraph)malloc(sizeof(struct GNode));
	
	printf("输入图的类型,1表示有向图(DG),2表示无向图(AG) :\n");
    scanf("%d",&Graph->kind);
    
    printf("输入顶点数和边数:\n");
    scanf("%d %d",&Graph->Nv,&Graph->Ne);
    
    //输入顶点信息
	printf("输入顶点信息:\n");
    for(v = 0;v < Graph->Nv; v++){
        getchar();
        scanf("%c",&Graph->G[v].Data);
        Graph->G[v].FisrtEdge = NULL;    //将指向边表的指针初始化 
    } 
    
    //建立边表
	char vi,vj;
	printf("输入边<vi,vj>中的顶点vi,vj:\n"); 
    for(k = 0;k < Graph->Ne; k++){  //k记录插入边的个数 
    	getchar();
        scanf("%c %c",&vi,&vj);
        
        for(i = 0; Graph->G[i].Data != vi; i++)  ;//找vi在顶点数组中的下标 
        for(j = 0; Graph->G[j].Data != vj; j++)  ;//找vj在顶点数组中的下标
        
        //为vj建立新的邻接点 
        NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
        NewNode->AdjV = j;    
        NewNode->Next = Graph->G[i].FisrtEdge;         //头插法插入边结点 
        Graph->G[i].FisrtEdge = NewNode;

        //下面代码有向图无,无向图有 
        if(Graph->kind == AG){
        	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
            NewNode->AdjV = i;    
            NewNode->Next = Graph->G[j].FisrtEdge;         //头插法插入边结点 
            Graph->G[j].FisrtEdge = NewNode;
		}  
    }
	return Graph;
} 

//打印邻接表
void outputG(LGraph Graph)
{
	PtrToAdjVNode p;
	printf("邻接表为:\n");
    int i;
    for(i = 0;i < Graph->Nv; i++){
        p = Graph->G[i].FisrtEdge;
        printf("%c ",Graph->G[i].Data);
		while(p){
			printf("->");
            printf(" <%c,%c> ",Graph->G[i].Data,Graph->G[p->AdjV].Data);
            p = p->Next;
        }
        printf("\n");
    } 
}
//统计边的个数 
int NeNum(LGraph Gr){
	int number=0;
	for(int i=0;i<Gr->Nv;i++){
		PtrToAdjVNode ptr=Gr->G[i].FisrtEdge;
		while(ptr!=NULL){
			number++;
			ptr=ptr->Next;
		}
	}
	
	if(Gr->kind==DG) return number;
	else return number/2;
}

//统计各顶点的出度
int *outdeg(LGraph Gr){
	int t[MAXVERTEXNUM];
	for(int i=0;i<Gr->Nv;i++){
		t[i]=0;	
	}
	
	for(int i=0;i<Gr->Nv;i++){
		int number=0;
		PtrToAdjVNode ptr=Gr->G[i].FisrtEdge;
		while(ptr!=NULL){
			number++;
			ptr=ptr->Next;
		}
		t[i]=number;
	}
	return t;
} 
//统计个顶点的入度 
int *indeg(LGraph Gr){
	int t5[MAXVERTEXNUM];
	for(int i=0;i<Gr->Nv;i++){
		t5[i]=0;	
	}
	for(int i=0;i<Gr->Nv;i++){
//		int number=0;
		PtrToAdjVNode ptr=Gr->G[i].FisrtEdge;
		while(ptr!=NULL){
			t5[ptr->AdjV]++;
			ptr=ptr->Next;
		}
//		t[i]=number;
	}
	return t5;
}

//统计出度为n的顶点个数
int outdegN(LGraph Gr,int N){
	int *t2;
	t2=outdeg(Gr);
	
	int number=0;
	for(int i=0;i<Gr->Nv;i++){
		if(t2[i]==N){
			number++;
		}
	}
	return number;
} 
//统计入度为n的顶点个数 
int indegN(LGraph Gr,int N){
	int *t3;
	t3=indeg(Gr);
	
	int number=0;
	for(int i=0;i<Gr->Nv;i++){
		if(t3[i]==N){
			number++;
		}
	}
	return number;
} 

int main(){
	LGraph Gr=BuildGraph();
	printf("统计图中边的个数并输出:");
	int N=NeNum(Gr);
	printf("%d\n",N);
	
	//各顶点的出度
	int *t2;
	t2=outdeg(Gr);
	for(int i=0;i<Gr->Nv;i++){
		printf("顶点%c的出度为:%d\n",Gr->G[i].Data,t2[i]);
	}
	int *t3;
	t3=indeg(Gr);
	for(int i=0;i<Gr->Nv;i++){
		printf("顶点%c的入度为:%d\n",Gr->G[i].Data,t3[i]);
	}
	
	
	//统计出度为n的顶点数
	int n;
	printf("请输入要统计的出度:");
	scanf("%d",&n);
	printf("出度为%d的节点数为:%d\n",n,outdegN(Gr,n));
	//统计入度为n的定点数 
	printf("请输入要统计的入度:");
	scanf("%d",&n);
	printf("入度为%d的节点数为:%d\n",n,indegN(Gr,n));
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值