我们都知道在存储稠密图时候,邻接表比邻接矩阵效率高,因为邻接矩阵中在存储稀疏图时候,很多没用连接的点既占了空间,也浪费搜索时间。所以这篇博客帮助大家,学习一下邻接表。写的不好之处,请海涵。
首先我们需要需要定义一个结构体,来描述边。
struct e{
int to; // 边的终点
int next;// 专业书上叫做存储当前边的下一条边,但是我觉得理解为上一条边好像更好,过会从图中可以看出,别急
int val;// 边的权值
//可能有些人想问,为啥没起点,因为起点在表头当中,就是后面我们直接用一个数组存储了各个起点。叫做head[MAXN]
};
接下来,我们需要将图的信息通过函数add()添加进来,图的每一条边心里给它加一个编号,我们这里从1开始
首先定义几个全局变量:head[MAXN] from to val num=1(边的序号)
介绍一下head[x]:存储x的最新一条编号,也可理解为x的最后一条编号。数组默认为0
void add(起点from,终点to,权值val){
e[num].next=head[from]; //意思是e[num].next存储from的上一条边的号
e[num].to=to;
e[num].val=val;//看情况写不写
//既然我们添加一条边,那么head[from]就要更新了,对吧
head[from]=num++;//之后边的序号就增加1
}
给大家画了这个草图,将就看一下,这个next是不是存储上一条边号?至少我是这样觉得。。只不过受单词影响了。。
解释一下上图中的几个重要地方:
怎么表示2 4之间有连接:
for(int i=head[2];i!=0;){//从head[2]的最后一条边寻找 对应上图就是4号边
if(e[i].to==4){
cout<<"find";
break;
}
//没有找到怎么办,别忘了我们next,起到了大作用,往上一条边访问,上一条与2连接的边号是多少?是3吧,怎么表达?
i=head[2]=e[i].next;
}
1 2
1 3
2 4
2 3
3 4
find
好了,说了这么多,还是看看代码吧,我们现在做个题目,就简单把上面这幅图用邻接表的方式输出吧
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 1000
// 描述边的信息
struct e{
int to;
int next;
int val;
};
int head[MAXN],num=1;
e ee[MAXN];
void add(int from,int to){
ee[num].next=head[from];
ee[num].to=to;
head[from]=num++;
}
int main(){
memset(head,0,sizeof head);
//上图 4个顶点 5条边 但是无向图是要保存双向,明白吧。
for(int i=1;i<=5;i++){
int from,to,val;//这里val就不输入了,因为是 0
cin>>from>>to;
add(from,to);
add(to,from);
}
for(int i=1;i<=4;i++){//遍历每个起点
for(int j=head[i];j!=0;){
if(ee[j].to!=0){
cout<<i<<" "<<ee[j].to<<endl;
}
j=head[i]=ee[j].next;
}
cout<<endl;
}
return 0;
}
//输入
1 2
1 3
2 4
2 3
3 4
//输出
1 3
1 2
2 3
2 4
2 1
3 4
3 2
3 1
4 3
4 2
如果觉得这篇文章对你有所帮助,请关注。
文章版权所有