邻接表是存图的一种很好的方式,在搜索算法中有较为广泛的应用。首先分清三种方法。
1、vector:这是最容易理解的一种方法,使用比较广泛(一般像笔者这样的萌新使用较多)。优点:方便,代码简洁,容易理解。缺点:某些不怀好意的题可能会卡你时间,vector效率不高。
2、链表:使用链表存图,优点:速度较快,缺点:内存开销大一些,可能会被卡内存。(一般不会)
3、链式前向星:使用最为广泛的一种方法,内存与时间开销相对平衡,性能均衡,无明显的优缺点。(缺点可能是太难理解了)
(一)vector
代码:
/*优点:方便,代码简洁
缺点:有时候有点慢*/
struct node
{
int to, dis;
};
vector<node> v[N]; //定义一个邻接表
void add(int from, int to, int len)
{
node now;
now.to = to;
now.dis = len;
v[from].push_back(now); //建立一条from与to连接的边
//如果是无向图,则再建立一条to-from的边
}
void visit(int i) //遍历与i相连的边
{
int len = v[i].len(); //判断i点与多少个点相连
for (int k = 0; k < len; k++) //tmp为与i相连接的点
{
node tmp = v[i][k];
}
}
说明几点:
1、开结构体是为了能够更好的存储每个边的长度还有起始点和末尾点,有一些题是不需要边的长度的,那么也不需要存边了,直接如下即可:
vector<int> vec[N];
void add(int from, int to)
{
vec[from].push_back(to);
//如果是无向图,还需要下面一步
//vec[to].push_back(from);
}
2、vec[i][j]存储的是, i 点可以连接到 j 点,这一信息。
以这张图为例:
则vector的存储方式可以理解为:
(二)链表
代码:
/*优点:速度较快
缺点:内存开销大一些*/
struct Edge
{
int to;
int value;
Edge *next;
};
Edge *edges[MAXN], pool[MAXM], *alloc;
Edge *new_Edge(int from, int to, int value) //建一条新边
{
Edge *tmp = alloc++;
tmp->to = to;
tmp->value = value;
tmp->next = edges[from];
return tmp;
}
void add_edge(int from, int to, int value)
{
edges[from] = new_Edge(from, to, value);
//无向图建双向边,有向图不需要
//edges[to] = new_Edge(to, from, value);
}
void init() //初始化
{
alloc = pool;
memset(edges, 0, sizeof edges);
}
代码简单一说,to表示第i条边的终点,next表示与第i条边同起点的下一条边的存储位置,还是以上面那张图为例,那么链表的存储方式就可以理解为:
(三)链式前向星
代码:
/*性能较平均*/
struct edges
{
int to;
int dis;
int next;
};
edges edge[N];
int head[N], num;
void init() //初始化
{
memset(head, -1, sizeof(head));
num = 0;
}
void add(int from, int to, int len)
{
edge[num].to = to;
edge[num].dis = len;
edge[num].next = head[from];
head[from] = num++;
}
void visit(int now) //遍历与now相连的边
{
for (int i = head[now]; i != -1; i = edge[i].next)
{
int to = edge[i].to;
}
}
说一下代码,edge[i].to表示第i条边的终点,edge[i].next表示与第i条边同起点的下一条边的存储位置,edge[i].dis为边权值。
另外还有一个head数组,它是用来表示以i为起点的“第一条边存储的位置”,实际上你会发现这里的“第一条边”存储的位置实际上是最后输入的那一条边,也就是说在遍历以 i 为顶点的边时,事实上是倒序遍历的,但是倒序并不会影响任何结果,所以这个方法的正确性是有保障的。
附上一个讲链式前向星的博客链接,内容大同小异。
邻接表的三种方法就介绍完了,希望大家能尽早掌握链式前向星~~~