首页 > 其他分享 >邻接表

邻接表

时间:2024-04-12 18:11:25浏览次数:19  
标签:nxt 数组 int 邻边 邻接 编号 eidx

邻接表

感觉写的很好啊!
转载自:数组模拟邻接表 - AcWing

首先假设我们有n个点(n <= N),m条边(m <= M)。

我们可以想一下对于任意一个结点u, 需要记录邻边的哪些信息。
这些信息应该包括这条邻边的终点,权重,以及下一条邻边的编号。
注意这里不需要记录邻边的起点,因为我们使用的时候都是给出起点的。
所以我们可以定义一个struct来表示邻边:

struct Edge
{
    int eid;    // 该条边的编号
    int e;      // 该条边的终点
    int w;      // 该条边的权重
    int nxt;    // 下一条邻边的编号
};

如果我们用上面的数据结构来记录邻边的信息,那么我们只需要定义如下变量来表示邻接表:

// 注意N和M的区别
int h[N];
Edge edges[M];
int eidx;

由于每条边都记录了下一条边的编号,这样我们只要把每个结点的第一条邻边的编号记录在h数组,我们就可以遍历它的每一条邻边了。

如果我们把Edge里的信息分开存到不同数组里,那么我们可以得到平时我们看到的变量定义:

// 注意N和M的区别
int h[N];
int e[M], w[M], nxt[M];  // 这三个数组等价于之前的Edge edges[M],注意这些数组的下标表示邻边的编号
int eidx;

这里每个数组的下标的含义不一样。
关键的事情说三遍:h数组的下标为结点的编号,e,w,nxt数组的下标为边的编号,eidx为边的编号
关键的事情说三遍:h数组的下标为结点的编号,e,w,nxt数组的下标为边的编号,eidx为边的编号
关键的事情说三遍:h数组的下标为结点的编号,e,w,nxt数组的下标为边的编号,eidx为边的编号

如果理解了以上,下面就很好理解了。
有向图的邻接表存储就是对于每个点 u 对应一个头节点h[u],记录第一条邻边的编号。
e, w, nxt数组的编号和建图的顺序有关,对于某一个点u, 它的所有邻边的编号不一定是连续的。
nxt[eidx]=h[u]; h[u]=eidx; 这个操作就是把新建的边插入表头。(先把新建的边的next指向现在队头的next,然后更新队头的next)
然后再eidx++, 给下一次建边使用

下边用图模拟一下加入四条边的过程

  1. 初始状态

Screen Shot 2020-12-02 at 7.49.05 AM.png

  1. 加完第一条边(1,2,9)之后

Screen Shot 2020-12-02 at 7.49.43 AM.png

  1. 加完第二条边(2,4,1)之后

Screen Shot 2020-12-02 at 7.49.49 AM.png

  1. 加完第三条边(1,3,3)之后
    这里可以看到后加入的边,反而在邻接表的最前面

Screen Shot 2020-12-02 at 7.50.02 AM.png

  1. 加完第四条边(3,4,5)之后

Screen Shot 2020-12-02 at 7.50.10 AM.png

最后是代码及注释

const int N = 1010, M = 1010;

int h[N], e[M], w[M], nxt[M], eidx;

void add(int u, int v, int weight)   // 添加有向边 u->v, 权重为weight
{
    e[eidx] = v;        // 记录边的终点
    w[eidx] = weight;   // 记录边的权重
    nxt[eidx] = h[u];   // 将下一条边指向结点u此时的第一条边
    h[u] = eidx;        // 将结点u的第一条边的编号改为此时的eidx
    eidx++;             // 递增边的编号edix, 为将来使用
}

void iterate(int u)   // 遍历结点u的所有邻边
{
    // 从u的第一条边开始遍历,直到eid==-1为止
    for(int eid = h[u]; eid != -1; eid = nxt[eid])
    {
        int v = e[eid];
        int weight = w[eid];
        cout << u << "->" << v << ", weight: " << weight << endl;
    }
}

