图的邻接矩阵和邻接表表示法

链表是一种线性存储结构,是一对一对应关系。而树是一种层次存储结构,是一对多的对应关系。而图则是一种关系存储结构,是多对多对应关系。树和图类似于数据库中的层次模型和关系模型。图的存储结构主要有两种,分别为邻接矩阵和邻接表法,其中邻接表较难,但本质相同,都是记录结点与其邻接结点,只是方法不同而已。下面分别讨论邻接表和邻接矩阵的思想。邻接表的思想是:定义三个结点,分别为表结点,头结点,邻接表结点,表结点存放与头结点相邻的结点序号,边的权值,以及下一个表结点。头结点中存放结点的真实值(char 或 int),和该结点的第一个邻接点。邻接表中存放的是头结点数组,结点数和边数。通过动态申请空间的方法给每个头结点创建邻接结点链表,这样就构造除了邻接表。而邻接矩阵则是通过采用一个邻接矩阵来记录邻接结点,当不相连时值为无穷大(自行定义的一个极大的数据)。在这里,我们规定:所讨论的图中任意两个结点之间最多有一条边,且无向图中顶点到其自身没有边(有向图可允许顶点到顶点有边),否则下面的算法会有相应的问题,(邻接矩阵就不可用了,邻接表就会有冗余数据了),下面是代码:

//图的存储结构
//邻接表
#include <stdio.h>
#include <stdlib.h>
#define Max 100 //顶点个数最多为100个
typedef char type;
typedef struct Arcnode{
	int index;
	int value;
	struct Arcnode *next;
}Arcnode,*parc;
typedef struct Node{
	type data;
    Arcnode *first;
}Node;
typedef struct Grap{
	Node nodetex[Max];
	int n; //顶点数
	int m; //边数
}Grap,*pgrap;
int Located(pgrap g,char ch){
	for(int i=0;i<g->n;i++)
		if(ch==g->nodetex[i].data)
			return i;
}
void Creat_grap(pgrap g){
	printf("输入图的结点数和边数:\n");
	scanf("%d%d",&g->n,&g->m);
	getchar();
	int i,index1,index2,value;
	char ch1,ch2;
	printf("输入各顶点:\n");
	for(i=0;i<g->n;i++){
	g->nodetex[i].data=getchar();
	g->nodetex[i].first=NULL;
	getchar();
	}
	printf("输入各边及权值:\n");	
	parc q;
	for(i=0;i<g->m;i++){
		scanf("%c,%c,%d",&ch1,&ch2,&value);
		getchar();
		index1=Located(g,ch1);
		index2=Located(g,ch2);
		q=(parc)malloc(sizeof(Arcnode));
		q->index=index2;
		q->value=value;
		q->next=g->nodetex[index1].first;
		g->nodetex[index1].first=q;
		//无向图(默认为任意两个顶点之间之多有一条边且

自身到自身无边)
		/*q=(parc)malloc(sizeof(Arcnode));
		q->index=index1;
		q->value=value;
		q->next=g->nodetex[index2].first;
		g->nodetex[index2].first=q;*/
	}
}
void Show_grap(pgrap g){
	printf("图中各顶点的邻接顶点为:\n");
	for(int i=0;i<g->n;i++){
		printf("%c:",g->nodetex[i].data);
		parc q=g->nodetex[i].first;
		while(q){
			putchar(g->nodetex[q->index].data);
			q=q->next;
		}
		printf("\n");
	}
}
void Delete_grap(pgrap g){
	parc p,q;
	for(int i=0;i<g->n;i++){
		p=g->nodetex[i].first;
		while(p){
			q=p->next;
			free(p);
			p=q;
		}
	}
}
int main(){
	Grap g;
	pgrap p=&g;
	Creat_grap(p);
	Show_grap(p);
	Delete_grap(p);
	return 0;
}

测试数据://无向图

输入图的结点数和边数:
5 7
输入各顶点:
A
B
C
D
E
输入各边及权值:
A,B,20
A,C,10
B,D,50
A,D,40
B,E,60
C,D,30
D,E,70
图中各顶点的邻接顶点为:
A:DCB
B:EDA
C:DA
D:ECAB
E:DB




Terminated with return code 0
Press any key to continue ...


输入图的结点数和边数://有向图
4 6
输入各顶点:
A
B
C
D
输入各边及权值:
A,B,10
B,A,10
A,A,20
A,C,30
C,D,40
D,B,50
图中各顶点的邻接顶点为:
A:CAB
B:A
C:D
D:B

下面是邻接矩阵代码:

//图的邻接矩阵表示法
#include <stdio.h>
#include <stdlib.h>
#define Max 100
#define Inf 0x1111
typedef char type;
typedef struct Grap{
	type data[Max];
	int value[Max][Max];
	int n,m;
}Grap,*pgrap;
int Located(pgrap g,char ch){
	for(int i=0;i<g->n;i++)
		if(g->data[i]==ch)
			return i;
}
void Creat_grap(pgrap g){
	printf("输入图的顶点数和边数:\n");
	scanf("%d%d",&g->n,&g->m);
	//printf("ksgfdkj\n");
	getchar();
	printf("输入图中的顶点:\n");
	int i,j;
	for(i=0;i<g->n;i++){
		g->data[i]=getchar();
		getchar();
	}
	for(i=0;i<g->n;i++)
		for(j=0;j<g->n;j++)
			g->value[i][j]=Inf;
	printf("请输入图中的边:\n");
	int index1,index2,value;
	char ch1,ch2;
	while(g->m--){
		scanf("%c,%c,%d",&ch1,&ch2,&value);
	    getchar();
		index1=Located(g,ch1);
		index2=Located(g,ch2);
		g->value[index1][index2]=value;
		//无向图
		//g->value[index2][index1]=value;
	}
}
void Show_grap(pgrap g){
	printf("邻接矩阵表示法个顶点的邻接顶点:\n");
	int i,j;
	for(i=0;i<g->n;i++){
		printf("%c:",g->data[i]);
		for(j=0;j<g->n;j++)
			if(g->value[i][j]!=Inf)
				putchar(g->data[j]);
		printf("\n");
	}
}
int main(){
	Grap g;
	pgrap p=&g;
	Creat_grap(p);
	Show_grap(p);
	return 0;
}


	
		

	

下面是测试数据://无向图

输入图的顶点数和边数:
5 7
输入图中的顶点:
A
B
C
D
E
请输入图中的边:
A,B,20
A,C,10
B,D,50
A,D,40
B,E,60
C,D,30
D,E,70
邻接矩阵表示法个顶点的邻接顶点:
A:BCD
B:ADE
C:AD
D:ABCE
E:BD

Terminated with return code 0
Press any key to continue ...


输入图的顶点数和边数: //有向图
4 6
输入图中的顶点:
A
B
C
D
请输入图中的边:
A,B,10
B,A,10
A,A,20
A,C,30
C,D,40
D,B,50
邻接矩阵表示法个顶点的邻接顶点:
A:ABC
B:A
C:D
D:B


Terminated with return code 0
Press any key to continue ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值