zoukankan      html  css  js  c++  java
  • 从零开始的图的存储方法

    图论是信息学竞赛中十分重要的一个部分,但许多算法都建立在如何存储图的结构上。

    笔者就在这里总结一下图的几种存储方法。

    1.邻接矩阵

    邻接矩阵是表示图的数据结构中最简单的一种,对于一个有n个点的图,我们需要一个n*n的矩阵,

    对于这个图,第i行第j列表示点ai到点aj的距离。

    使用邻接矩阵的时候我们需要初始化,map1[i][i]=0,map1[i][j]=∞。每读入一组数据将map1[i][j]赋值为value即可。

    对于邻接矩阵,初始化需要O(n^2)的时间,建图需要O(m)的时间,而且空间复杂度是O(n^2)。

    虽然邻接矩阵非常简单,但很少有算法选择时间和空间都如此高的邻接矩阵来存储图。

    但也有使用邻接矩阵较简单的 如:Floyd

    2.前向星

    前向星的构造方法很简单,每读入一条边,就将这条边存入数组中,把数组中的边按照起点的顺序排序,就构造完成了。

    int head[MAXN];//存储起点为ai的第一条边的位置
    struct node
    {
        int begin;  //起点 
        int to;     //终点 
        int val;    //权值 
    };
    node map1[MAXM];
    View Code

    将所有信息读入后,按到起点为第一顺序,终点为第二顺序,权值为第三顺序排序。

    前向星的复杂度与排序的算法有关,一般为O(m*logm)。

    因为需要开两个数组,所以空间复杂度为O(n+m)。

    3.邻接表

    邻接表是图中最常用的存储结构,对于图中的每个顶点ai,把所有邻接于ai的边存入一个单链表,这个单链表就是顶点ai的邻接表。

    邻接表实现的方式有很多

    如 动态指针建标,vector数组建表,静态建表(与前向星有关)。

    这里只介绍后两种。

    1.

    首先是vector数组建表

    数据结构:

    struct node
    {
        int to;   //顶点序号
        int val;  //权值
    };
    vector <node> map1[maxn];
    View Code

     遍历

    node e;
    cin>>x>>y>>z;
    e.to=y;
    e.val=z;
    map1[i].push_back(e);
    
    //遍历
    for(i=1;i<=n;i++)
    {
        for(vector <node> ::iterator k=map1[i].begin();k!=map1[i].end();k++)
        {
            node t=*k;
            cout<<i<<" "<<t.to<<" "<<t.val<<endl;
        }
    } 
    View Code

    使用vector有一点好处,就是空间的申请和释放都不需要自己处理,不容易犯错

    2.

    静态建标

    也有人叫做链式前向星

    这种方法是采用用数组模拟链表的策略来建立邻接表

    数据结构:

    for(i=1;i<=n;i++)
    {
        cin>>x>>y>>z;
        map1[i].to=y;
        map1[i].val=z;
        map1[i].next=head[x];
        head[x]=i;
    }
    View Code

    建图与遍历

    for(i=1;i<=m;i++)
    {
        cin>>x>>y>>z;
        map1[i].to=j;
        map1[i].val=z;
        map1[i].next=head[x];
        head[x]=i;
    }
    
    //遍历
    
    for(i=1;i<=n;i++)
    {
        for(k=head[i];k!=-1;k=map1[k].next)
        {
            cout<<i<<" "<<map1[k].to<<" "<<map1[k].val<<endl; 
        }
    } 
    View Code

    因为我们使用了两个数组,所以空间复杂度是O(n+m),每读入一条边就需要维护数组,所以时间复杂度为O(m)

    静态建标的优点在于必要的空间较小,时间复杂度不是很高,代码和原理还有实现都十分明确,而且可以存重边,

    除了不能直接用起点和终点确定是否有边以外,其他都是完美的。

     

  • 相关阅读:
    一周自学动态站点设计
    【甘道夫】Apache Hadoop 2.5.0-cdh5.2.0 HDFS Quotas 配额控制
    linux系统管理命令--系统测试工具
    Atitit.异步编程 java .net php python js 对照
    项目开发经常使用PHP功能
    它们的定义app.config中间section节点和在执行中使用
    Android 它们的定义ListView实现底部和页下拉刷新刷新的顶
    vs2012连接sql2008(错误类型:Could not load file or assembly)
    管理不,因为你不是说经理
    java编程接口(5) ------ button和button组
  • 原文地址:https://www.cnblogs.com/ashon37w/p/7111716.html
Copyright © 2011-2022 走看看