图的存储结构 --- 邻接表

来源:互联网 发布:魔兽世界种族寿命 知乎 编辑:程序博客网 时间:2024/06/05 16:56


图的邻接矩阵存储方式方便实现和操作,但是当遇到图为稀疏图的时候这种邻接矩阵的存储将大部分的存储空间都浪费掉了, 比如有5个顶点但是只有一条弧的稀疏图,他的存储只有一条信息是有用的,如下邻接矩阵的存储:



这个时候只有map[1][0] = 9, 其余的存储空间都没有被利用起来,这时候图的另外一种存储方式就显示出了巨大的优势,那就是图的邻接表存储方式。


邻接表是将一个一维数组和链表结合起来作为图的存储方式, 一维数组存储顶点信息, 顶点数组中每个元素都有一个指向第一个邻接顶点的指针,顶点的所有邻接顶点组成一个单链表。 如下所示为无向图的单链表存储方式:




从存储示意图可以看出来, 邻接表的每个顶点都有一个data域和一个指向第一个邻接顶点(其实任何一个邻接顶点都可以称之为第一个)域两部分组成, data域负责存储当前顶点的信息,而第一个邻接顶点域则是该顶点邻接表的第一个头结点。每一个邻接顶点域都包含一个自己顶点信息(自己在顶点数组中的下标)和一个next指针指向下一个邻接顶点。有了这样一个结构,我们想要知道两个节点是否相通则可以遍历对于顶点的链表看是否存在第二个节点即可,当然有向图只需要遍历起点顶点的链表,无向图则不用区分这些。说道有向图,我们要注意一点的是,有向图的邻接表存储都是用弧尾到弧首的放心进行存储,比如下面所示:



当然你也可以使用相反的方式存储,从弧首到弧尾进行逆向存储,我们称这种方式为逆邻接表存储方式,方法类似不在重复复述介绍,有兴趣的可以在纸上画画,很容易就能弄出来。下面看代码的具体实现:

typedef int EdgeType;typedef int VertexType;#define MAXVEERTEX 100typedef struct edge// 边表结点{int ver_index;// 邻接顶点域 说明邻接顶点在数组中的下标edge* next;// 下一个邻接顶点域}EdgeNode;typedef struct vertex// 顶点表结构{VertexType ver_noee;// 顶点信息EdgeNode* first_vertex;// 顶点链表}VertexNode, AdjList[MAXVEERTEX];typedef struct graph{AdjList list;int ver_num, edge_num;}Graph;void create_adjlist_graph(Graph* g){cout << "Input graph vertexs and edges :" << endl;cin >> g->ver_num >> g->edge_num;for (int i = 0; i < g->ver_num; i++){cout << " Input graph vertex info" << endl;cin >> g->list[i].ver_noee;g->list[i].first_vertex = NULL;}int val;VertexType vi, vj;EdgeNode* node = NULL;for (int i = 0; i < g->edge_num; i++){cout << "input vertex and edge info for example(vi vj x)" << endl;cin >> vi >> vj >> val;node = (EdgeNode*) malloc(sizeof(EdgeNode));if (node == NULL)  exit(0);node->ver_index = vj;node->next = g->list[vi].first_vertex;g->list[vi].first_vertex = node;node = (EdgeNode*) malloc(sizeof(EdgeNode));if (node == NULL)  exit(0);node->ver_index = vi;node->next = g->list[vj].first_vertex;g->list[vj].first_vertex = node;}}




0 0
原创粉丝点击