邻接表三种常见方法简介

邻接表是存图的一种很好的方式,在搜索算法中有较为广泛的应用。首先分清三种方法。

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 为顶点的边时,事实上是倒序遍历的,但是倒序并不会影响任何结果,所以这个方法的正确性是有保障的。

附上一个讲链式前向星的博客链接,内容大同小异。

https://www.cnblogs.com/ECJTUACM-873284962/p/6905416.html

邻接表的三种方法就介绍完了,希望大家能尽早掌握链式前向星~~~

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接表和逆邻接表是一种常用的图的存储结构,用于表示有向图或无向图的边关系。下是求邻接表和逆邻接表方法: 1. 邻接表邻接表是一种链式存储结构,用于表示图的边关系。对于有向图,邻接表中的每个顶点都有一个链表链表中存储了该顶点指向的其他顶点。具体求邻接表的步骤如下: - 创建一个数组,数组的大小为图中顶点的个数。 - 遍历图中的每个顶点,对于每个顶点,创建一个链表链表中存储该顶点指向的其他顶点。 - 遍历图中的每条边,将边的起始顶点添加到对应顶点的链表中。 2. 逆邻接表: 逆邻接表邻接表的一种变形,用于表示有向图中每个顶点的入边关系。具体求逆邻接表的步骤如下: - 创建一个数组,数组的大小为图中顶点的个数。 - 遍历图中的每个顶点,对于每个顶点,创建一个链表链表中存储指向该顶点的其他顶点。 - 遍历图中的每条边,将边的终点添加到对应顶点的链表中。 下面是一个示例,展示如何求解邻接表和逆邻接表: ```python # 邻接表 adj_list = [[] for _ in range(num_vertices)] # 创建一个空的邻接表 for edge in edges: start, end = edge # 边的起始顶点和终点 adj_list[start].append(end) # 将终点添加到起始顶点的链表中 # 逆邻接表 reverse_adj_list = [[] for _ in range(num_vertices)] # 创建一个空的逆邻接表 for edge in edges: start, end = edge # 边的起始顶点和终点 reverse_adj_list[end].append(start) # 将起始顶点添加到终点的链表中 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值