图的表示方法


图的常见表示方法是邻接表和邻接矩阵,但是没了应对题目的千变万化和降低考试的时候的错误率,可以自己写一种自己熟悉的图结构,然后再遇到图算法的题目的时候,只需要写一个转化函数将题目给的图结构转换为自己定义的图结构就行

左神课程给出的图结构模板

左神语录:不带模板上考场,就等于裸奔

构建思路

图模板

1) 节点类:包含节点值,入度值,出度值,与该节点相邻的节点集合(表示该节点可以通过边指向谁),该节点出去的边的集合
2)边类:包含边的权重,边的出发节点和变得终止节点
a) 图的大结构

class Node
{
public:
	int value;//节点的值,可以是任何类型,表示该节点存放的内容
	int in;//入度
	int out;//出度
	list<Node*> nexts;//与节点相邻的节点集合
	list<Edge*> edges;//属于节点的边的集合,表示那个边是从该节点出去的
	Node(int v)
	{
		value = v;
		in = 0;
		out = 0;
	}
	Node() { value = 0; in = 0; out = 0; }
};

class Edge
{
public:
	int weight;
	Node* from;
	Node* to;
	Edge(int w, Node* N1, Node* N2)//因为需要定义Node这个类,所以需要再从类中加上
								  //一个没有接受参数的构造函数,不然会出问题
	{
		weight = w;
		from = N1;
		to = N2;
	}
	//Edge() { weight = 0, from = nullptr; to = nullptr; }
};


class GraphF
{
public:
	unordered_map<int, Node*> nodes;//点集,第一个参数表示第几个节点
	unordered_set<Edge*> edges;//边集
	GraphF() {};//用于定义GraphF类对象
};

图结构转换函数

  • 图结构之间的转换
    给定一个二维数组matrix,shape=[N,3];第一列表示边的出发节点,第二列表示点的终止节点,第三列表示边的权重;比如【0,3,5】表示节点0指向节点3,边的权重为5;
  • code
#include<iostream>
#include<unordered_map>
#include<unordered_set>
#include<list>
#include<vector>

using namespace std;

class Edge;

class Node
{
public:
	int value;//节点的值,可以是任何类型,表示该节点存放的内容
	int in;//入度
	int out;//出度
	list<Node*> nexts;//与节点相邻的节点集合
	list<Edge*> edges;//属于节点的边的集合,表示那个边是从该节点出去的
	Node(int v)
	{
		value = v;
		in = 0;
		out = 0;
	}
	Node() { value = 0; in = 0; out = 0; }
};

class Edge
{
public:
	int weight;
	Node* from;
	Node* to;
	Edge(int w, Node* N1, Node* N2)//因为需要定义Node这个类,所以需要再从类中加上
								  //一个没有接受参数的构造函数,不然会出问题
	{
		weight = w;
		from = N1;
		to = N2;
	}
	//Edge() { weight = 0, from = nullptr; to = nullptr; }
};


class GraphF
{
public:
	unordered_map<int, Node*> nodes;//点集,第一个参数表示第几个节点
	unordered_set<Edge*> edges;//边集
	GraphF() {};//用于定义GraphF类对象
};

/*
[
	[0,1,7],
	[1,2,5],
	[2,3,7],
	[3,1,8]
]
第一列表示出发节点
第二列表示结尾节点
第三列表示两个节点直接边的权重
*/
//将上边的图结构描述转换为我们定义的图结构描述

GraphF trans_Graph(vector<vector<int>>& matrix)
{
	GraphF graph;
	for (int k = 0; k < matrix.size(); k++)
	{
		int from = matrix[k][0];
		int to = matrix[k][1];
		int weight = matrix[k][2];
		Node newfromNode(from);
		Node newtoNode(to);

		if (graph.nodes.find(from) == graph.nodes.end())
			graph.nodes.insert(pair<int, Node*>(from, &newfromNode));
		if (graph.nodes.find(to) == graph.nodes.end())
			graph.nodes.insert(pair<int, Node*>(to, &newtoNode));

		auto fromNode = graph.nodes.find(from);
		auto toNode = graph.nodes.find(to);

		(*fromNode).second->nexts.push_back(toNode->second);
		(*fromNode).second->out++;
		(*toNode).second->in++;
		Edge new_edge(weight, (*fromNode).second, (*toNode).second);
		Edge* newedge = &new_edge;
		(*fromNode).second->edges.push_back(newedge);
		graph.edges.insert(newedge);
	}
	return graph;
}

int main()
{
	vector<vector<int>>  mat{ {0,1,7},{1,2,5},{2,3,7},{3,1,8} };
	GraphF G;

	G = trans_Graph(mat);
	cout << 1 << endl;
	return 0;
}

代码地址:https://github.com/hjfenghj/cpp_code/blob/main/graph_tran.cpp

问题记录

再写以上代码的时候,出现了蛮多错误,总结起来就三点

  1. 以上有两个类Node和Edge,而且两者互相调用,就需要有个先后;
    类或结构体的前向声明只能用来定义指针对象或引用,因为编译到这里时还没有发现定义,不知道该类或者结构的内部成员,没有办法具体的构造一个对象,所以会报错;所以如果把类Edge提前声明,那么再Node中只能定义Edge的指针,否者会出现field has incomplete type
  2. 注意pair结构的使用方法
  3. 根据类的使用方法,添加对应的构造函数;比如需要想定义整型变量那样定义一个类对象,就需要加一个无参数的构造函数;

下一篇来纪录几道使用图模板的习题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光技术人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值