当前位置: 首页 > news >正文

政务信息网站建设制度百度电话客服

政务信息网站建设制度,百度电话客服,旅游网站建设的目的,重庆金融公司网站建设文章目录 一、图的基本概念二、图的存储结构2.1 邻接矩阵2.2 邻接表2.3 邻接矩阵的实现2.4 邻接表的实现 三、总结 一、图的基本概念 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E&#…

文章目录

  • 一、图的基本概念
  • 二、图的存储结构
    • 2.1 邻接矩阵
    • 2.2 邻接表
    • 2.3 邻接矩阵的实现
    • 2.4 邻接表的实现
  • 三、总结

一、图的基本概念

  • 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是顶点的集合,E是边的集合
  • 在图中数据元素,我们则称之为顶点(Vertex)。
  • 图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。

有上面的定义可以得出树是一个特殊的图,与图的区别是没有环连通。
树关注的是节点(顶点)的值,而图关注的是顶点及边的权值。

  • 图按照有无方向分为无向图有向图。无向图由顶点和边构成,有向图由顶点和弧构成。弧有弧尾和弧头之分。
    -

比方说现在想表示社交关系,那么QQ,微信等就是无向图,抖音微博这种就是有向图(你关注的人不一定关注了你)。

  • 图按照边或弧的多少分稀疏图稠密图。如果任意两个顶点之间都存在边叫完全图,有向的叫有向完全图。若无重复的边或顶点到自身的边则叫简单图。
  • 图中顶点之间有邻接点、依附的概念。无向图顶点的边数叫做,有向图顶点分为入度和出度。
  • 图上的边或弧上带权则称为
  • 一个图包含了另一个图的部分顶点和部分边,就叫做子图
    在这里插入图片描述
  • 图中顶点间存在路径,两顶点存在路径则说明是连通的,如果路径最终回到起始点则称为环(回路),当中不重复叫简单路径若无向图任意两顶点都是连通的,则图就是连通图,有向则称强连通图
  • 生成树在无向图中,一个连通图的最小连通子图称作该图的生成树。有 n 个顶点的连通图的生成树有 n 个顶点和 n-1 条边。
    在这里插入图片描述

二、图的存储结构

一个图的信息包括两部分,即图中顶点的信息以及描述顶点之间的关系 ---- 边或者弧的信息。因此无论采用什么方法建立图的存储结构,都要完整、准确地反映这两个面的信息。下面介绍两种常用的图的存储结构。这篇介绍两个常见的结构:邻接矩阵和邻接表。

2.1 邻接矩阵

因为节点与节点之间的关系就是联通与否,即为 0 或者 1,因此邻接矩阵(二维数组)即是:先用一个数组将定点保存,然后采用矩阵来表示节点与节点之间的关系
在这里插入图片描述
可以看出无向图是对称的,而有向图没有对称关系。
如果边是带权值的且两个顶点不相连,我们可以用INT_MAX或者INT_MIN来表示。

邻接矩阵存储图的优点是能够快速知道图中两个顶点是否连通,缺点是顶点很多且边比较少时,比较浪费空间,并且两个节点之间的路径不好求。若要确定图中有多少条边,需要遍历一遍邻接矩阵,空间复杂度为 O(N^2) 。这是用邻接矩阵来存储图的局限性。

所以邻接矩阵适合存稠密图,适合查找两个顶点是否相连

2.2 邻接表

邻接表:使用数组表示顶点的集合,使用链表表示边的关系。

用数组保存顶点,用链表保存连通的顶点。
在这里插入图片描述
邻接表适合存稀疏图,适合查找一个顶点连出去的边

2.3 邻接矩阵的实现

邻接矩阵有以下的模板参数:

template <class V, class W, W MAX = INT_MAX, bool DIR = false>

V - 顶点,W - 权值,MAX - 最大值(默认参数给整形的最大值),DIR - 表示图是否有方向。

template <class V, class W, W MAX = INT_MAX, bool DIR = false>
class Graph
{
public:
private:vector<V> _vertexs;// 顶点集合unordered_map<V, int> _idxMap;// 顶点映射下标vector<vector<W>> _matrix;// 邻接矩阵
};

构造函数
我们传进一个数组和一个size_t型数据,数组里面存放顶点,数据表示数组的大小。
在内部我们首先要把每个顶点存储起来,并初始化邻接矩阵,把权值全部初始化成MAX代表不相连。

