邻接表无向图

邻接表无向图的介绍

邻接表无向图是指通过邻接表表示的无向图。

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

#define MAX 100
#define isLetter(a)  ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
#define LENGTH(a)  (sizeof(a)/sizeof(a[0]))

// 邻接表中表对应的链表的顶点
typedef struct _ENode
{
	int ivex;                   // 该边所指向的顶点的位置
	struct _ENode *next_edge;   // 指向下一条弧的指针
}ENode, *PENode;

// 邻接表中表的顶点
typedef struct _VNode
{
	char data;              // 顶点信息
	ENode *first_edge;      // 指向第一条依附该顶点的弧
}VNode;

// 邻接表
typedef struct _LGraph
{
	int vexnum;             // 图的顶点的数目
	int edgnum;             // 图的边的数目
	VNode vexs[MAX];
}LGraph;


/*
* 返回ch在matrix矩阵中的位置
*/
static int get_position(LGraph g, char ch)
{
	int i;
	for (i = 0; i<g.vexnum; i++)
		if (g.vexs[i].data == ch)
			return i;
	return -1;
}

/*
* 读取一个输入字符
*/
static char read_char()
{
	char ch;

	do {
		ch = getchar();
	} while (!isLetter(ch));

	return ch;
}

/*
* 将node链接到list的末尾
*/
static void link_last(ENode *list, ENode *node)
{
	ENode *p = list;

	while (p->next_edge)
		p = p->next_edge;
	p->next_edge = node;
}

/*
* 创建邻接表对应的图(自己输入)
*/
LGraph* create_lgraph()
{
	char c1, c2;
	int v, e;
	int i, p1, p2;
	ENode *node1, *node2;
	LGraph* pG;

	// 输入"顶点数"和"边数"
	printf("input vertex number: ");
	scanf("%d", &v);
	printf("input edge number: ");
	scanf("%d", &e);
	if (v < 1 || e < 1 || (e >(v * (v - 1))))
	{
		printf("input error: invalid parameters!\n");
		return NULL;
	}

	if ((pG = (LGraph*)malloc(sizeof(LGraph))) == NULL)
		return NULL;
	memset(pG, 0, sizeof(LGraph));

	// 初始化"顶点数"和"边数"
	pG->vexnum = v;
	pG->edgnum = e;
	// 初始化"邻接表"的顶点
	for (i = 0; i<pG->vexnum; i++)
	{
		printf("vertex(%d): ", i);
		pG->vexs[i].data = read_char();
		pG->vexs[i].first_edge = NULL;
	}

	// 初始化"邻接表"的边
	for (i = 0; i<pG->vexnum; i++)
	{
		// 读取边的起始顶点和结束顶点
		printf("edge(%d): ", i);
		c1 = read_char();
		c2 = read_char();

		p1 = get_position(*pG, c1);
		p2 = get_position(*pG, c2);
		// 初始化node1
		node1 = (ENode*)malloc(sizeof(ENode));
		node1->ivex = p2;
		// 将node1链接到"p1所在链表的末尾"
		if (pG->vexs[p1].first_edge == NULL)
			pG->vexs[p1].first_edge = node1;
		else
			link_last(pG->vexs[p1].first_edge, node1);
		// 初始化node2
		node2 = (ENode*)malloc(sizeof(ENode));
		node2->ivex = p1;
		// 将node2链接到"p2所在链表的末尾"
		if (pG->vexs[p2].first_edge == NULL)
			pG->vexs[p2].first_edge = node2;
		else
			link_last(pG->vexs[p2].first_edge, node2);
	}

	return pG;
}

/*
* 创建邻接表对应的图(用已提供的数据)
*/
LGraph* create_example_lgraph()
{
	char c1, c2;
	char vexs[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
	char edges[][2] = {
		{ 'A', 'C' },
		{ 'A', 'D' },
		{ 'A', 'F' },
		{ 'B', 'C' },
		{ 'C', 'D' },
		{ 'E', 'G' },
		{ 'F', 'G' } };
	int vlen = LENGTH(vexs);
	int elen = LENGTH(edges);
	int i, p1, p2;
	ENode *node1, *node2;
	LGraph* pG;


	if ((pG = (LGraph*)malloc(sizeof(LGraph))) == NULL)
		return NULL;
	memset(pG, 0, sizeof(LGraph));

	// 初始化"顶点数"和"边数"
	pG->vexnum = vlen;
	pG->edgnum = elen;
	// 初始化"邻接表"的顶点
	for (i = 0; i<pG->vexnum; i++)
	{
		pG->vexs[i].data = vexs[i];
		pG->vexs[i].first_edge = NULL;
	}

	// 初始化"邻接表"的边
	for (i = 0; i<pG->vexnum; i++)
	{
		// 读取边的起始顶点和结束顶点
		c1 = edges[i][0];
		c2 = edges[i][1];

		p1 = get_position(*pG, c1);
		p2 = get_position(*pG, c2);
		// 初始化node1
		node1 = (ENode*)malloc(sizeof(ENode));
		node1->ivex = p2;
		// 将node1链接到"p1所在链表的末尾"
		if (pG->vexs[p1].first_edge == NULL)
			pG->vexs[p1].first_edge = node1;
		else
			link_last(pG->vexs[p1].first_edge, node1);
		// 初始化node2
		node2 = (ENode*)malloc(sizeof(ENode));
		node2->ivex = p1;
		// 将node2链接到"p2所在链表的末尾"
		if (pG->vexs[p2].first_edge == NULL)
			pG->vexs[p2].first_edge = node2;
		else
			link_last(pG->vexs[p2].first_edge, node2);
	}

	return pG;
}

/*
* 打印邻接表图
*/
void print_lgraph(LGraph G)
{
	int i, j, k;
	ENode *node;

	printf("List Graph:\n");
	for (i = 0; i < G.vexnum; i++)
	{
		printf("%d(%c): ", i, G.vexs[i].data);
		node = G.vexs[i].first_edge;
		while (node != NULL)
		{
			printf("%d(%c) ", node->ivex, G.vexs[node->ivex].data);
			node = node->next_edge;
		}
		printf("\n");
	}
}

void main()
{
	LGraph* pG;

	// 自定义"图"(自己输入数据)
	//pG = create_lgraph();
	// 采用已有的"图"
	pG = create_example_lgraph();

	// 打印图
	print_lgraph(*pG);
}

上面的图G1包含了"A,B,C,D,E,F,G"共7个顶点,而且包含了"(A,C),(A,D),(A,F),(B,C),(C,D),(E,G),(F,G)"共7条边。

上图右边的矩阵是G1在内存中的邻接表示意图。每一个顶点都包含一条链表,该链表记录了"该顶点的邻接点的序号"。例如,第2个顶点(顶点C)包含的链表所包含的节点的数据分别是"0,1,3";而这"0,1,3"分别对应"A,B,D"的序号,"A,B,D"都是C的邻接点。就是通过这种方式记录图的信息的。

猜你喜欢

转载自blog.csdn.net/qq_40061421/article/details/81635717