zoukankan      html  css  js  c++  java
  • 图的存储结构

    1.二维数组邻接矩阵存储

    定义int G[101][101]; G[i][j]的值,表示从点i到点j的边的权值,定义如下:

    2.二维数组邻接矩阵存储的优化 (多用于稠密图

    int g[101][101],num[101];   //num[i]记录与顶点i相连的边数,增强顶点的联系
    double w[101][101];
    cin >> e;
    for (k = 1; k <= e; k++)
    {
    cin >> i >> j >> v;             //读入两个顶点序号及权值
    w[i][j]=w[j][i]=v;
    g[i][++num[i]] = j;             //对于不带权的图g[i][j]=1
    g[j][++num[j]] = i;             //无向图的对称性, 有向图则不要!
    } 
    
    查询:O(e)//边数
    for(int i=1;i<=n;i++)
    for(int j=1;j<=num[i];j++)
    {
      直接调用w[i][g[i][j]]……
    }

    3. STL邻接矩阵存储的优化

    (关于vector的用法,请见☟

    Vector(动态数组)怎么用咧↓↓↓ - endl - 博客园  https://www.cnblogs.com/ljy-endl/p/11271899.html)

    vector<int>g[101];
    double w[101][101];
    cin >> e;
    for (k = 1; k <= e; k++)
    {
    cin >> i >> j >> v;             //读入两个顶点序号及权值
    w[i][j]=w[j][i]=v;
    g[i].push_back(j);//对于不带权的图g[i][j]=1
    g[j].push_back(i);//无向图的对称性, 有向图则不要!
    } 
    查询:O(e)//边数
    for(int i=1;i<=n;i++)
    for(int j=0;j<g[i].size();j++)
    {
      直接调用w[i][g[i][j]]……
    }

    4.数组模拟邻接表存储(!!!)(多用于稀疏图

    例:将下图用数组模拟邻接表存储

    因为此图是无向图,所以还可以由输入得到:

    然后再将上述数据整理一下,得到下表:

    i为第几条边,from指起点,to指终点,w指长度

    (注意不同颜色的数字和箭头)

     将上表按照 从第几个顶点开始 的方式用下图存储

    (数据处理完之后:head[第i个顶点]=i连接的最后一条边,然后又通过这一条边的nxt查询连接i顶点的下一条边,直到nxt=0为止

    (注意:是倒序存储,这样可以避免正序查找时重复遍历数组)

    将上图所示的过程用代码写粗来就是下面的红色字体:

    #include <iostream>
    using namespace std;
    const int maxn=1001,maxm=100001;
    struct Edge
    {
        int next;                               //下一条边的编号 
        int to;                                 //这条边到达的点 
        int dis;                                //这条边的长度 
    }edge[maxm];              //也可以用to[maxm],dis[maxm],nxt[maxm]三个数组替代
    
    int head[maxn],num_edge,n,m,u,v,d;//head[]表头,num_edge当前加入第几条边
    
    void add_edge(int from,int to,int dis)      //加入一条从from到to距离为dis的单向边 
    {
        edge[++num_edge].next=head[from];
        edge[num_edge].to=to;
        edge[num_edge].dis=dis;
        head[from]=num_edge;
    }
    int main()
    {
        num_edge=0;
        scanf("%d %d",&n,&m);                    //读入点数和边数
        for(int i=1;i<=m;i++)
        {
              scanf("%d %d %d",&u,&v,&d);   //u、v之间有一条长度为d的边 
              add_edge(u,v,d);
                       add_edge(v,u,d);                          //无向边多加一条反向的
        }
             for(int j=1;j<=n;j++)
        for(int i=head[j];i!=0;i=edge[i].next)   //遍历从点j开始的所有边 
        {
               //...
        }
    
        //...
    
        return 0;
    }
  • 相关阅读:
    可由inetd启动的协议无关时间获取服务器程序
    daemon_inetd函数
    作为守护进程运行的协议无关时间获取服务器程序
    daemon_init函数:调用该函数把普通进程转变为守护进程
    getnameinfo函数
    tcp_connect函数
    20200311 11. 应用生命周期事件
    20200311 10. Web 应用
    20200311 9. 分派请求
    20200311 8. 注解和可插拔性
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/11272163.html
Copyright © 2011-2022 走看看