【数据结构】 对于“前向星”的理解

在做图论题的时候,关于如何存图,经常会很纠结。用邻接矩阵,可能会很浪费空间;用邻接表,结构很紧凑,但是链表结构又较难实现。所以,网上有大牛发明了“前向星”,也就是静态链表,即用数组实现邻接表的功能。下面介绍一下我对前向星的一些理解。
注:由于前向星其实和邻接表的原理相同,只不过是用数组实现,因此本文在解释前向星原理的时候经常与邻接表进行比较。希望读者在看本文之前先理解邻接表的原理和实现。
注二:对于树同样可以静态建树,可以参见我的另一篇文章https://www.jianshu.com/p/7e6488e40863
图结构示例如下:

示例.png

如果使用邻接表存储,结构如下
邻接表.png

可以看出,邻接链表在每个顶点后接一个链表,表示这个顶点的邻接点。那么,如果合理地使用数组存储这个链表,显然更为优越——既能保证不浪费空间,实现起来也比链表容易。
于是,前向星应运而生。前向星和邻接链表不同的一点就是,对于每个顶点,前向星存储的是该顶点的邻接边而非邻接点,也就是说,相比于邻接表在每个顶点后挂上一串该顶点的邻接点,前向星在每个顶点后面“挂”上一串该顶点的邻接边。这里的后一个“挂”是不准确的,我们可以在脑海中可以想象这个结构,但要注意实现“前向星”的数据结构并非如此。
以下是实现前向星的数据结构

//存边的信息的结构体
struct Edge
{
    int to;//某个顶点u的邻接点 
    int next;//顶点u的下一条邻接边的编号 
    int val;//该邻接边的权值 
};
//两个必要的数组
Edge edge[edgenumber];//edge[i]表示编号为i的边 
int head[vexnumber];//head[u]表示u的其中一条邻接边的编号 

只看上面的数据结构,相信大家还是很疑惑:
为什么Edge结构体不用记录顶点u?
两个数组又有什么用?
不要着急,我下面会仔细分析这些问题。

正如我上面所说,前向星存储的是每个顶点的邻接边。可以在脑海中想象一下,在每个顶点后面连一个链表,不过链表的节点表示的是邻接边而非邻接点。而用数组实现这个链表,就是前向星。

为什么不要存储顶点u?
不管用哪种结构存图,都应该是每读入一条边的信息,就更新一次图结构。读入一条边u-->v,那么我们在存储图的时候,对于顶点u,该边就是u的一条邻接边,我们就把这条边“挂”在u后面。等读入所有的边,建图完成,顶点u后“挂”的边就全是顶点u的邻接边,因此只需要记录这些邻接边的另一个顶点,而不需要存储顶点u。
由于边是按顺序一条一条读入,我们就很自然的想到对边进行编号,然后将这些边存入edge数组。对于Edge结构体中的next,其实就相当于链表中的next指针。不过此处的next是int型变量,存储的是下一条邻接边的编号。
那么head数组是干什么的呢?
这个就相当于邻接链表中的表头数组,head[u]就表示顶点u的某一条邻接边。根据这条边的next,就能找出顶点u所有的邻接边。
如果还是很难想象,没关系,我们可以先来模拟一下。对于上文的示例,作为无向图,假设边权全为1,如果题目给数据,会给出如下数据,由于已经说明是无向图,就不必每条边都正反给出两次了。
5 5 //顶点数和边数
1 2 1
1 4 1
2 3 1
2 5 1
3 5 1
我先给出初始化和建图的代码,然后再做解释。

    for(int i=0;i<vexnumber;i++)
    {
        head[i]=-1;
    }
    cin>>edgenum;
    //由于是无向图,要正向反向都建边
    for(int i=0;i<2*edgenum;i+=2)
    {
        int from,to,v;
        cin>>from>>to>>v;
        //第一条
        edge[i].to=to;
        edge[i].val=v;
        edge[i].next=head[from];//类似链表头插
        head[from]=i;
        //第二条
        edge[i+1].to=from;
        edge[i+1].val=v;
        edge[i+1].next=head[to];
        head[to]=i+1;
    }

以下是模拟建图的过程
需要注意的是,下文edge数组图片中的from->to列并不出现在Edge结构体中,我将其写出来仅仅是为了直观的展示这条边的两个顶点。
初始情况
初始化head数组为-1,类似链表中的NULL。


初始edge数组.png

初始head数组.png

读入第一条边
由于第一条边是 1--2,而且图是无向图,所以要在1--2和2--1建边。更新edge[i].next为head[u],同时更新head数组,使其值为相应的边的编号。这个操作类似链表的头插操作。


edge数组.png

head数组.png

读入第二条边


edge数组.png
head数组.png

读入第三条边


edge数组.png
head数组.png

读入第四条边


edge数组.png
head数组.png

读入第五条边


edge数组.png
head数组.png

这样建图就完成了,为了直观,画成邻接表形式,但注意下图并非真正的存储结构。


图的逻辑结构.png

对于图论题,遍历图是经常要做的操作。对于前向星,遍历图的操作依然类似邻接表。以下是遍历图的代码

for(int cur=1;cur<=vexnum;cur++)
{
    for(int k=head[cur];k!=-1;k=edge[k].next)
    {
        //相应操作
        //......
        //...... 
    }
}

思考一下就能看出,其中cur表示顶点,而k为cur的邻接边在edge数组中的下标。
仅仅只是看了数组中存储的东西,应该还是很难完全理解。因此希望读者自己模拟一遍,加深理解。
以上就是我对前向星的理解。其实前向星采用的就是邻接链表的思想,只不过存储的是顶点的邻接边,并且用数组实现。总而言之,前向星节省空间,便与实现,是存储图的很优秀的数据结构。只要理解其原理,在做赛题的时候省时省力,事半功倍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • 1. 图的定义和基本术语 线性结构中,元素仅有线性关系,每个元素只有一个直接前驱和直接后继;树形结构中,数据元素(...
    yinxmm阅读 5,457评论 0 3
  • 图是一种比线性表和树更复杂的数据结构,在图中,结点之间的关系是任意的,任意两个数据元素之间都可能相关。图是一种多对...
    Alent阅读 2,306评论 1 22
  • 最近看了一部电影《那天的氛围》。我认为这部电影最大的意义在于它诠释了一种新的,更加积极健康的,洒脱明了的爱情观。 ...
    陌上桃花开阅读 325评论 0 2
  • 中午做好饭菜,然后到客厅等包爸爸回家吃饭时突然听到一阵吧唧吧唧的声音,往阳台望去,看到对面那栋楼四楼有一人端着饭碗...
    海海916阅读 116评论 0 1
  • 上午小新与朋友一起参加滑冰课程,中午又一起吃饭。 饭后,朋友阿男来到小新家。 俩人自由玩耍一段时间之后,爸爸计划组...
    攀登_超越阅读 356评论 0 2