zoukankan      html  css  js  c++  java
  • 邻接表建图方法及代码

    图论这块挺不好理解的,建图+最短路,代码不容易理解,尤其是建图过程。

    以下是转的写的很好地一篇博文,图文并茂:


    邻接表建图法1
    极大的节省了空间和时间 是建图非常棒的一种方式
    它利用数组模拟出边与边之间的关系  
    图示解析(数据为代码中的测试数据):


    #include<iostream>
      #define Maxn 200
      using namespace std;
      struct edge{int from,to,weight,next;}e[Maxn];//存储边信息的结构体 
     int first[Maxn];//起点为下标存储(e中边的位置) 
     int main()
     {
         int edges;//边数 
         memset(first,-1,sizeof(first));
         //因为刚开始first不指向任何一条边的下标,所以first都为-1 
         cin>>edges;//边数 
         for(int i=0;i<edges;i++)
         {
             cin>>e[i].from>>e[i].to>>e[i].weight;//起点 终点 权重 
             e[i].next=first[e[i].from];first[e[i].from]=i;//不容易理解的地方
             /*
             利用first数组存储的是最新的(以数组下标为起点的)边的下标 
             并且该条边的next指向的是同样以数组下标为起点的下一条边的下标 
             直到下一条边的next=-1(即将所有以数组下标为起点的边都遍历了一遍) 
             */
         }
         for(int u=1;u<10;u++)//输出图 
         {
             cout<<"以"<<u<<"为起点的所有边的信息:"<<endl; 
             for(int v=first[u];v!=-1;v=e[v].next)//遍历以u为起点的所有边的信息 
                 cout<<e[v].from<<" "<<e[v].to<<" "<<e[v].weight<<endl;
         }
         return 0;
     }
     /*
     5
     3 4 6
     3 7 8
     1 3 6
     2 4 7
     3 5 1
     */




    邻接表建图法2
    这种方式与上一种方式出自一个思想 
    只不过是前者是利用数组模拟边之间的关系
    而它是用指针来表示边之间的关系 

    #include<iostream>
     #define Maxn 200
     using namespace std;
     struct edge
     {
         int from,to,weight;
         edge *next;
     }e[Maxn];//存储边 
     edge*first[Maxn];//所有以起点为下标的头指针
     int main()
     {
         int edges;//边数 
         for(int i=0;i<Maxn;i++)first[i]=NULL;
         //因为刚开始first不指向任何一条边,所以初始化first都为NULL 
         cin>>edges;//边数 
         for(int i=0;i<edges;i++)
         {
             cin>>e[i].from>>e[i].to>>e[i].weight;//起点 终点 权重 
             e[i].next=first[e[i].from];first[e[i].from]=&e[i];//不容易理解的地方
             /*
             利用first数组存储的是最新的(以数组下标为起点的)边的地址 
             并且该条边的next指向的是同样以数组下标为起点的下一条边的地址 
             直到下一条边的next=NULL(即将所有以数组下标为起点的边都遍历了一遍) 
             */
         }
         for(int u=1;u<10;u++)//输出图 
         {
             cout<<"以"<<u<<"为起点的所有边的信息:"<<endl; 
             for(edge*v=first[u];v;v=v->next)//遍历所有以u为起点的边 
                 cout<<v->from<<" "<<v->to<<" "<<v->weight<<endl;
         }
         return 0;
     }



    邻接表建图3 
    这种方式十分精巧,适合表明点之间的关联关系,并且可以统计出以某一点为起点的边的总数
    但不能够存储权重,如果数据量比较大时,浪费的空间非常大

    #include<iostream>
     #define Maxn 200
     using namespace std;
     int main()
     {
         int G[Maxn][Maxn],edges,from;
         for(int u=1;u<Maxn;u++)G[u][0]=0; //G[u][0]用于记录起点为u的边的总数 
         cin>>edges;//边数 
         while(edges--)
             cin>>from>>G[from][++G[from][0]];//起点 终点 
         for(int u=1;u<10;u++)//输出图 
         {
             cout<<"所有以"<<u<<"为起点的边共有"<<G[u][0]<<"条分别为: "<<endl; 
             for(int v=1;v<=G[u][0];v++)//输出所有以u为起点的边的信息 
             cout<<G[u][v]<<" ";
             cout<<"\n";
         }
         return 0;
     }


  • 相关阅读:
    数据结构(java语言描述)顺序栈的使用(两个大数相加)
    DB2 Sql性能查看与优化
    spring默认为单例模式
    Java map的匿名类的初始化
    使用nohup后台执行ftp传输命令
    停止一个java的线程执行
    静态类
    XML语法随记
    Crontab有关
    string转Date转回String(JAVA)
  • 原文地址:https://www.cnblogs.com/dollarzhaole/p/3188907.html
Copyright © 2011-2022 走看看