zoukankan      html  css  js  c++  java
  • 《数据结构》C++代码 邻接表与邻接矩阵

           上一篇“BFS与DFS”写完,突然意识到这个可能偏离了“数据结构”的主题,所以回来介绍一下图的存储:邻接表和邻接矩阵。

           存图有两种方式,邻接矩阵严格说就是一个bool型的二维数组,map[i][j]表示i到j有没有单向边,邻接表则是对1~N中每个点都拉出一个链表来,链表E[i]中存的每个点j都表示i到j有一条单向边。 这两种方式各有利弊,在稀疏图中,邻接表更好,省时间而且省空间;在稠密图中,邻接矩阵更好,不浪费时间的同时省去了指针域的空间。

           而实际写代码时,对于邻接矩阵,我们可能会考虑用int型的邻接矩阵来同时表达边的权值,这取决于具体情况;对于邻接表,我们在对每个点拉出一个链表时,可以实际分配一个一维数组作为表头,以简化删除边时的代码,同时方便存每个点的信息,也可以像本文代码中直接用指针来作为表头,省些空间。

           本文仅仅给出相对基本的代码,边上的信息仅有一个权值,想必这已经够了。如果信息增多,大家在同样的位置添加信息即可。另外,临界表在很多情况下是可以用静态内存来代替动态内存的,这个方法本文代码就不赘述了,方法同“线性表”一文中所述。

          注意!对于邻接表和邻接矩阵,我并未试过用类来写,在此仅仅给出一个很丑的类版代码,不是为了供大家参考,而是抛砖引玉,希望有高手能给出更好的类版实现代码,不胜感激!

    清爽版:

     1 const int maxn = 10000;
     2 
     3 // 邻接矩阵
     4 struct edge
     5 {
     6     bool p; // p表示此边有无,也可以通过c取一个题目中不可能取到的值来代替p的作用
     7     int c;
     8     edge():p(false) {}
     9 }map[maxn+1][maxn+1];
    10 void Clear()
    11 {
    12     for(int i=1;i<=maxn;++i)
    13         for(int j=1;j<=maxn;++j) map[i][j].p=false;
    14 }
    15 void AddEdge(int u,int v,int c)
    16 {
    17     map[u][v].p=true; map[u][v].c=c;
    18 }
    19 void DelEdge(int u,int v)
    20 {
    21     map[u][v].p=false;
    22 }
    23 
    24 // 邻接表
    25 struct edge
    26 {
    27     int v;
    28     int c;
    29     edge *next;
    30     edge(int _v=0,int _c=0): v(_v), c(_c) {}
    31 }*E[maxn+1]; // 全局定义,初始便都是0;若在局部定义,则应先清0
    32 void Clear()
    33 {
    34     edge *p;
    35     for(int i=1;i<=maxn;++i)
    36         while(E[i])
    37         {
    38             p=E[i]; E[i]=p->next;
    39             delete p;
    40         }
    41 }
    42 void AddEdge(int u,int v,int c)
    43 {
    44     edge *p=new edge(v,c);
    45     p->next=E[u]; E[u]=p;
    46 }
    47 void DelEdge(int u,int v)
    48 {
    49     if(E[u]->v==v) { E[u]=E[u]->next; return; }
    50     for(edge *p=E[u],*q=p->next;q;p=q,q=p->next)
    51         if(q->v==v)
    52         {
    53             p->next=q->next;
    54             delete q;
    55             return; // 如果有重边,则此处不应返回,应待循环完再返回
    56         }
    57 }

    类版:

     1 // 邻接表
     2 struct edge
     3 {
     4     int v;
     5     int c;
     6     edge *next;
     7     edge(int _v=0,int _c=0): v(_v), c(_c) {}
     8 };
     9 
    10 class Map
    11 {
    12     static const int maxn = 10000;
    13     edge *E[maxn+1];
    14 public:
    15     Map() { for(int i=1;i<=maxn;++i) E[i]=0; }
    16     void clear()
    17     {
    18         edge *p;
    19         for(int i=1;i<=maxn;++i)
    20             while(E[i])
    21             {
    22                 p=E[i]; E[i]=p->next;
    23                 delete p;
    24             }
    25     }
    26     void add(int u,int v,int c)
    27     {
    28         edge *p=new edge(v,c);
    29         p->next=E[u]; E[u]=p;
    30     }
    31     void del(int u,int v)
    32     {
    33         if(E[u]->v==v) { E[u]=E[u]->next; return; }
    34         for(edge *p=E[u],*q=p->next;q;p=q,q=p->next)
    35             if(q->v==v)
    36             {
    37                 p->next=q->next;
    38                 delete q;
    39                 return; // 如果有重边,则此处不应返回,应待循环完再返回
    40             }
    41     }
    42     edge* begin(int u) { return E[u]; }
    43     edge* next(edge *p) { return p->next; }
    44 }G;

     

  • 相关阅读:
    Javascript对象原型prototype和继承
    Javascript(js)使用function定义构造函数
    phpExcel中文帮助手册
    php curl_init函数用法
    nginx启动,重启,关闭命令
    Nginx配置文件详细说明
    Nginx 简单的负载均衡配置示例
    MySQL数据库的同步配置
    ucenter home 视频增加缩略图
    web分词程序和算法
  • 原文地址:https://www.cnblogs.com/icedream61/p/4141966.html
Copyright © 2011-2022 走看看