int main()
{
    int n, m;
    cin >> n >> m;

    memset(h, -1, sizeof h);  // 初始化h数组为-1
    eidx = 0;                 // 初始化边的编号为0

    while(m--)
    {
        int u, v, weight;
        cin >> u >> v >> weight;
        add(u, v, weight);
    }

    for(int u = 1; u <= n; ++u)
        iterate(u);

    return 0;
}


标签:nxt,数组,int,邻边,邻接,编号,eidx
From: https://www.cnblogs.com/KAI040522/p/18131870

相关文章

  • 图的存储-邻接表
    1.邻接表所谓邻接表,就是把从同一个顶点发出的边链接在同一个称为边链表的单链表中。边链表的每个结点代表一条边,称为边结点。每个边结点有2个域:该边终点的序号,以及指向下一个边结点的指针。在邻接表中,还需要一个用于存储顶点信息的顶点数组。 例如,如下所示的有向图对应的邻......
  • 图的存储-邻接矩阵
    1.有向图和无向图的邻接矩阵 设G(V,E)是一个具有n个顶点的图,则图的邻接矩阵是一个n×n的二维数组,用Edge[n][n]表示,它的定义为:下面的图给出了无向图G1(V,E)及其邻接矩阵表示。在图中,为了表示顶点信息,特意将顶点的标号用字母A、B、C、D、E和F表示,各顶点的信息......
  • Dijkstra邻接矩阵板子
    constintN=510;//节点个数intn;intg[N][N];//图intdist[N];//距离boolst[N];//判断点是否访问过intdijkstra(ints)//s表示起点,求s到任意点的最短距离{memset(dist,0x3f,sizeofdist);dist[s]=0;for(inti=0;i<n;i++){......
  • 邻接矩阵详解
    邻接矩阵是图论中用于表示图(Graph)结构的一种重要数据结构,特别适用于表示顶点之间连接关系的图形。在计算机科学和数学领域,它被广泛应用来编码无向图和有向图的信息。对于一个具有n个顶点的图G=(V,E),邻接矩阵是一个n×n的矩阵A,其中的行和列分别对应着图中的每个顶点。矩......
  • 邻接表存储带权的无向图(c++题解)
    题目描述给出一个无向带权图,顶点数为n,边数为m。输入格式第一行两个整数n,m,接下来有m行,每行3个整数u,v,w,表示点u到点v有一条边,边权为w。输出格式第i行输出第点i的所有邻接点,按照点i到该点的边权由小到大输出,如果边权相等,则按照点的编号有小到大输出。样例样例输入复......
  • C#实现图的邻接矩阵和邻接表结构
    原文链接:https://blog.csdn.net/weixin_41883890/article/details/125517599本文介绍C#实现图的邻接矩阵和邻接表结构。逻辑结构分为两部分:V和E集合,其中,V是顶点,E是边。因此,用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵......
  • 邻接矩阵 存储图
    存储图可以用邻接表和邻接矩阵以下代码来自https://www.acwing.com/blog/content/405///对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点inth[N],e[N],ne[N],idx,w[N];//添加一条边a->b,权重是wvoidadd(inta,intb,intw){e[id......
  • OSPF的邻居关系和邻接关系
    1、ospf邻居(neighbors)同一个网段上的路由器可以成为邻居。邻居是通过Hello报文来选择的,Hello报文使用IP多播方式在每个端口定期发送。路由器一旦在其相邻路由器的Hello报文中发现他们自己,则他们就成为邻居关系了,在这种方式中,需要通信的双方确认。邻居的协商只在主地址(Primaryadd......
  • C++图的邻接表创建
    C++图的邻接表存储结构typedefstructNode{ intnextVex; structNode*next; }*node;structHeadNode{ Eelement; structNode*next;};typedefstructGraphTable{ intvex,edge; structHeadNodeVertex[MAXV];}*Graph;图的创建函数Graphcreate(){ Grap......
  • 12.12邻接表存储实现图的深度优先遍历(c++)
    今天学习了数据结构中的邻接表存储实现图的深度优先遍历,其中让我受益匪浅,以下是我的解题思路。编写程序,实现由邻接表存储实现无向图的深度优先搜索遍历的功能。顶点为字符型。输入格式:第一行输入顶点个数及边的个数,第二行依次输入各顶点,第三行开始依次输入边的两个顶点,用空格......