2023/4/9总结

邻接表

1.邻接表是一种由数组和链表相结合的存储方法,它的存在主要也是为了避免空间的浪费,比如当我们在存储一个边数相对顶点较少的图时,采用邻接矩阵来存储,是十分浪费内存空间的,因为邻接矩阵的空间开辟是根据顶点的个数来开辟一个n*n的二维数组,边少的话就会导致大部分空间都没有使用但是却开辟固定了。

比如下图:

2023/4/9总结_第1张图片

2.而邻接表是采用数组加链表的形式,相当于动态存图,对于一个点到另一个点之间构成的边,只需要在这个点后面连接另一个点则代表从v到u构成了一条边。如图:

2023/4/9总结_第2张图片

3.邻接表中定义一个结构体数组用于存放顶点,包含一个数据域存储顶点的信息,一个指针域指向边表(一个单链表,)的第一个节点。

typedef struct VertexNode//顶点表节点 
{
	VertexNode data;
	EdgeNode *firstedge;
}VertexNode,AdjList[MAX];

4.由于邻接点的个数不定,所以边表是一个单链表,边表节点中每个节点包含一个数据域存储该顶点对应的下标,一个链域指向下一个邻接点或者我们还可以开辟一个数据域用于存储每条边的权值。

typedef struct EdgeNode//边表节点 
{
	int adjvex;//编号 
	//int info; //权值 
	struct EdgeNode *next;
}EdgeNode;

 5.邻接表的创建就是根据输入的顶点然后再根据输入边的两个顶点然后建立边表,这其实就是一个单链表的头插法。

以下是无向图邻接表的建立(对于无向图,一条边都是对应两个顶点,所以在循环中,针对i和j分别进行了插入,如果是有向图,将后面对j的插入删除即可):

#include"stdio.h"
#define 1000005 MAX
typedef struct EdgeNode//边表节点 
{
	int adjvex;//编号 
	//int info; //权值 
	struct EdgeNode *next;
}EdgeNode;

typedef struct VertexNode//顶点表节点 
{
	VertexNode data;
	EdgeNode *firstedge;
}VertexNode,AdjList[MAX];

typedef struct//图表 
{
	AdjList adjList;
	int numNodes,numEdges;//点数和边数 
}GraphAdjList;

void CreateALGraph(GraphAdjList *G)
{
	int i,j,k;
	EdgeNode *e;
	scanf("%d %d",&G->numNodes,&G->numEdges);
	for(i=0;inumNodes;i++)
	{
		scanf("%d",&G->adjList[i].data);//输入顶点信息
		G->adjList[i].firstedge=NULL; //边表置空 
	}
	for(k=0;knumEdges;k++) //建立边表
	{
		printf("输入边(vi,uj)上的顶点编号:\n");
		scanf("%d %d",&i,&j);
		e=(EdgeNode *)malloc(sizeof(EdgeNode));
		e->adjvex=j;
		e->next=G->adjList[i].firstedge;
		G->adjList[i].firstedge=e;
		e=(EdgeNode *)malloc(sizeof(EdgeNode));
		e->adjvex=i;
		e->next=G->adjList[j].firstedge;
		G->adjList[j].firstedge=e;
	 } 
}

6.本算法的时间复杂度,对n个顶点e条边来说,容易得出O(n+e)。 

7.写了两个用了邻接表的题,附上题解:

 P5318 【深基18.例3】查找文献_Repeat715的博客-CSDN博客

 P3916 图的遍历_Repeat715的博客-CSDN博客

你可能感兴趣的:(数据结构,链表,算法)