使用场景:
此方式主要用于卡空间的某些题目中
与邻接表之间使用场景的差别:
链式前向星主要用于边比较多,顶点比较少的情况
链式前向星的优点:比邻接表还省空间,可以解决某些卡空间的问题,删除边也很方便,只需要更改next指针的指向即可。
总结:根据图的疏密选择存储方式,一般情况下用邻接表,卡空间时间这些要求比较高的题目或者需要删除边操作的用链式前向星。
链式前向星需要一个结构体,以及一个数组
结构体:
struct edg
{
int w ; //起点到终点的边的长度
int to; //终点
int next; // 同一个起点的下一条边对于的编号
}edgs[N] ; //这个用于存储所有的边
数组:
同时还需要一个 head[N]数组
head[N]数组的含义:
head[i] 存储的值为 以i为起点的边的最后一个遍历到的边的 edgs[k]的k号值。
举例:
建图:
其中边有:
1 -> 2 ...... 用edgs[1]存储
1 -> 5 ...... 用edgs[2]存储
1 -> 3 ...... 用edgs[3]存储
2 -> 3 ...... 用edgs[4]存储
3 -> 4 ...... 用edgs[5]存储
4 -> 1 ...... 用edgs[6]存储
则:
head[1] = 3 -> 2 -> 1 //为edgs[k]的k值
head[2] = 4
head[3] = 5
head[4] = 6
代码 建图 实现:
struct edg
{
int w;
int to;
int next;
}edgs[N];
int head[N];
int idx = 0; //第0条边开始
void add(int start ,int end , int len)
{
idx++; //idx的下标习惯从1开始
edgs[idx].w = len;
edgs[idx].to = end;
edgs[idx].next = head[start]; // head[start]中存的为start -> 某个结点的边 存入到edgs[k]后的k的编号, 第一个边的话,next指向的为 0. 可以用于判断是否还有从start结点出发的出边是否遍历完
head[start] = idx; //head[start] 每次插入一个值就会改变。
}
int main()
{
for(int i = 0 ; i < n ; i++) //共n条边
{
int start,end,len; //边:从结点Start到end 的长度为len
scanf("%d %d %d",&start,&end,&len);
add(start,end,len);
}
}
在此建图的基础上使用dfs遍历此图 代码实现
int choose[N]; //用于判断结点是否被遍历过了
void dfs(int i)
{
printf("%d ",i);
choose[i] = 1;
for(int j = head[i] ; j != 0 ; j = edgs[i].next) //head[i]中除了最后统计的一条边的next指向0外,其他结点都不指向0.因为edgs[idx]中idx从1开始
{
if( !choose[edgs[j].to] )
{
dfs(edgs[j].to);
}
}
}
j = edgs[i].next 吗? 为什么啊 不应该是 j = edgs[j].next
和链接表有啥区别吗
emmm,这不就是邻接表吗?
”代码 建图 实现“中的:
edgs[i].w = len;
edgs[i].to = end;
edgs[i].next = head[start];
“i”是什么??应该是idx吧
对的。已修改。