Graph(const V* a, size_t n)
{_vertexs.reserve(n);for (size_t i = 0; i < n; i++){_vertexs.push_back(a[i]);// 将传入数组的值存储到vector中_idxMap[a[i]] = i;// 让数组中的每一个数据映射一个下标}_matrix.resize(n);for (size_t i = 0; i < n; i++){_matrix[i].resize(n, MAX);}
}

添加边

首先要获取两个顶点的下标,然后还要判断是有向图还是无向图,无向图要添加两次。

// 获取顶点下标
size_t GetIdx(const V& v)
{auto it = _idxMap.find(v);if (it == _idxMap.end()){assert(false);return -1;}return it->second;
}void addEdge(const V& src, const V& dst, const W& w)
{size_t si = GetIdx(src);size_t di = GetIdx(dst);_matrix[si][di] = w;if (DIR == false){_matrix[di][si] = w;}
}

打印观察

void Print()
{// 打印矩阵横坐标cout << "  ";for (size_t i = 0; i < _vertexs.size(); ++i){printf("%5d", i);}cout << endl;// 打印矩阵for (size_t i = 0; i < _matrix.size(); ++i){cout << i << " "; // 打印矩阵纵坐标for (size_t j = 0; j < _matrix[i].size(); ++j){if (_matrix[i][j] == MAX)printf("%5c", '*');elseprintf("%5d", _matrix[i][j]);}cout << endl;}
}

整体代码

template <class V, class W, W MAX = INT_MAX, bool DIR = false>
class Graph
{
public:Graph(const V* a, size_t n){_vertexs.reserve(n);for (size_t i = 0; i < n; i++){_vertexs.push_back(a[i]);// 将传入数组的值存储到vector中_idxMap[a[i]] = i;// 让数组中的每一个数据映射一个下标}_matrix.resize(n);for (size_t i = 0; i < n; i++){_matrix[i].resize(n, MAX);}}// 获取顶点下标size_t GetIdx(const V& v){auto it = _idxMap.find(v);if (it == _idxMap.end()){assert(false);return -1;}return it->second;}void addEdge(const V& src, const V& dst, const W& w){size_t si = GetIdx(src);size_t di = GetIdx(dst);_matrix[si][di] = w;if (DIR == false){_matrix[di][si] = w;}}void Print(){// 打印顶点和下标间的映射关系for (size_t i = 0; i < _vertexs.size(); ++i){cout << "[" << i << "]" << "->" << _vertexs[i] << endl;}cout << endl;// 打印矩阵横坐标cout << "  ";for (size_t i = 0; i < _vertexs.size(); ++i){printf("%5d", i);}cout << endl;// 打印矩阵for (size_t i = 0; i < _matrix.size(); ++i){cout << i << " "; // 打印矩阵纵坐标for (size_t j = 0; j < _matrix[i].size(); ++j){if (_matrix[i][j] == MAX)printf("%5c", '*');elseprintf("%5d", _matrix[i][j]);}cout << endl;}}private:vector<V> _vertexs;// 顶点集合unordered_map<V, int> _idxMap;// 顶点映射下标vector<vector<W>> _matrix;// 邻接矩阵
};void TestGraph()
{Graph<char, int, INT_MAX, false> g("ABCDE", 5);g.addEdge('A', 'B', 1);g.addEdge('B', 'D', 4);g.addEdge('A', 'D', 2);g.addEdge('B', 'C', 9);g.addEdge('A', 'C', 8);g.addEdge('E', 'A', 5);g.addEdge('A', 'E', 3);g.addEdge('C', 'D', 6);g.Print();
}

在这里插入图片描述

2.4 邻接表的实现

邻接表里面存的是边,所以我们要设计一个边的类。

template <class W>
struct Edge
{Edge(int dsti, const W& w): _dsti(dsti), _w(w), _next(nullptr){}int _dsti;W _w;// 权值Edge<W>* _next;
};

当要加入一个边的时候,直接头插即可。
其他的和邻接矩阵同理。

template <class W>
struct Edge
{Edge(int dsti, const W& w): _dsti(dsti), _w(w), _next(nullptr){}int _dsti;W _w;// 权值Edge<W>* _next;
};template <class V, class W, bool DIR = false>
class Graph
{
public:Graph(const V* a, size_t n){_vertexs.reserve(n);for (size_t i = 0; i < n; i++){_vertexs.push_back(a[i]);// 将传入数组的值存储到vector中_idxMap[a[i]] = i;// 让数组中的每一个数据映射一个下标}_tables.resize(n, nullptr);}// 获取顶点下标size_t GetIdx(const V& v){auto it = _idxMap.find(v);if (it == _idxMap.end()){assert(false);return -1;}return it->second;}void addEdge(const V& src, const V& dst, const W& w){size_t si = GetIdx(src);size_t di = GetIdx(dst);Edge<W>* eg = new Edge<W>(di, w);eg->_next = _tables[si];_tables[si] = eg;if (DIR == false){Edge<W>* eg = new Edge<W>(si, w);eg->_next = _tables[di];_tables[di] = eg;}}void Print(){// 打印顶点和下标间的映射关系for (size_t i = 0; i < _vertexs.size(); ++i){cout << "[" << i << "]" << "->" << _vertexs[i] << endl;}cout << endl;for (size_t i = 0; i < _tables.size(); ++i){// 遍历当前链表,并打印链表结点中的相关信息cout << _vertexs[i] << "[" << i << "]->";Edge<W>* cur = _tables[i];while (cur){cout << "[" << _vertexs[cur->_dsti] << ":" << cur->_dsti << ":" << cur->_w << "]->";cur = cur->_next;}cout << "nullptr" << endl;}}private:vector<V> _vertexs;// 顶点集合unordered_map<V, int> _idxMap;// 顶点映射下标vector<Edge<W>*> _tables;// 邻接表
};void TestGraph()
{Graph<char, int, true> g("ABCDE", 5);g.addEdge('A', 'B', 1);g.addEdge('B', 'D', 4);g.addEdge('A', 'D', 2);g.addEdge('B', 'C', 9);g.addEdge('A', 'C', 8);g.addEdge('E', 'A', 5);g.addEdge('A', 'E', 3);g.addEdge('C', 'D', 6);g.Print();
}

在这里插入图片描述

三、总结

根据邻接表和邻接矩阵的结构特性可知,当图为稀疏图、顶点较多,即图结构比较大时,更适宜选择邻接表作为存储结构。当图为稠密图、顶点较少时,或者不需要记录图中边的权值时,使用邻接矩阵作为存储结构较为合适。
邻接表和邻接矩阵相辅相成,各有优缺点,是互补的。



http://www.hkea.cn/news/514955/

相关文章:

  • 怎么做微信里的网页网站链接网站设计平台
  • 长宁专业做网站网络营销案例分享
  • 哈尔滨专业建网站哪家好码迷seo
  • 涞水县住房和城乡建设局网站厦门seo专业培训学校
  • 网站建设销售招聘德阳seo
  • 平台网站建设的公司seozou是什么意思
  • wordpress 相册 主题seo整站优化技术培训
  • 做窗帘网站图片百度自动点击器下载
  • 飘雪影视大全免费观看视频快推达seo
  • 做网站的装饰标语seo宣传网站
  • 国外 平面设计 网站百度收录
  • 做网站话术简述搜索引擎的工作原理
  • 现在建设网站赚钱吗seo外链论坛
  • 青海网站建设企业海南百度竞价推广
  • 南京做网站yuanmus电脑突然多了windows优化大师
  • 美国做deals的网站软文营销经典案例优秀软文
  • 招标网站怎么做吴江seo网站优化软件
  • 苏州建设工程协会网站seo去哪里学
  • 上海正规网站制作价格可口可乐软文营销案例
  • 番禺网站 建设信科网络站长之家ping
  • 建筑工程施工承包合同关键词优化报价推荐
  • 网站可以免费看企业网站系统
  • 中华人民共和国建设部网站seo怎么快速提高排名
  • 南宁做网站的有几家东莞网络营销网站建设
  • 苏州知名网站建设开发新区seo整站优化公司
  • 政府建设网站计划书品牌营销策略包括哪些内容
  • 深圳市做网站百度seo排名点击器app
  • 五莲网站建设维护推广网络营销推广及优化方案
  • 重庆网红整站多关键词优化
  • 动易网站cms一级消防工程师考试