邻接矩阵和邻接表的对比
之前一篇文章我们学习了 图的邻接矩阵和DFS遍历, 邻接矩阵对于图来说是一种很不错的存储结构,但是也有特殊的情况,例如边数很少的时候。
此时的邻接矩阵,只有(v0,v1)和(v1, v0)有值,其他都是0或无穷。然而,所以对于邻接矩阵来说,其它的空间都被浪费掉了,图中结点数很少的时候,影响不大,但是对于结点数多,且边数少的时候,性能影响就明显了。所以我们可以考虑另外一种方式,使用链表的方式来存储图结构,也就是 邻接表
邻接表
邻接表采用数组和链表结合的方式存储,具体的定义和处理看下图例子:
1. 无向图的邻接表定义
2. 有向图的邻接表定义
代码实现无向图邻接表的建立和DFS遍历
#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 100
int visited[MAXVEX];
//边表结点
typedef struct EdgeNode{
int adjvex; //结点下标
int weight; //结点权值
struct EdgeNode *next; //next指针
} EdgeNode;
//顶点表结点
typedef struct VertexNode{
int data; //顶点域
EdgeNode *firstedge; // 边表指针
} VertexNode, AdjList[100];
//图的邻接表结构
typedef struct {
AdjList adjList;
int maxVertexes, numEdge; //顶点数和边数
} Graph;
void createALGraph(Graph *G){
int i, j;
EdgeNode *e;
printf("输入顶点数和边数:");
scanf("%d%d", &G->maxVertexes, &G->numEdge);
//输入顶点
for(i = 0; i < G->maxVertexes; i++){
scanf("%d", &G->adjList[i].data);
G->adjList[i].firstedge = NULL;
}
//输入边
printf("输入边(i, j)上的顶点:\n");
for(int k = 0; k < G->numEdge; k++){
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;
}
}
void DFS(Graph *G, int i){
EdgeNode *p;
visited[i] = 1;
printf("%d", G->adjList[i].data);
p = G->adjList[i].firstedge;
while(p){
if(!visited[p->adjvex]){
DFS(G, p->adjvex);
}
p = p->next;
}
}
void DFSTraverse(Graph *G){
int i;
for(i = 0; i < G->maxVertexes; i++){
visited[i] = 0;
}
for(i = 0; i < G->maxVertexes; i++){
if(!visited[i]){
DFS(G, i);
}
}
}
int main(){
Graph G;
createALGraph(&G);
DFSTraverse(&G);
}
结果如下: