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

【图论】图的C++实现代码

在这个例程中我们用类实现了节点、(无向图)连边、无向图,实现了节点度的计算、无向图聚类系数计算、度分布统计、无向图的Dijkstra算法(已知起止点计算最短路的算法)

#include <iostream>
#include<vector>
#include<set>
#include<unordered_map>
using namespace std;

class Edge
{
public:
	int v1;
	int v2;
	int weight;
	Edge(int v1, int v2, int w)
	{
		this->v1 = v1;
		this->v2 = v2;
		this->weight = w;
	}
};

class DJPathInfo // 存放已知最短路
{
public:
	vector<vector<int>> shortest_path;
	vector<int> shortest_path_len;
	DJPathInfo(int n)
	{
		vector<int> empty;
		this->shortest_path=vector<vector<int>>(n, empty);
		this->shortest_path_len= vector<int>(n, 0);
	}
};

class Node
{
public:
	std::vector<Edge> edges;
	int id;

	Node(int i)
	{
		this->id = i;
	}

	int degree()
	{
		return this->edges.size();
	}

	vector<int> neighbors()
	{
		vector<int> res;
		if (this->edges.size() > 0)
		{
			for (auto edge : this->edges)
			{
				if (edge.v1 == this->id) res.push_back(edge.v2);
				else res.push_back(edge.v1);
			}
			return res;
		}
		else return res;
	}

	float cluster_coeff(vector<vector<bool>> adj_mat)
	{
		int num_neighbor = this->edges.size() - 1;
		if (num_neighbor < 2) return 0;
		vector<int> neighbors = this->neighbors();
		float E = 0; //邻居之间的边数
		for (auto i : neighbors)
		{
			for (auto j : neighbors)
			{
				if (i >= j) continue;
				if (adj_mat[i][j] == true) E++;
			}
		}
		cout << 2 * E / (neighbors.size() * (neighbors.size() - 1)) << endl;
		return 2 * E / (neighbors.size() * (neighbors.size() - 1));
	}
};

class Graph
{
public:
	vector<vector<bool>> adj_mat;
	vector<vector<float>> w_mat;
	int node_num;
	vector<Edge> edges;
	vector<Node> nodes;
	Graph(vector<vector<bool>> A, vector<vector<float>> W)
	{
		this->adj_mat = A;
		this->w_mat = W;
		this->node_num = A.size();
		for (int i = 0; i < node_num; i++) this->nodes.push_back(Node(i));
		for (int i = 0; i < node_num; i++)
			for (int j = 0; j < i; j++)
			{
				if (A[i][j] == true) this->add_edge(i, j, W[i][j]);
			}
	}

	Graph(int n)
	{
		vector<float> zero(n, 0);
		vector<bool> all_false(n, false);
		vector<vector<bool>> A(n, all_false);
		vector<vector<float>> W(n, zero);
		this->adj_mat = A;
		this->w_mat = W;
		this->node_num = A.size();
		for (int i = 0; i < node_num; i++) this->nodes.push_back(Node(i));
		for (int i = 0; i < node_num; i++)
			for (int j = 0; j < i; j++)
			{
				if (A[i][j] == true) this->add_edge(i, j, W[i][j]);
			}
	}

	void add_edge(int id1, int id2, int weight)
	{
		Edge e = Edge(id1, id2, weight);
		this->adj_mat[id1][id2] = true;
		this->adj_mat[id2][id1] = true;
		this->w_mat[id1][id2] = weight;
		this->w_mat[id2][id1] = weight;
		this->edges.push_back(e);
		this->nodes[id1].edges.push_back(e);
		this->nodes[id2].edges.push_back(e);
	}

	void tell_info()
	{
		for (auto v : this->nodes)
		{
			std::cout << "Node ID:" << v.id << std::endl;
			std::cout << "Neighbor/Weight:";
			for (auto i : v.neighbors()) cout <<'(' << i<<','<< this->w_mat[v.id][i] << ')' << ',';
			std::cout<<std::endl;
		}
	}


