左神算法基础class6—题目1图的存储与表达
1.题目:图的存储与表达
图的存储方式:1)邻接表2)邻接矩阵
如何表达图?生成图?
2.分析
(1)邻接表法
①无权重
如果为无向图既有1–>2,也有2–>1.
②有权重
(2)邻接矩阵
(3)矩阵表达(题目常出现)
纵向有三列,每一列分别为权重weight、来源from、指向to
3.图在内存中的存储
在内存中,常用类来表达。
(1)class Graph
Graph类有点和边两大部分,使用hash_map存储节点,使用hash_set存储边的信息
class Graph
{
public:
unordered_map<int,Node*> nodes;
unordered_set<Edge*> edges;
Graph(){};
};
下面来解释节点和边的构成
(2)class Node
节点有五部分数据,分别是节点的值value、入度in、出度out、当前节点的下一个节点nexts、以及与从当前节点出发的边。
class Node
{
public:
int value;
int out;
int in;
list<Node*> nexts;
list<Edge*> edges;
Node(int val,int inn = 0,int outt = 0):value(val),in(inn),out(outt){}
};
(3)class Edge
节点有三部分数据,分别是边上的权重、当前边的from和to节点
class Edge
{
public:
int weight;
Node* from;
Node* to;
Edge(int wgt,Node* f,Node* t):weight(wgt),from(f),to(t){}
};
(4)class GraphGenerator
把产生图函数封装成了类。注意:采用(3)中矩阵的方式
图的产生过程如下,
①先生成一个graph对象,对数组按行遍历,第一个元素赋给权重,第二、第三元素表示节点值赋给from和to;
②判断当前图中以from、to为值得节点存在否,不存在则创建图中的节点
③再把图中from和to节点拿出来,建立边;
④补充from节点的指向节点to、边、出度。补充to节点的入度;
⑤把建立的边加到图里的边。
class GraphGenerator
{
public:
Graph createGraph(vector<vector<int> > matrix)
{
Graph graph;//需要graph的node和edge 、node有五个data、edge有三个data
for(int i = 0; i < matrix.size();++i)
{
int weight = matrix[i][0];
int from = matrix[i][1];
int to = matrix[i][2];
//Graph的node里不含有from节点、to节点时建上
if(graph.nodes.find(from) == graph.nodes.end())
graph.nodes[from] = new Node(from);
if(graph.nodes.find(to) == graph.nodes.end())
graph.nodes[to] = new Node(to);
//拿出from,to点
Node* fromNode = graph.nodes[from];
Node* toNode = graph.nodes[to];
//Node* fromNode = graph.nodes.find(from)->second;
//Node* toNode = graph.nodes.find(to)->second;
//新建边
Edge* newEdge = new Edge(weight, fromNode, toNode);
//增加节点的四个数据
fromNode->nexts.push_back(toNode);
fromNode->edges.push_back(newEdge);
fromNode->out++;
toNode->in++;
graph.edges.insert(newEdge);
}
return graph;
}
};
(5)测试
输出graph中的所有节点以及边
//test
unordered_map<int,Node*>::iterator ite1 = graph.nodes.begin();
while(ite1 != graph.nodes.end())
{
cout << "节点: "<<(ite1)->second->value<<"、";
//cout << "节点: "<<(ite1)->first<<"、";
ite1++;
}
cout<<endl<<"-----------------------------------------------"<<endl ;
unordered_set<Edge*>::iterator ite = graph.edges.begin();
while(ite != graph.edges.end())
{
cout << "边权为 "<<(*ite)->weight<<" ";
cout<<(*ite)->from->value <<"---->"<<(*ite)->to->value<<endl;
ite++;
}
cout<<endl<<"-----------------------------------------------"<<endl ;
4.完整代码
#include <iostream>
#include<unordered_map>
#include<unordered_set>
#include<list>
#include<vector>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class Edge;
class Node
{
public:
int value;
int out;
int in;
list<Node*> nexts;
list<Edge*> edges;
Node(int val,int inn = 0,int outt = 0):value(val),in(inn),out(outt){}
};
class Edge
{
public:
int weight;
Node* from;
Node* to;
Edge(int wgt,Node* f,Node* t):weight(wgt),from(f),to(t){}
};
class Graph
{
public:
unordered_map<int,Node*> nodes;
unordered_set<Edge*> edges;
Graph(){};
};
class GraphGenerator
{
public:
Graph createGraph(vector<vector<int> > matrix)
{
Graph graph;//需要graph的node和edge 、node有五个data、edge有三个data
for(int i = 0; i < matrix.size();++i)
{
int weight = matrix[i][0];
int from = matrix[i][1];
int to = matrix[i][2];
//Graph的node里不含有from节点、to节点时建上
if(graph.nodes.find(from) == graph.nodes.end())
graph.nodes[from] = new Node(from);
if(graph.nodes.find(to) == graph.nodes.end())
graph.nodes[to] = new Node(to);
//拿出from,to点
Node* fromNode = graph.nodes[from];
Node* toNode = graph.nodes[to];
//Node* fromNode = graph.nodes.find(from)->second;
//Node* toNode = graph.nodes.find(to)->second;
//新建边
Edge* newEdge = new Edge(weight, fromNode, toNode);
//增加节点的四个数据
fromNode->nexts.push_back(toNode);
fromNode->edges.push_back(newEdge);
fromNode->out++;
toNode->in++;
graph.edges.insert(newEdge);
}
return graph;
}
};
int main(int argc, char** argv) {
GraphGenerator g;
vector<vector<int> > matrix= {{7,1,2},{5,1,3},{2,2,3}};
Graph graph = g.createGraph(matrix);
//test
unordered_map<int,Node*>::iterator ite1 = graph.nodes.begin();
while(ite1 != graph.nodes.end())
{
cout << "节点: "<<(ite1)->second->value<<"、";
//cout << "节点: "<<(ite1)->first<<"、";
ite1++;
}
cout<<endl<<"-----------------------------------------------"<<endl ;
unordered_set<Edge*>::iterator ite = graph.edges.begin();
while(ite != graph.edges.end())
{
cout << "边权为 "<<(*ite)->weight<<" ";
cout<<(*ite)->from->value <<"---->"<<(*ite)->to->value<<endl;
ite++;
}
cout<<endl<<"-----------------------------------------------"<<endl ;
return 0;
}