图
存储方式
- 邻接表
- 邻接矩阵
class Edge
{
public:
//权重
int weight;
//该边从from点指向to点
Node* from;
Node* to;
Edge(int w, Node* f, Node* t) :weight(w), from(f), to(t) {}
};
class Node
{
public:
//值
int value;
//入度
int in;
//出度
int out;
vector<Node*>nexts;
vector<Edge*>edges;
Node(int v) :value(v),in(0),out(0),nexts(vector<Node*>()),edges(vector<Edge*>()) {}
};
//图的结构
class Graph
{
public:
//int是点的编号
unordered_map<int, Node*>node;
unordered_set<Edge*>edge;
};
转化
Graph createGraph(vector<vector<int>>matrix)
{
Graph graph;
//from点:matrix[i][0] to点:matrix[i][1] 权重:matrix[i][2]
for (size_t i = 0; i < matrix.size(); i++)
{
int from = matrix[i][0];
int to = matrix[i][1];
int weight = matrix[i][2];
if (graph.node.find(from) == graph.node.end())
//from节点在结构中没有出现
graph.node.insert(make_pair(from, new Node(from)));
if (graph.node.find(to) == graph.node.end())
//to节点在结构中没有出现
graph.node.insert(make_pair(to, new Node(to)));
//下面操作时 肯定有from和to
//获取from和to
Node* fromNode = graph.node.at(from);
Node* toNode = graph.node.at(to);
Edge* newEdge = new Edge(weight, fromNode, toNode);
//在from节点的邻居加上to节点
fromNode->nexts.push_back(toNode);
//from出度加一
fromNode->out++;
//to的入度加一
toNode->in++;
//form指出的边
fromNode->edges.push_back(newEdge);
//把新建的边放到边集中
graph.edge.insert(newEdge);
}
return graph;
}
宽度优先遍历
- 利用队列实现
- 从源节点开始依次按照宽度进队列,然后弹出
- 每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
- 直到队列变空
//图的宽度优先遍历
void bfs(Node* node)
{
if (node == nullptr)return;
queue<Node*>q;
unordered_set<Node*>setHash;
q.push(node);
setHash.insert(node);
while (!q.empty())
{
Node* node = q.front();
q.pop();
cout << node->value << " ";
for (Node* cur : node->nexts)
{
if (setHash.find(cur) == setHash.end())
{
q.push(cur);
setHash.insert(cur);
}
}
}
}
深度优先遍历
- 准备一个栈
- 从源节点开始把节点按照深度放入栈,然后弹出
- 每弹出一个点,把该节点下一个没有进栈的邻接节点放入栈
- 直到栈空
一条路走到黑
//图的深度优先遍历
void depthFirstTraversal(Node* node)
{
if (node == nullptr)return;
stack<Node*>s;
unordered_set<Node*>setHash;
s.push(node);
setHash.insert(node);
cout << node->value << " ";
while (!s.empty())
{
Node* node = s.top();
s.pop();
for (auto& cur : node->nexts)
{
if (setHash.find(cur) == setHash.end())
{
cout << cur->value << " ";
setHash.insert(cur);
s.push(node);
s.push(cur);
//跳出循环
break;
}
}
}
}
拓扑排序算法
适用于有向图,有入度为0的节点,没有环
vector<int> topologySorting(Graph g)
{
//用来存放结果
vector<int>v;
//key:节点
//value:入度
//为了防止修改原来的图
unordered_map<Node*, int>mapHash;
//存放入度为0的节点
queue<Node*>in;
for (size_t i = 0; i < g.node.size(); i++)
{
Node* curNode = g.node.at(i);
mapHash.insert(make_pair(curNode, curNode->in));
if (curNode->in == 0)in.push(curNode);
}
while (!in.empty())
{
Node* node = in.front();
in.pop();
v.push_back(node->value);
for (auto& next : node->nexts)
{
mapHash.insert(make_pair(next, mapHash.find(next)->second--));
if (mapHash.find(next)->second == 0)in.push(next);
}
}
return v;
}
kruskal 算法
适用范围:无向图
生成最小生成树
//判断是否有环()
class MySets
{
public:
//节点 以及 对应的集合
unordered_map<Node*, vector<Node*>>setMap;
MySets(unordered_map<int, Node*>node)
{
for (auto &cur : node)
{
vector<Node*>n;
n.push_back(cur.second);
setMap.insert(make_pair(cur.second, n));
}
}
bool isSameSet(Node* &from, Node* &to)
{
return setMap.at(from) == setMap.at(to);
}
void union_(Node* &from, Node* &to)
{
vector<Node*>fromSet = setMap.at(from);
vector<Node*>toSet = setMap.at(to);
for (auto& toNode : toSet)
{
//把to节点集合中所有元素加到from对应集合中
fromSet.push_back(toNode);
//setMap.erase(toNode);
把to节点对应的集合的所有点所对应的集合变为from所属的集合
//setMap.insert(make_pair(toNode, fromSet));
}
for (auto& node : fromSet)
{
setMap.erase(node);
setMap.insert(make_pair(node, fromSet));
}
}
};
class C
{
public:
bool operator()(Edge*e1, Edge*e2)
{
return e1->weight > e2->weight;
}
};
//k算法生成最小生成树
set<int> kruskalMST(Graph &graph)
{
//小根堆
priority_queue<Edge*, vector<Edge*>, C>priorityQueue;
//生成集合
MySets mysets(graph.node);
//所有的边加到小根堆
for (auto edge : graph.edge)
priorityQueue.push(edge);
set<int> result;
while (!priorityQueue.empty())
{
Edge* e = priorityQueue.top();//最小的元素
priorityQueue.pop();
if (!mysets.isSameSet(e->from, e->to))
{
result.insert(e->weight);
//不在一个集合,加到一个集合
mysets.union_(e->from, e->to);
}
}
return result;
}
prim算法
适用范围:无向图
生成最小生成树
//p算法生成最小生成树
set<int> primMST(Graph& graph)
{
//小根堆
priority_queue<Edge*, vector<Edge*>, C>priorityQueue;
//存放节点,在这里面的节点代表着已经走过了
unordered_set<Node*>setNode;
set<int>result;
for (auto& node : graph.node)//防止森林结构(图可能不是连通的)
{
if (setNode.find(node.second) == setNode.end())
{
setNode.insert(node.second);
//初始节点所连接的边
for (auto& edge : node.second->edges)
priorityQueue.push(edge);
while (!priorityQueue.empty())
{
Edge* e = priorityQueue.top();//最小的
priorityQueue.pop();
if (setNode.find(e->to) == setNode.end())
{
setNode.insert(e->to);
result.insert(e->weight);
//下一个选中节点的边
for (auto& nextEdge : e->to->edges)
priorityQueue.push(nextEdge);
}
}
}
}
return result;
};
迪杰克斯拉算法
使用条件:没有权重累加和为负数的环
寻找一个节点到指定节点的最短路径
Node* getMinDistanceAndUnselectedNode(unordered_map<Node*, int>distanceMap, unordered_set<Node*>selectedNode)
{
Node* minNode = nullptr;
int minValue = INT32_MAX;
for (auto& node : distanceMap)
{
if (selectedNode.find(node.first) == selectedNode.end() && minValue > node.second)
{
minNode = node.first;
minValue = node.second;
}
}
return minNode;
}
//djkstra
unordered_map<Node*, int>dijkstra(Node* head)
{
unordered_map<Node*, int>distanceMap;//从Node*到head的最小距离是int
distanceMap.insert(make_pair(head, 0));
unordered_set<Node*>selectedNode;//记录已经被选择的节点
Node* minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNode);//选择最小的节点head
while (minNode != nullptr)
{
int distance = distanceMap.at(minNode);//最短距离
for (auto& edge : minNode->edges)//遍历该节点邻接的边
{
Node* node = edge->to;//边的另一头的点
if (distanceMap.find(node) == distanceMap.end())
distanceMap.insert(make_pair(node, distance + edge->weight));
else
//此处注意当key相同的时候
//使用insert插入会失败(无法做到替换的作用)
//使用下标可以替换
distanceMap[node] =(min(distanceMap.at(node), distance + edge->weight));
}
selectedNode.insert(minNode);
minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNode);
}
return distanceMap;
}
所有代码
#include<iostream>
#include<unordered_map>
#include<unordered_set>
#include<vector>
#include<queue>
#include<stack>
#include<set>
using namespace std;
class Node;
class Edge;
class Edge
{
public:
//权重
int weight;
//该边从from点指向to点
Node* from;
Node* to;
Edge(int w, Node* f, Node* t) :weight(w), from(f), to(t) {}
};
class Node
{
public:
//值
int value;
//入度
int in;
//出度
int out;
vector<Node*>nexts;
vector<Edge*>edges;
Node(int v) :value(v),in(0),out(0),nexts(vector<Node*>()),edges(vector<Edge*>()) {}
};
//图的结构
class Graph
{
public:
//int是点的编号
unordered_map<int, Node*>node;
unordered_set<Edge*>edge;
};
Graph createGraph(vector<vector<int>>matrix)
{
Graph graph;
//from点:matrix[i][0] to点:matrix[i][1] 权重:matrix[i][2]
for (size_t i = 0; i < matrix.size(); i++)
{
int from = matrix[i][0];
int to = matrix[i][1];
int weight = matrix[i][2];
if (graph.node.find(from) == graph.node.end())
//from节点在结构中没有出现
graph.node.insert(make_pair(from, new Node(from)));
if (graph.node.find(to) == graph.node.end())
//to节点在结构中没有出现
graph.node.insert(make_pair(to, new Node(to)));
//下面操作时 肯定有from和to
//获取from和to
Node* fromNode = graph.node.at(from);
Node* toNode = graph.node.at(to);
Edge* newEdge = new Edge(weight, fromNode, toNode);
//在from节点的邻居加上to节点
fromNode->nexts.push_back(toNode);
//from出度加一
fromNode->out++;
//to的入度加一
toNode->in++;
//form指出的边
fromNode->edges.push_back(newEdge);
//把新建的边放到边集中
graph.edge.insert(newEdge);
}
return graph;
}
//图的宽度优先遍历
void bfs(Node* node)
{
if (node == nullptr)return;
queue<Node*>q;
unordered_set<Node*>setHash;
q.push(node);
setHash.insert(node);
while (!q.empty())
{
Node* node = q.front();
q.pop();
cout << node->value << " ";
for (Node* cur : node->nexts)
{
if (setHash.find(cur) == setHash.end())
{
q.push(cur);
setHash.insert(cur);
}
}
}
}
//图的深度优先遍历
void depthFirstTraversal(Node* node)
{
if (node == nullptr)return;
stack<Node*>s;
unordered_set<Node*>setHash;
s.push(node);
setHash.insert(node);
cout << node->value << " ";
while (!s.empty())
{
Node* node = s.top();
s.pop();
for (auto& cur : node->nexts)
{
if (setHash.find(cur) == setHash.end())
{
cout << cur->value << " ";
setHash.insert(cur);
s.push(node);
s.push(cur);
//跳出循环
break;
}
}
}
}
vector<int> topologySorting(Graph g)
{
//用来存放结果
vector<int>v;
//key:节点
//value:入度
//为了防止修改原来的图
unordered_map<Node*, int>mapHash;
//存放入度为0的节点
queue<Node*>in;
for (size_t i = 0; i < g.node.size(); i++)
{
Node* curNode = g.node.at(i);
mapHash.insert(make_pair(curNode, curNode->in));
if (curNode->in == 0)in.push(curNode);
}
while (!in.empty())
{
Node* node = in.front();
in.pop();
v.push_back(node->value);
for (auto& next : node->nexts)
{
mapHash.insert(make_pair(next, mapHash.find(next)->second--));
if (mapHash.find(next)->second == 0)in.push(next);
}
}
return v;
}
//判断是否有环()
class MySets
{
public:
//节点 以及 对应的集合
unordered_map<Node*, vector<Node*>>setMap;
MySets(unordered_map<int, Node*>node)
{
for (auto &cur : node)
{
vector<Node*>n;
n.push_back(cur.second);
setMap.insert(make_pair(cur.second, n));
}
}
bool isSameSet(Node* &from, Node* &to)
{
return setMap.at(from) == setMap.at(to);
}
void union_(Node* &from, Node* &to)
{
vector<Node*>fromSet = setMap.at(from);
vector<Node*>toSet = setMap.at(to);
for (auto& toNode : toSet)
{
//把to节点集合中所有元素加到from对应集合中
fromSet.push_back(toNode);
//setMap.erase(toNode);
把to节点对应的集合的所有点所对应的集合变为from所属的集合
//setMap.insert(make_pair(toNode, fromSet));
}
for (auto& node : fromSet)
{
setMap.erase(node);
setMap.insert(make_pair(node, fromSet));
}
}
};
class C
{
public:
bool operator()(Edge*e1, Edge*e2)
{
return e1->weight > e2->weight;
}
};
//k算法生成最小生成树
set<int> kruskalMST(Graph &graph)
{
//小根堆
priority_queue<Edge*, vector<Edge*>, C>priorityQueue;
//生成集合
MySets mysets(graph.node);
//所有的边加到小根堆
for (auto edge : graph.edge)
priorityQueue.push(edge);
set<int> result;
while (!priorityQueue.empty())
{
Edge* e = priorityQueue.top();//最小的元素
priorityQueue.pop();
if (!mysets.isSameSet(e->from, e->to))
{
result.insert(e->weight);
//不在一个集合,加到一个集合
mysets.union_(e->from, e->to);
}
}
return result;
}
//p算法生成最小生成树
set<int> primMST(Graph& graph)
{
//小根堆
priority_queue<Edge*, vector<Edge*>, C>priorityQueue;
//存放节点
unordered_set<Node*>setNode;
set<int>result;
for (auto& node : graph.node)//防止森林结构(图可能不是连通的)
{
if (setNode.find(node.second) == setNode.end())
{
setNode.insert(node.second);
//初始节点所连接的边
for (auto& edge : node.second->edges)
{
priorityQueue.push(edge);
}
while (!priorityQueue.empty())
{
Edge* e = priorityQueue.top();//最小的
priorityQueue.pop();
if (setNode.find(e->to) == setNode.end())
{
setNode.insert(e->to);
result.insert(e->weight);
//下一个选中节点的边
for (auto& nextEdge : e->to->edges)
priorityQueue.push(nextEdge);
}
}
}
}
return result;
};
Node* getMinDistanceAndUnselectedNode(unordered_map<Node*, int>distanceMap, unordered_set<Node*>selectedNode)
{
Node* minNode = nullptr;
int minValue = INT32_MAX;
for (auto& node : distanceMap)
{
if (selectedNode.find(node.first) == selectedNode.end() && minValue > node.second)
{
minNode = node.first;
minValue = node.second;
}
}
return minNode;
}
//djkstra
unordered_map<Node*, int>dijkstra(Node* head)
{
unordered_map<Node*, int>distanceMap;//从Node*到head的最小距离是int
distanceMap.insert(make_pair(head, 0));
unordered_set<Node*>selectedNode;//记录已经被选择的节点
Node* minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNode);//选择最小的节点head
while (minNode != nullptr)
{
int distance = distanceMap.at(minNode);//最短距离
for (auto& edge : minNode->edges)//遍历该节点邻接的边
{
Node* node = edge->to;//边的另一头的点
if (distanceMap.find(node) == distanceMap.end())
distanceMap.insert(make_pair(node, distance + edge->weight));
else
distanceMap[node] =(min(distanceMap.at(node), distance + edge->weight));
}
selectedNode.insert(minNode);
minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNode);
}
return distanceMap;
}
int main()
{
vector<vector<int>>matrix;
vector<int>m1(3);
m1[0] = 1;
m1[1] = 2;
m1[2] = 7;
matrix.push_back(m1);
m1[0] = 2;
m1[1] = 1;
m1[2] = 7;
matrix.push_back(m1);
m1[0] = 1;
m1[1] = 3;
m1[2] = 2;
matrix.push_back(m1);
m1[0] = 3;
m1[1] = 1;
m1[2] = 2;
matrix.push_back(m1);
m1[0] = 1;
m1[1] = 4;
m1[2] = 100;
matrix.push_back(m1);
m1[0] = 4;
m1[1] = 1;
m1[2] = 100;
matrix.push_back(m1);
m1[0] = 2;
m1[1] = 4;
m1[2] = 1000;
matrix.push_back(m1);
m1[0] = 4;
m1[1] = 2;
m1[2] = 1000;
matrix.push_back(m1);
m1[0] = 2;
m1[1] = 5;
m1[2] = 10000;
matrix.push_back(m1);
m1[0] = 5;
m1[1] = 2;
m1[2] = 10000;
matrix.push_back(m1);
m1[0] = 3;
m1[1] = 4;
m1[2] = 4;
matrix.push_back(m1);
m1[0] = 4;
m1[1] = 3;
m1[2] = 4;
matrix.push_back(m1);
//m1[0] = 0;
//m1[1] = 1;
//m1[2] = 5;
//matrix.push_back(m1);
//m1[0] = 1;
//m1[1] = 2;
//m1[2] = 3;
//matrix.push_back(m1);
//m1[0] = 0;
//m1[1] = 2;
//m1[2] = 7;
//matrix.push_back(m1);
//m1[0] = 0;
//m1[1] = 3;
//m1[2] = 6;
//matrix.push_back(m1);
/*m1[0] = 1;
m1[1] = 2;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 2;
m1[1] = 1;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 1;
m1[1] = 3;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 3;
m1[1] = 1;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 1;
m1[1] = 4;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 4;
m1[1] = 1;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 3;
m1[1] = 5;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 5;
m1[1] = 3;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 4;
m1[1] = 5;
m1[2] = 1;
matrix.push_back(m1);
m1[0] = 5;
m1[1] = 4;
m1[2] = 1;
matrix.push_back(m1);*/
Graph graph = createGraph(matrix);
//bfs(graph.node[1]);
//cout << endl;
//depthFirstTraversal(graph.node[1]);
//vector<int> v = topologySorting(graph);
//for (auto i = v.begin(); i!=v.end(); i++)
//{
// cout << *i << " ";
//}
MySets mysets(graph.node);
//mysets.union_(graph.node.at(1), graph.node.at(2));
//cout<<mysets.isSameSet(graph.node.at(1), graph.node.at(2));
set<int> e = primMST(graph);
unordered_map<Node*, int>s = dijkstra(graph.node.at(1));
for (auto& x : s)
{
cout << x.first->value << ": "<<x.second<<endl;
}
return 0;
}