	vector<int> DJ(int s, int dest) // Dijkstra算法
	{
		DJPathInfo info(this->nodes.size());
		vector<int> res = {s};
		set<int> S;
		S.insert(s);
		set<int> U;
		for (auto v : this->nodes[s].neighbors()) U.insert(v);
		if (U.size() == 0) return res;
		for (auto v : U)
		{
			info.shortest_path[v].push_back(v);
			info.shortest_path_len[v] = this->w_mat[s][v];
		}
		info.shortest_path_len[s] = 0;
		while (U.size() != 0)
		{
			int n = *U.begin();
			int n_len = info.shortest_path_len[n];
			for (auto it = U.begin(); it != U.end(); it++)
			{
				if (info.shortest_path_len[n] > info.shortest_path_len[*it])
				{
					n = *it;
					n_len = info.shortest_path_len[*it];
				}
			}
			S.insert(n);
			U.erase(n);
			for (auto v : this->nodes[n].neighbors())
			{
				if (S.find(v) != S.end()) continue;
				U.insert(v);
				if (info.shortest_path[v].size() == 0)
				{
					info.shortest_path[v] = info.shortest_path[n];
					info.shortest_path[v].push_back(v);
					info.shortest_path_len[v] = info.shortest_path_len[n] + this->w_mat[n][v];
					continue;
				}
				if (info.shortest_path_len[n] + this->w_mat[n][v] < info.shortest_path_len[v])
				{
					info.shortest_path[v] = info.shortest_path[n];
					info.shortest_path[v].push_back(v);
					info.shortest_path_len[v] = info.shortest_path_len[n] + this->w_mat[n][v];
				}
			}
		}
		if (S.find(dest) != S.end())
		{
			for (auto v : info.shortest_path[dest]) res.push_back(v);
			info.shortest_path_len[dest];
		}
		return res;
	}

	float cluster_coeff()
	{
		float res=0;
		for (auto node : this->nodes) res += node.cluster_coeff(this->adj_mat);
		return res / float(this->nodes.size());
	}
	void degree_distribution() // 度分布
	{
		vector<float> res;
		unordered_map<int, int> degree_count;
		for (auto v : this->nodes)
		{
			degree_count.emplace(v.degree(), 0);
		}
		for (auto v : this->nodes)
		{
			degree_count[v.degree()]++;
		}
		for (auto it : degree_count)
		{
			std::cout << "degree =" << it.first << ', '<<" prob=" << float(it.second) / this->nodes.size() << endl;
		}
	}
};


int main()
{
	Graph G = Graph(11);
	G.add_edge(0, 1, 2);
	G.add_edge(0, 2, 9);
	G.add_edge(0, 3, 1);
	G.add_edge(1, 4, 1);
	G.add_edge(1, 2, 6);
	G.add_edge(2, 4, 5);
	G.add_edge(2, 5, 1);
	G.add_edge(2, 6, 2);
	G.add_edge(2, 3, 7);
	G.add_edge(3, 6, 9);
	G.add_edge(4, 7, 2);
	G.add_edge(4, 8, 9);
	G.add_edge(4, 5, 3);
	G.add_edge(5, 8, 6);
	G.add_edge(5, 6, 4);
	G.add_edge(6, 8, 3);
	G.add_edge(6, 9, 1);
	G.add_edge(7, 8, 7);
	G.add_edge(7, 10, 9);
	G.add_edge(8, 10, 2);
	G.add_edge(8, 9, 1);
	G.add_edge(9, 10, 4);
	G.tell_info();
	cout << "Djkstra Test: shortest 0 -> 10: ";
	for (const auto& p : G.DJ(0, 10)) cout << p << ',';
	cout<<endl;
	cout << "clustring coefficient=" << G.cluster_coeff() << endl;
	cout << "degree distribution:"  << endl;
	G.degree_distribution();
	return 0;
}

http://www.kler.cn/a/386231.html

相关文章:

  • mysql每日一题(上升的温度,date数据的计算)
  • Docker在CentOS上的安装与配置
  • 【数学二】线性代数-二次型
  • 38配置管理工具(如Ansible、Puppet、Chef)
  • 基于node一键发布到服务器的js脚本
  • 会话信息处理: HttpSession、token序列化、收集登录设备信息、基于`spring-session-data-redis`实现session共享。
  • Python小白学习教程从入门到入坑------第二十八课 文件基础操作文件读写(语法进阶)
  • 【AIGC】如何通过ChatGPT轻松制作个性化GPTs应用
  • java后台生成模拟聊天截图并返回给前端
  • MySql中索引为什么用B+树,他有什么特点?时间复杂度是多少?能存多少数据?是不是只能三层?他与B-树有什么不同?还有其它的树你是是否知道?
  • AIPPT项目(提供完整API接入支持套壳)成熟产品线上运营
  • MySQL常用订单表复杂查询15例
  • 找工作就上:万码优才!海量技术岗位等你来
  • PKG_CHECK_MODULES(FUSE,fuse)
  • 「实战应用」如何用图表控件LightningChart .NET在WPF中制作表格?(一)
  • 关于 CSS 常用布局及特点作用
  • 微信小程序-事件总线
  • BP 神经网络模型:原理、实现与应用
  • GFPS技术原理(二)-模型注册和配置
  • react中的组件传参
  • pythons工具——图像的随机增强变换(只是变换了图像,可用于分类训练数据的增强)
  • Elasticsearch 实战应用详解!
  • Vue3+exceljs+file-saver 实现将表格数据中包含图片导出Excel
  • 算法
  • vite构建的react程序放置图片
  • 怎么样鉴定疾病相关稀有细胞群?二值化精细模型标签,这个刚发的顶刊单细胞算法值得一学!