自用C++图的类模板

与世无争的帅哥 提交于 2020-02-08 19:13:45

图的实现:使用邻接矩阵

使用方法:

创建类实例:

template <typename IndexType,typename DataType>
class Graph{
public:
    Graph() {}//构造函数
    Graph(const Graph&);//复制构造函数
    Graph& operator=(const Graph&);//赋值函数
    Graph(Graph&&);//移动构造函数
    Graph& operator=(Graph&&);//移动赋值函数
    void show();//显示图
	bool insert(IndexType, DataType, IndexType, bool = false);//插入
	bool del(IndexType, IndexType, bool = false);//删除
	bool update(IndexType, DataType, IndexType, bool = false);//更新
	void clear() { name2dex.clear(); dex2name.clear(); mat.clear(); }//清空
	DataType shortestpath(IndexType,IndexType);//求最短路径
	std::pair<bool, std::vector<IndexType>> topologicalsort();//求拓扑排序
	~Graph() {}
};
//例:
Graph<std::string,int> g;

功能:

1.插入边

bool insert(IndexType, DataType, IndexType, bool = false);//插入成功返回true
//当最后一个参数为true时,即插入无向边
//例如:g.insert("A",1,"B");
//这就插入了一条从A到B的边,边权值为1

2.删除边

bool del(IndexType, IndexType, bool = false);//删除成功返回true
//当最后一个参数为true时,删除无向边
//例如:g.del("A","B");
//这就删除了从A到B的边

3.更新边权值

bool update(IndexType, DataType, IndexType, bool = false);
//与insert方法一致

4.清空图

void clear();

5.求最短路径(Dijkstra)

DataType shortestpath(IndexType,IndexType);//返回某点到某点间的最短路径长度

6.求拓扑排序

std::pair<bool, std::vector<IndexType>> topologicalsort();
//返回pair类型
//其中pair.first=true时则有拓扑排序
//pair.second为拓扑排序结果

一个例子:

主函数实现:

#include <iostream>
#include "Graph_m.h"
#define A "A"
#define B "B"
#define C "C"
#define D "D"
#define E "E"
#define F "F"
using namespace std;

template<typename DataType>
void show(vector<DataType> arr) {//显示vector
	for (DataType i : arr)cout << i << " "; cout << endl;
}
int main()
{
	using IndexType=string;
	Graph<IndexType, int> G1;
	G1.insert(A, 1, B);
	G1.insert(A, 3, C);
	G1.insert(A, 10, F);
	G1.insert(B, 4, E);
	G1.insert(C, 1, D);
	G1.insert(E, 2, F);
	G1.insert(D, 1, F);
	G1.show();cout<<endl;
	show(G1.topologicalsort().second);//显示拓扑排序
	cout << G1.shortestpath(A, F);//显示最短距离
}

结果:

 

 

Graph类模板完整代码:

#ifndef _GRAPH_M_
#define _GRAPH_M_
#include<iostream>
#include<vector>
#include<map>
#include<unordered_map>
#include<queue>

template <typename IndexType,typename DataType>
class Graph {
	std::unordered_map<IndexType, int> name2dex;//index start from 1
	std::unordered_map<int, IndexType> dex2name;//index start from 1
	std::vector<std::vector<DataType>> mat;
	struct nodedist {
		int index;
		DataType dist;
		nodedist(int i, DataType d) :index(i), dist(d) {}
		bool operator<(const nodedist& other)const { return dist > other.dist; }
	};
public:
	Graph() {}
	Graph(std::vector<IndexType>&, std::vector<std::vector<DataType>>&);
	Graph(const Graph&);
	Graph& operator=(const Graph&);
	Graph(Graph&&);
	Graph& operator=(Graph&&);
	void show();
	bool insert(IndexType, DataType, IndexType, bool = false);
	bool del(IndexType, IndexType, bool = false);
	bool update(IndexType, DataType, IndexType, bool = false);
	void clear() { name2dex.clear(); dex2name.clear(); mat.clear(); }
	DataType shortestpath(IndexType,IndexType);
	std::pair<bool, std::vector<IndexType>> topologicalsort();
	~Graph() {}
};
template <typename IndexType,typename DataType>
Graph<IndexType,DataType>::Graph(std::vector<IndexType>& name, std::vector<std::vector<DataType>>& m) {
	if (name.size() != m.size())return;
	int num = name.size();
	if (num <= 0)return;
	mat = m;
	for (int i = 0; i < num; i++) {
		name2dex.insert(std::pair<IndexType, int>(name[i], i + 1));
		dex2name.insert(std::pair<int, IndexType>(i + 1, name[i]));
	}
}

template <typename IndexType, typename DataType>
Graph<IndexType, DataType>::Graph(const Graph& g) {
	name2dex = g.name2dex;
	dex2name = g.dex2name;
	mat = g.mat;
}

template <typename IndexType, typename DataType>
Graph<IndexType, DataType>& Graph<IndexType, DataType>::operator=(const Graph& g) {
	name2dex = g.name2dex;
	dex2name = g.dex2name;
	mat = g.mat;
	return *this;
}

