普通的数据结构教科书对邻接表的实现中规中矩,耶鲁大学教授James Aspnes的代码显得非常油菜花,而且运用了C语言的一个称为bug的特性,不检查数组越界。
选几小段分析一下:
struct successors{ int d; /* number of successors */ int len; /* number of slots in array */ char is_sorted; /* true if list is already sorted */ int list [1]; /* actual list of successors */ }; struct graph{ int n; /* number of vertices */ int m; /* number of edges */ struct successors *alist[1]; }; /* 由于VC不支持结构体的嵌套定义,我将struct successors从struct graph中抽取了出来 */ /* create a new graph with n vertices labeled 0..n-1 and no edges */ Graph graph_create(int n){ Graph g; int i; g = (Graph) malloc(sizeof(struct graph) + sizeof(struct successors *) * (n-1)); assert(g); g->n = n; g->m = 0; for(i = 0; i < n; i++){ g->alist[i] = (struct successors *) malloc(sizeof(struct successors)); assert(g->alist[i]); g->alist[i]->d = 0; g->alist[i]->len = 1; g->alist[i]->is_sorted = 1; } return g; }
struct successors *alist[1] 是一个数组,该数组的类型是指向struct successors的指针,数组的元素只有一个。
看到这里,也许你和我一样,心中有个隐隐约约的疑问,为什么只有一个元素???别着急,往下看。
在graph_create函数调用时,一切都明白了,原来上面定义的邻接表只能容纳一个顶点的指针(很重要),运行到malloc函数时,补齐了剩下的n-1个顶点的指针。在接下来的for循环中,将这些指针指向了新开辟的内存块。之所以这样写能工作,得益于
1. malloc开辟出逻辑连续的内存块。
2. C语言对数组越界不做检查。
再来看看添加边的函数
/* add an edge to an existing graph */ void grpah_add_edge(Graph g, int u, int v){ assert(u >= 0); assert(v >= 0); assert(u < g->n); assert(v < g->n); /* do we need to grow the list? */ while(g->alist[u]->d >= g->alist[u]->len){ g->alist[u]->len *= 2; g->alist[u] = (struct successors *)realloc(g->alist[u], sizeof(struct successors) + sizeof(int) * (g->alist[u]->len -1)); } /* now add the new sink */ g->alist[u]->list[g->alist[u]->d++] = v; g->alist[u]->is_sorted = 0; g->m++; }
这段代码同样利用了C语言不检查数组越界的特性。最终,该图在内存中的结构如下所示。
Successor下面的数字代表该顶点与哪些顶点相连接。
完整的源代码在这里:
http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Graphs.html
相关推荐
在“C语言数据结构邻接表课程设计”中,我们将深入探讨如何利用C语言实现数据结构中的邻接表,这是图论中一个重要的抽象概念。邻接表是表示图的有效方式,尤其对于稀疏图(边的数量远小于顶点数量的平方)来说,它的...
### 二、头歌数据结构图的邻接表存储 #### 1. 数据类型定义 - **顶点类型**:`VertexType` 定义为一个字符数组,用于存储顶点的名称。 - **图的种类**:`GraphKind` 定义了四种类型的图:有向图 (DG)、有向网 (DN)...
### 数据结构:图的邻接表存储 #### 一、引言 在计算机科学中,图是一种非线性数据结构,由顶点集合V和边集合E组成,表示为G=(V,E)。图可以用来表示各种各样的关系,如社交网络中的朋友关系、互联网中的网页链接等...
邻接表是图数据结构的一种高效实现,特别适用于稀疏图(边的数量远小于顶点数量的平方)。在邻接表中,每个顶点都有一个链表或数组,存储与之相连的所有顶点。这种方式节省了空间,因为对于没有直接连接的顶点,我们...
数据结构实验报告主要探讨了如何使用邻接表作为存储结构来实现图的深度优先遍历(DFS)和广度优先遍历(BFS)。在计算机科学中,图是一种表示对象间关系的数据结构,邻接表是高效存储无向图或有向图的一种方式,它...
数据结构课堂实验,邻接表的实现,给大家一个参考
数据结构中图的邻接表存储以及其遍历算法!
数据结构:建立图的邻接表
数据结构实验报告
数据结构中的图是一种重要的抽象数据类型,用于模拟实体之间的关系。在这个实验中,我们专注于图的邻接表存储结构,这是一种高效地表示图的方式,特别适用于处理稀疏图(即边的数量远小于顶点数量的平方)。 邻接表...
完成“数据结构作业 邻接表”可能涉及以下内容:理解图的概念、邻接表的结构、如何用代码实现邻接表、以及如何使用邻接表进行DFS和BFS。通过这项作业,你可以深入理解数据结构的重要性,并提高解决实际问题的能力。...
根据书P262习题3给定的无向带权图,用邻接表作为存储结构,用kruskal算法构造其最小生成树。 克鲁斯卡尔算法的基本思想是:设一个有n个顶点的连通网络G={V,E},先构造一个包括全部n个顶点和0条边的森林F={T0,T1,…...
在本实验中,我们将深入探讨数据结构中的一个重要概念——邻接表,这是图数据结构的一种高效表示方法。湖南大学的数据结构课程通过实验5来让学生掌握邻接表的实现与应用。下面,我们将详细讨论邻接表及其相关知识,...
在计算机科学中,数据结构是组织和管理数据的重要方式,而图是一种常用的数据结构,用于表示对象之间的关系。本文将详细探讨如何利用邻接表来处理无向图,并实现一个算法,判断图中两个顶点间是否存在长度为k的简单...
数据结构上级试验,邻接表,c语言,vc系统使用
在计算机科学中,数据结构是组织、存储和处理数据的方式,而邻接表是一种高效表示图数据结构的方法,尤其在处理稀疏图时更为实用。本文将深入探讨邻接表的概念,以及如何使用C++来实现它,并结合封装原则进行代码...
在处理图形问题时,数据结构图起着至关重要的作用。本主题主要涵盖了三种关键概念:邻接矩阵、邻接表以及图的两种遍历方法——深度优先搜索(DFS)和广度优先搜索(BFS)。 首先,邻接矩阵是一种表示图的数据结构,...
1)熟练掌握图的邻接表存储结构的实现; 2)熟练掌握基于邻接表的图的基本操作算法实现; 3)灵活使用有向图来解决具体的问题。 (2)实验内容: 1)定义有向图的邻接表类,封装图的基本操作算法,包括: a.创建、...
1. 紧缩邻接表的数据结构:紧缩邻接表将图的每个顶点的邻接表紧凑的存储在两个向量 list 和 h 中,其中向量 list 依次存储顶点 0,1,…,n-1的邻接顶点,向量单元 h[i]存储顶点 i 的邻接表在向量 list 中的起始位置...
邻接表是实现有向图的一种常见且高效的数据结构。 邻接表由两部分组成:节点数组和边列表。对于一个包含n个节点的图,我们通常会有一个大小为n的数组,每个数组元素对应一个节点。数组中的每个元素又包含一个列表,...