C语言实现邻接表(无向图的链式表示)

本文介绍了如何使用C语言构建邻接表来表示无向图,包括定义结构体、初始化、插入顶点和边、打印输出、删除边和顶点以及销毁图的操作。在调试阶段,未初始化的指针会被自动填充特定值以方便调试。此外,文章详细讲解了插入边时的双向插入过程,并展示了邻接表的动态变化。
摘要由CSDN通过智能技术生成


V1顶点后面链着的是与他相连的边的序号(第i个单链表后的结点表示依附于顶点Vi的边)
这是一个无向图,所以邻接表一共有12条边
在这里插入图片描述

定义结构体

在这里插入图片描述
每个单链表的第一个结点存放有关顶点的信息,把这个结点看做链表的表头,其余节点存放有关的信息

#define Default_Vertex_Size 10
#define T  char

typedef struct Edge//其余结点形成的边表
{
   
	int dest;//与当前结点相邻的顶点的序号
	struct Edge *link;//指向下一个边结点的指针
}Edge;

typedef struct Vertex//单链表的表头形成的顶点表
{
   
	T data;//顶点信息
	Edge *adj;//指向第一个边结点的指针
}Vertex;

typedef struct GraphLnk
{
   
	int MaxVertices;
	int NumVertices;
	int NumEdges;

	Vertex *NodeTable;
}GraphLnk;

初始化

void InitGraph(GraphLnk *g)
{
   
	g->MaxVertices = Default_Vertex_Size;
	g->NumEdges = g->NumVertices = 0;
	
	g->NodeTable = (Vertex*)malloc(sizeof(Vertex) * g->MaxVertices);
	assert(g->NodeTable != NULL);
	for(int i=0; i<g->MaxVertices; ++i)
	{
   
		g->NodeTable[i].adj = NULL;
	}
}

在这里插入图片描述
在这里插入图片描述

对于0xcccccccc和0xcdcdcdcd,
在 Debug 模式下,VC 会把未初始化的栈内存上的指针全部填成 0xcccccccc ,当字符串看就是 “烫烫烫烫……”;
会把未初始化的堆内存上的指针全部填成 0xcdcdcdcd,当字符串看就是 “屯屯屯屯……”。
那么调试器为什么要这么做呢?VC的DEBUG版会把未初始化的指针自动初始化为0xcccccccc或0xcdcdcdcd,而不是就让取随机值,那是为了方便我们调试程序,如果野指针的初值不确定,那么每次调试同一个程序就可能出现不一样的结果,比如这次程序崩掉,下次却能正常运行,这样显然对我们解bug是非常不利的,所以自动初始化的目的是为了让我们一眼就能确定我们使用了未初始化的野指针了。

插入顶点

void InsertVertex(GraphLnk *g, T v)
{
   
	if(g->NumVertices >= g->MaxVertices)
		return;
	g->NodeTable[g->NumVertices++].data = v;
}

在这里插入图片描述

插入边

在这里插入图片描述

//获取顶点的位置
int  GetVertexPos(GraphLnk *g, T v)
{
   
	for(int i=0; i<g->NumVertices; ++i)
	{
   
		if(g->NodeTable[i].data == v)
			return i;
	}
	return -1;
}


void InsertEdge(GraphLnk *g, T vertex1, T vertex2)
{
   
	int v1 = GetVertexPos(g,vertex1)
邻接表是一种图的存储结构,可以用来表示稀疏图。下面是一个用C语言实现邻接表存储的示例代码: ```c #include <stdio.h> #include <stdlib.h> struct AdjListNode { int dest; struct AdjListNode* next; }; struct AdjList { struct AdjListNode* head; }; struct Graph { int V; struct AdjList* array; }; struct AdjListNode* newAdjListNode(int dest) { struct AdjListNode* newNode = (struct AdjListNode*)malloc(sizeof(struct AdjListNode)); newNode->dest = dest; newNode->next = NULL; return newNode; } struct Graph* createGraph(int V) { struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph)); graph->V = V; graph->array = (struct AdjList*)malloc(V * sizeof(struct AdjList)); int i; for (i = 0; i < V; ++i) { graph->array[i].head = NULL; } return graph; } void addEdge(struct Graph* graph, int src, int dest) { struct AdjListNode* newNode = newAdjListNode(dest); newNode->next = graph->array[src].head; graph->array[src].head = newNode; newNode = newAdjListNode(src); newNode->next = graph->array[dest].head; graph->array[dest].head = newNode; } void printGraph(struct Graph* graph) { int v; for (v = 0; v < graph->V; ++v) { struct AdjListNode* pCrawl = graph->array[v].head; printf("\n Adjacency list of vertex %d\n head ", v); while (pCrawl) { printf("-> %d", pCrawl->dest); pCrawl = pCrawl->next; } printf("\n"); } } int main() { int V = 5; struct Graph* graph = createGraph(V); addEdge(graph, 0, 1); addEdge(graph, 0, 4); addEdge(graph, 1, 2); addEdge(graph, 1, 3); addEdge(graph, 1, 4); addEdge(graph, 2, 3); addEdge(graph, 3, 4); printGraph(graph); return 0; } ``` 这个示例代码创建了一个包含5个顶点的无向图,然后使用邻接表存储这个图,并最终输出它的邻接表。在这个示例代码中,我们首先定义了三种结构体:`AdjListNode`、`AdjList`和`Graph`。其中,`AdjListNode`表示邻接表中的一个节点,包括目标节点的编号和指向下一个节点的指针;`AdjList`表示一个节点的邻接表,包括指向第一个节点的指针;`Graph`表示整个图,包括顶点数和一个指向邻接表数组的指针。 接下来,我们定义了一些函数来操作这些结构体,包括`newAdjListNode`用于创建一个新的邻接表节点,`createGraph`用于创建一个新的图,`addEdge`用于向图中添加一条边,`printGraph`用于输出图的邻接表。 在`main`函数中,我们首先创建了一个包含5个顶点的图,然后添加了7条边,最后输出了这个图的邻接表。 以上就是一个简单的使用C语言实现邻接表存储的示例代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值