template <typename IndexType, typename DataType>
Graph<IndexType, DataType>::Graph(Graph&& g) {
	name2dex = std::move(g.name2dex);
	dex2name = std::move(g.dex2name);
	mat = std::move(g.mat);
}

template <typename IndexType, typename DataType>
Graph<IndexType, DataType>& Graph<IndexType, DataType>::operator=(Graph&& g) {
	name2dex = std::move(g.name2dex);
	dex2name = std::move(g.dex2name);
	mat = std::move(g.mat);
	return *this;
}

template <typename IndexType,typename DataType>
bool Graph<IndexType,DataType>::insert(IndexType s, DataType dist, IndexType e, bool t) {
	int sdex = name2dex[s], edex = name2dex[e];
	if (!sdex || !edex) {
		if (!sdex) {
			sdex = dex2name.size() + 1;
			name2dex[s] = sdex;
			dex2name[sdex] = s;
		}
		if (!edex) {
			edex = dex2name.size() + 1;
			name2dex[e] = edex;
			dex2name[edex] = e;
		}
		mat.resize(name2dex.size());
		for (int i = 0; i < mat.size(); i++) { mat[i].resize(mat.size()); }
		mat[sdex - 1][edex - 1] = dist;
		if (t)mat[edex - 1][sdex - 1] = dist;
	}
	else {
		if (mat[sdex - 1][edex - 1])return false;
		mat[sdex - 1][edex - 1] = dist;
		if (t)mat[edex - 1][sdex - 1] = dist;
	}
	return true;
}

template <typename IndexType,typename DataType>
bool Graph<IndexType,DataType>::del(IndexType s, IndexType e, bool t) {
	int sdex = name2dex[s], edex = name2dex[e];
	if (!sdex && !edex)return false;
	mat[sdex - 1][edex - 1] = 0;
	if(t)mat[edex - 1][sdex - 1] = 0;
	return true;
}

template <typename IndexType,typename DataType>
bool Graph<IndexType,DataType>::update(IndexType s, DataType dist, IndexType e, bool t) {
	int sdex = name2dex[s], edex = name2dex[e];
	if (!sdex && !edex)return false;
	mat[sdex - 1][edex - 1] = dist;
	if(t)mat[edex - 1][sdex - 1] = dist;
	return true;
}

template <typename IndexType,typename DataType>
DataType Graph<IndexType, DataType>::shortestpath(IndexType s, IndexType e) {
	int sdex = name2dex[s], edex = name2dex[e];
	//std::cout << "Calculate Path...  start:" << sdex << " end:" << edex << std::endl;
	if (!sdex || !edex)return 0;
	if (sdex == edex)return mat[sdex - 1][edex - 1];
	std::vector<bool> set(mat.size(), false);//confirm point
	std::vector<DataType> dis(mat.size(), 0);//distance
	std::priority_queue<nodedist> que;//priority_queue
	que.push(nodedist(sdex-1,0));
	while (!que.empty()) {
		int index = que.top().index;
		DataType dist = que.top().dist;
		que.pop();
		//std::cout << "current point:" << dex2name[index + 1] << " ";
		if (set[index])continue;//has confirmed
		if (index == edex - 1)return dist;
		set[index] = true;
		dis[index] = dist;
		for (int i = 0; i < mat.size(); i++) {
			if (mat[index][i])que.push(nodedist(i,dist+mat[index][i]));
		}
	}
	return dis[edex - 1];
}

template <typename IndexType,typename DataType>
void Graph<IndexType,DataType>::show() {
	std::cout << "  ";
	for (int i = 0; i < mat.size(); i++) {
		std::cout << dex2name[i + 1] << " ";
	}
	std::cout << std::endl;
	for (int i = 0; i < mat.size(); i++) {
		std::cout << dex2name[i + 1] << " ";
		for (int j = 0; j < mat.size(); j++) {
			std::cout << mat[i][j] << " ";
		}
		std::cout << std::endl;
	}
}

template <typename IndexType,typename DataType>
std::pair<bool, std::vector<IndexType>> Graph<IndexType, DataType>::topologicalsort() {
	std::pair<bool, std::vector<IndexType>> ans(false,std::vector<IndexType>());
	std::queue<int> my_que;
	std::vector<int> indegrees(mat.size(), 0);
	int num = mat.size();
	for (int i = 0; i < mat.size(); i++) {
		for (int j = 0; j < mat.size(); j++) {
			if (mat[j][i])indegrees[i]++;
		}
	}
	for (int i = 0; i < indegrees.size(); i++)if (!indegrees[i]) { my_que.push(i); ans.second.push_back(dex2name[i+1]); }
	while (!my_que.empty()) {
		int index = my_que.front();
		my_que.pop();
		for (int i = 0; i < mat.size(); i++) {
			if (mat[index][i]) {
				if (--indegrees[i] == 0) { my_que.push(i); ans.second.push_back(dex2name[i+1]); }
			}
		}
		num--;
	}
	ans.first = (num == 0);
	return ans;
}
#endif

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!