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

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

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

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

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

清爽版:

 const int maxn = ;

 // 邻接矩阵
struct edge
{
bool p; // p表示此边有无,也可以通过c取一个题目中不可能取到的值来代替p的作用
int c;
edge():p(false) {}
}map[maxn+][maxn+];
void Clear()
{
for(int i=;i<=maxn;++i)
for(int j=;j<=maxn;++j) map[i][j].p=false;
}
void AddEdge(int u,int v,int c)
{
map[u][v].p=true; map[u][v].c=c;
}
void DelEdge(int u,int v)
{
map[u][v].p=false;
} // 邻接表
struct edge
{
int v;
int c;
edge *next;
edge(int _v=,int _c=): v(_v), c(_c) {}
}*E[maxn+]; // 全局定义,初始便都是0;若在局部定义,则应先清0
void Clear()
{
edge *p;
for(int i=;i<=maxn;++i)
while(E[i])
{
p=E[i]; E[i]=p->next;
delete p;
}
}
void AddEdge(int u,int v,int c)
{
edge *p=new edge(v,c);
p->next=E[u]; E[u]=p;
}
void DelEdge(int u,int v)
{
if(E[u]->v==v) { E[u]=E[u]->next; return; }
for(edge *p=E[u],*q=p->next;q;p=q,q=p->next)
if(q->v==v)
{
p->next=q->next;
delete q;
return; // 如果有重边,则此处不应返回,应待循环完再返回
}
}

类版:

 // 邻接表
struct edge
{
int v;
int c;
edge *next;
edge(int _v=,int _c=): v(_v), c(_c) {}
}; class Map
{
static const int maxn = ;
edge *E[maxn+];
public:
Map() { for(int i=;i<=maxn;++i) E[i]=; }
void clear()
{
edge *p;
for(int i=;i<=maxn;++i)
while(E[i])
{
p=E[i]; E[i]=p->next;
delete p;
}
}
void add(int u,int v,int c)
{
edge *p=new edge(v,c);
p->next=E[u]; E[u]=p;
}
void del(int u,int v)
{
if(E[u]->v==v) { E[u]=E[u]->next; return; }
for(edge *p=E[u],*q=p->next;q;p=q,q=p->next)
if(q->v==v)
{
p->next=q->next;
delete q;
return; // 如果有重边,则此处不应返回,应待循环完再返回
}
}
edge* begin(int u) { return E[u]; }
edge* next(edge *p) { return p->next; }
}G;

《数据结构》C++代码 邻接表与邻接矩阵的更多相关文章

  1. 数据结构与算法之PHP用邻接表、邻接矩阵实现图的广度优先遍历(BFS)

    一.基本思想 1)从图中的某个顶点V出发访问并记录: 2)依次访问V的所有邻接顶点: 3)分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,直到图中所有已被访问过的顶点的邻接点都被访问到. 4) ...

  2. 图的dfs遍历模板(邻接表和邻接矩阵存储)

    我们做算法题的目的是解决问题,完成任务,而不是创造算法,解题的过程是利用算法的过程而不是创造算法的过程,我们不能不能陷入这样的认识误区.而想要快速高效的利用算法解决算法题,积累算法模板就很重要,利用模 ...

  3. 数据结构C++使用邻接表实现图

    定义邻接表存储的图类.[实验要求] (1)创建一个邻接表存储的图:(2)返回图中指定边的权值:(3)插入操作:向图中插入一个顶点,插入一条边:(4)删除操作:从图中删除一个顶点,删除一条边:(5)图的 ...

  4. Network of Schools(强连通分量缩点(邻接表&矩阵))

    Description A number of schools are connected to a computer network. Agreements have been developed ...

  5. vector 邻接表的建立(好笨啊,才懂,可能太困了吧)。。

    原创,未经允许不得转载. 图的建立有两种,邻接矩阵和邻接表. 邻接矩阵适用于图较为密集,(稀疏图太浪费存储空间了),图如果较为稀疏,则使用邻接表为宜,dijkstra算法就是以邻接表为基础的. 有向无 ...

  6. POJ 3013 SPFA算法,邻接表的使用

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 19029   Accepted: 4 ...

  7. 图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))

    sdut 2140 图结构练习——判断给定图是否存在合法拓扑序列 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述  给定一个有向图 ...

  8. 数据结构学习笔记05图 (邻接矩阵 邻接表-->BFS DFS、最短路径)

    数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边& ...

  9. 数据结构作业——图的存储及遍历(邻接矩阵、邻接表+DFS递归、非递归+BFS)

    邻接矩阵存图 /* * @Author: WZY * @School: HPU * @Date: 2018-11-02 18:35:27 * @Last Modified by: WZY * @Las ...

随机推荐

  1. Android(java)学习笔记63:Clock App 编写报错01

    1. 首先我们二话不说直接先看报错内容如下: 07-12 08:25:03.572: E/dalvikvm(3602): native fork pid:0 done. 07-12 08:25:03. ...

  2. Uva 12299 带循环移动的RMQ(线段树)

    题目链接:https://vjudge.net/contest/147973#problem/C 题意:传统的RMQ是一个不变的数组a求区间最值.现在要循环移动(往前移动). 分析:求区间问题,很容易 ...

  3. 【[TJOI2017]DNA】

    [题目][https://www.lydsy.com/JudgeOnline/problem.php?id=4892] 好像用\(SAM\)做的都是\(dfs\)啊 其实这里也是搜索 如果用\(SAM ...

  4. caffe resize用interpolation

    opencv的resize默认的是使用双线性插值INTER_LINEAR,也可以是尝试其他的方式进行插值操作 if (param.random_interpolation_method()) { // ...

  5. 线程 task训练

    1. task类表示一个线程,最简单的task的构造方法是 ,参数是Action<t>,是一个无返回值的泛型委托. 指向要执行的函数.当调用·start()方法时,就执行子线程.执行指向的 ...

  6. 短信状态监听 - iOS

    当使用 App 时若短信介入需要对当前状态进行监听操作,根据不同的状态实行相关的需求操作,废话不多说步骤如下. 首先,常规操作先引用对应的头文件,来为后续功能铺路. #import <Messa ...

  7. 开发必看 | iOS开发常用设计模式!

    ios开发学习中,经常弄不清楚ios的开发模式,今天我们就来进行简单的总结和探讨~(一)代理模式 应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现.优势:解耦合敏捷原则: ...

  8. BZOJ1004: [HNOI2008]Cards(Burnside引理 背包dp)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4255  Solved: 2582[Submit][Status][Discuss] Descript ...

  9. 【思维题 细节】loj#6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

    挂于±1的细节…… 题目描述 跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相. 由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后还冒着被打 ...

  10. Atlas实现mysql主从分离

     可以接受失败,无法接受放弃!加油! 一.介绍Atlas及架构图 Atlas源代码用C语言编写,它对于Web Server相当于是DB,相对于DB相当于是Client,如果把Atlas的逻辑放到Web ...