数据结构图论基础知识(一)

文章目录

  • [1. 图的基本概念](#1. 图的基本概念)
  • [2. 图的一些现实的应用](#2. 图的一些现实的应用)
    • [2.1 ABCDE各个城市之间的关系](#2.1 ABCDE各个城市之间的关系)
    • [2.2 社交关系](#2.2 社交关系)
  • [3. 图的存储结构](#3. 图的存储结构)
    • 3.1邻接矩阵
    • [3.2 邻接矩阵的实现](#3.2 邻接矩阵的实现)
    • [3.3 邻接表](#3.3 邻接表)

1. 图的基本概念

  1. (graph) (edge)和顶点 (Vertex)构成
  2. 图是由顶点集合及顶点间的关系组成的一种数据结构 :G = (V, E),其中:顶点集合V = {x|x属于某个数据对象集}是有穷非空集合
  3. E = {(x,y)|x,y属于V}或者E = {<x, y>|x,y属于V && Path(x, y)}是顶点间关系的有穷集合,也叫做边的集合。
  4. 图更关注元素与元素之间的关系
  5. 图分为有向图和无向图
  6. 二叉树也是图吗?
    树是一种特殊的(无环联通图)图,但是图不一定是树,再者树关心的是节点中存的值,图关注的是顶点和边的权值

2. 图的一些现实的应用

2.1 ABCDE各个城市之间的关系

  1. 顶点:城市
  2. 边:城市之间的关系(比如它们之间的距离,到达的时间,)
  3. 保证联通情况下的最小开销,D点要到达B点的最小距离就可以是一个最小生成树的问题
  4. 最小生成树:用最小的代价,把图中的两个点间接地连在一起

2.2 社交关系

  1. 顶点:人
  2. 边:表示两个人是好友
  3. 权值:可以表示两个人之间的亲密度
  4. qq,微信等都是无向图,是强社交关系 :表示两个人互相都是好友
  5. 微博,抖音等都是有向图 ,是社交媒体关系,是弱社交关系:我可以关注喜欢的博主,但是博主不一定关注了我

3. 图的存储结构

3.1邻接矩阵

  1. 因为节点与节点之间的关系就是连通与否,即为0或者1,因此邻接矩阵(二维数组)即是:先用一个数组将定点保存,然后采用矩阵来表示节点与节点之间的关系。


2. 无向图的邻接矩阵是对称的,第i行(列)元素之和,就是顶点i的度。有向图的邻接矩阵则不一定是对称的,第i行(列)元素之后就是顶点i 的出(入)度。
3. 如果边带有权值,并且两个节点之间是连通的,上图中的边的关系就用权值代替,如果两个顶点不通,则使用无穷大代替


4. 用邻接矩阵存储图的好处 是能够快速知道两个顶点是否连通O(1)缺陷 是如果顶点比较多,边比较少时,矩阵中存储了大量的0成为系数矩阵,比较浪费空间,并且要求两个节点之间的路径不是很好求,不适合查找一个顶点所连接的所有边O(N),比如查找3这个顶点的所有边,要看0,1,2,3是否为1,也就是要查找N次

3.2 邻接矩阵的实现

cpp 复制代码
#pragma once

#include<iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;

// 邻接矩阵
namespace matrix
{
	// 无向图,V顶点,W边
	template<class V,class W,W MAX_W = INT_MAX,bool Direction = false>
	class Graph
	{
	public:
		// 图创建的方式:
		// 1.io输入,不方便测试,oj测试比较方便
		// 2.图的结构写到文件中,读取文件
		// 3.手动添加边,方便测试

		// 图的初始化
		Graph(const V* a, size_t n)// 传一个顶点相关的集合进行初始化
		{
			// 顶点的集合
			_vertexs.reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				_vertexs.push_back(a[i]);
				_indexMap[a[i]] = i;
				// 顶点和下标的映射
			}
			
			_matrix.resize(n);
			for (int i = 0; i < _matrix.size(); i++)
			{
				_matrix[i].resize(n,MAX_W);
			}
		}

		// 获取顶点的下标,检查顶点是否是错误的
		size_t GetVertexIndex(const V& v)
		{
			auto it = _indexMap.find(v);
			if (it != _indexMap.end())
			{
				return it->second;
			}
			else
			{
				// 抛异常
				throw invalid_argument("顶点不存在");

				return -1;
			}
		}

		// 给序号为两个节点的添加边(权值)
		void AddEdge(const V& src,const V& dst,const W& w)
		{
			size_t srci = GetVertexIndex(src);
			size_t dsti = GetVertexIndex(dst);
			_matrix[srci][dsti] = w;

			// 无向图需要添加两个有关联的边
			if (Direction == false) _matrix[dsti][srci] = w;
		}

		// 打印
		void Print()
		{
			// 顶点
			for (int i = 0; i < _vertexs.size(); i++)
			{
				cout << "[" << i << "]" << "->" << _vertexs[i] << '\n';
			}
			cout << '\n';

			cout << "  ";
			// 横着的下标
			for (int i = 0; i < _vertexs.size(); i++)
			{
				cout << i << " ";
			}
			cout << '\n';

			// 邻接矩阵
			for (int i = 0; i < _matrix.size(); i++)
			{
				// 竖着的下标
				cout << i << " ";
				for (int j = 0; j < _matrix[i].size(); j++)
				{
					if (_matrix[i][j] == MAX_W)
					{
						cout << "*" << " ";
					}
					else
						cout << _matrix[i][j] << " ";
				}
				cout << '\n';
			}
		}
         
	private:
		vector<V> _vertexs;// 顶点集合
		map<V, int> _indexMap;// 顶点映射下标
		vector<vector<W>> _matrix;// 邻接矩阵
	};

	void TestGraph()
	{
		char vertices[] = { '0', '1', '2', '3' };  // 显式传入 char 数组
		Graph<char, int, INT_MAX, true> g(vertices, 4);
		g.AddEdge('0', '1', 1);
		g.AddEdge('0', '3', 4);
		g.AddEdge('1', '3', 2);
		g.AddEdge('1', '2', 9);
		g.AddEdge('2', '3', 8);
		g.AddEdge('2', '1', 5);
		g.AddEdge('2', '0', 3);
		g.AddEdge('3', '2', 6);

		g.Print();
	}
}

#include"Graph.h"
using namespace std;

int main()
{
	matrix::TestGraph();

	return 0;
}

3.3 邻接表

邻接表:使用数组表示顶点的集合,使用链表表示边的关系。
1.无向图邻接表存储

  1. 有向图邻接表存储,一般情况下,存储一个出边表即可,主要是为了找到一个顶点连接出去的路径有哪些

总结一下,邻接矩阵和邻接表是相辅相成的关系,各有优缺点,两者具有互补的关系

相关推荐
一只鱼^_18 分钟前
牛客练习赛138(首篇万字题解???)
数据结构·c++·算法·贪心算法·动态规划·广度优先·图搜索算法
寒小松44 分钟前
Problem E: List练习
java·数据结构·list
清幽竹客2 小时前
redis数据结构-02(INCR、DECR、APPEND)
数据结构·redis
Akiiiira2 小时前
【数据结构】线性表
数据结构
小狗祈祷诗2 小时前
day20-线性表(链表II)
c语言·数据结构·链表
普通的冒险者2 小时前
几个简单的数组小练习(适合初学)
java·数据结构
How_doyou_do4 小时前
数据结构-堆
数据结构
小陈的进阶之路4 小时前
计算机大类专业数据结构下半期实验练习题
数据结构·算法·深度优先
不会计算机的捞地4 小时前
【数据结构入门训练DAY-30】数的划分
数据结构·算法·深度优先
@我漫长的孤独流浪6 小时前
最短路与拓扑(2)
数据结构·c++·算法