代码拉取完成,页面将自动刷新
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <memory>
#include "UnionFindSet.h"
#include <set>
using namespace std;
namespace matrix
{
// V : vertice 数据顶点
// W : weight 权重,
// Direction: 判断图类型
template <class V, class W, W INT_MAX = INT32_MAX, bool Direction = false>
class Graph
{
public:
// 我们手动输入权值
Graph(const V *vertice, size_t n)
{
for (int i = 0; i < n; i++)
{
_vertices.push_back(vertice[i]);
// 构建顶点与下标的映射关系
_vertice_index[vertice[i]] = i;
}
_matrix.resize(n);
for (int i = 0; i < n; i++)
{
_matrix[i].resize(n, INT_MAX);
}
}
size_t GetIndex(const V &v)
{
auto it = _vertice_index.find(v);
if (it == _vertice_index.end())
{
// 顶点指针错误
// assert(1);
return -1;
}
return it->second;
}
// 手动添加顶点间关系,并赋权值
// 约定一下:有向是左 -> 右
void addedge(const V &v1, const V &v2, const W weight)
{
auto v1_index = GetIndex(v1);
auto v2_index = GetIndex(v2);
// 无向图
if (Direction == false)
{
_matrix[v1_index][v2_index] = weight;
_matrix[v2_index][v1_index] = weight;
}
else // 有向,则修改v2的坐标
{
_matrix[v1_index][v2_index] = weight;
}
}
void size_t_addedge(size_t v1, size_t v2, const W weight)
{
// 无向图
if (Direction == false)
{
_matrix[v1][v2] = weight;
_matrix[v2][v1] = weight;
}
else // 有向,则修改v2的坐标
{
_matrix[v2][v1] = weight;
}
}
void showgrapth()
{
int n = 0;
cout << "\t";
for (int i = 0; i < _vertices.size(); i++)
cout << i << "\t";
cout << endl;
for (auto i : _matrix)
{
cout << n++ << "\t";
for (auto n : i)
{
if (n == INT32_MAX)
cout << "*" << "\t";
else
cout << n << "\t";
}
cout << endl;
}
}
// 层序遍历————默认从0开始层序遍历
void BFS(const V &v)
{
auto index = GetIndex(v);
queue<int> q;
vector<bool> _set(_vertices.size(), false);
q.push(index);
cout << _vertices[index] << "->";
_set[index] = true;
while (q.empty() != true)
{
int tmp = q.front();
q.pop();
// 获取所有连接点,并判断载入队列
int time = 0;
while (time < _matrix[tmp].size())
{
if (_matrix[tmp][time] != INT_MAX && _set[time] == false)
{
q.push(time);
cout << _vertices[time] << " ";
_set[time] = true;
}
time++;
}
cout << "->";
}
cout << endl;
}
void _dfs(int index, vector<bool> &_set)
{
cout << _vertices[index] << "--";
for (int i = 0; i < _matrix[index].size(); i++)
{
if (_set[i] != true && _matrix[index][i] != INT_MAX)
{
_set[i] = true;
_dfs(i, _set);
}
}
}
void DFS(const V &v)
{
auto index = GetIndex(v);
vector<bool> _set(_vertices.size(), false);
_set[index] = true;
_dfs(index, _set);
cout << endl;
}
struct edge
{
size_t _v1;
size_t _v2;
W _w;
edge(size_t v1, size_t v2, W w)
: _v1(v1), _v2(v2), _w(w)
{
}
bool operator>(const edge &v1) const
{
return _w > v1._w;
}
};
W Kruskal(Graph<V, W> &minfree)
{
priority_queue<edge, vector<edge>, greater<edge>> greater_queue;
// 队列载入边信息
for (int i = 0; i < _matrix.size(); i++)
{
for (int j = 0; j < _matrix[i].size(); j++)
{
if (i >= j && _matrix[i][j] != INT_MAX)
greater_queue.push(edge(i, j, _matrix[i][j]));
}
}
size_t sum_edge = 0;
W sum_w = W();
UnionFindSet it(_vertices.size());
int time = _vertices.size() - 1;
while (sum_edge < time)
{
edge tmp = greater_queue.top();
if (it.IsSameRoot(tmp._v1, tmp._v2))
{
greater_queue.pop();
continue;
}
cout << _vertices[tmp._v1] << "->" << _vertices[tmp._v2] << ": " << tmp._w << endl;
// 单独构建一个外部最小生成树
minfree.size_t_addedge(tmp._v1, tmp._v2, tmp._w);
it._union(tmp._v1, tmp._v2);
greater_queue.pop();
sum_w += tmp._w;
sum_edge++;
}
// cout << "w : " << sum_w << endl;
// cout << "sum_edge : " << sum_edge << endl;
// cout << "_vertice : " << _vertices.size() << endl;
// 经过n - 1次连接边,如果所有顶点都在树中,则有最小生成树;
// 如何判断? 并查集,由于我们实现了压缩路径算法,所以所有孩子只有一个根。
int root = it.GetRoot(0);
for (int i = 1; i < it.size(); i++)
{
// 如果根不相同,说明还有孤岛顶点,即不是最小生成树
if (root != it.GetRoot(i))
return W();
}
return sum_w;
}
W Prim(Graph<V, W> &minfree, const V &start)
{
size_t ptr = GetIndex(start);
set<size_t> X;
set<size_t> Y;
for (int i = 0; i < _vertices.size(); i++)
Y.insert(i);
priority_queue<edge, vector<edge>, greater<edge>> greater_queue;
// 先载入开始顶点
X.insert(ptr);
Y.erase(ptr);
// 队列载入与顶点相连边的顶点信息
for (int i = 0; i < _matrix.size(); i++)
{
if (_matrix[ptr][i] != INT_MAX)
greater_queue.push(edge(ptr, i, _matrix[ptr][i]));
}
size_t edge_sum = 0;
W w_sum = 0;
while (greater_queue.empty() != true)
{
edge tmp = greater_queue.top();
if (X.find(tmp._v1) != X.end() && X.find(tmp._v2) != X.end())
{
greater_queue.pop();
continue;
}
// 不都在X中都载入
size_t new_X;
if (X.find(tmp._v1) == X.end())
new_X = tmp._v1;
else
new_X = tmp._v2;
// cout << _vertices[tmp._v1] << "->" << _vertices[tmp._v2] << ": " << tmp._w << endl;
minfree.size_t_addedge(tmp._v1, tmp._v2, tmp._w);
greater_queue.pop();
w_sum += tmp._w;
edge_sum++;
X.insert(new_X);
Y.erase(new_X);
for (int i = 0; i < _matrix.size(); i++)
{
if (_matrix[new_X][i] != INT_MAX)
greater_queue.push(edge(new_X, i, _matrix[new_X][i]));
}
}
// cout << "w : " << w_sum << endl;
// cout << "sum_edge : " << edge_sum << endl;
// cout << "_vertice : " << _vertices.size() << endl;
if (edge_sum != _vertices.size() - 1)
return W();
return w_sum;
}
// 最短路径
void Dijkstra(const V &v)
{
vector<W> dij_vec(_vertices.size(), INT_MAX);
vector<bool> exist(_vertices.size(), true);
int exist_sum = _vertices.size();
auto start_index = GetIndex(v);
dij_vec[start_index] = 0;
exist[start_index] = false;
exist_sum--;
while (exist_sum > 0)
{
// 在未被标记顶点内寻找
for (int i = 0; i < _matrix[start_index].size(); i++)
{
if (exist[i] && _matrix[start_index][i] != INT_MAX)
{
dij_vec[i] = min(dij_vec[i], (_matrix[start_index][i] + dij_vec[start_index]));
}
}
// 开始删除目前最小值
// 获取最小值下标
int index = -1;
size_t min_index = INT_MAX;
for (int i = 0; i < dij_vec.size(); i++)
{
if (exist[i] && dij_vec[i] < min_index)
{
min_index = dij_vec[i];
index = i;
}
}
// 删除已经确定的顶点
if (index != -1)
{
// cout << "delete: " << _vertices[index] << endl;
exist[index] = false;
start_index = index;
exist_sum--;
}
}
cout << "结果:" << endl;
for (int i = 0; i < dij_vec.size(); i++)
{
cout << _vertices[i] << " min:" << dij_vec[i] << endl;
}
}
bool Bellman_Ford(const V &v)
{
vector<W> bell_vec(_vertices.size(), INT_MAX);
vector<size_t> last_index(_vertices.size(), -1);
auto start_index = GetIndex(v);
bell_vec[start_index] = 0;
last_index[start_index] = 0;
int n = _vertices.size();
for (int z = 0; z < n; z++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (_matrix[i][j] != INT_MAX && bell_vec[i] + _matrix[i][j] < bell_vec[j])
{
bell_vec[j] = bell_vec[i] + _matrix[i][j];
last_index[j] = i;
}
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (_matrix[i][j] != INT_MAX && bell_vec[i] + _matrix[i][j] < bell_vec[j])
{
return false;
}
}
}
cout << "结果:" << endl;
for (int i = 0; i < n; i++)
{
cout << _vertices[i] << " min:" << bell_vec[i] << endl;
}
return true;
}
void Floyd_warshall()
{
vector<vector<W>> dis;
vector<vector<int>> parentpath;
int n = _vertices.size();
dis.resize(n);
parentpath.resize(n);
// 初始化权值图
// 初始化父路径图
for (int i = 0; i < n; i++)
{
dis[i].resize(n, INT_MAX);
parentpath[i].resize(n, -1);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (_matrix[i][j] != INT_MAX)
{
dis[i][j] = _matrix[i][j];
// 默认i->j就是最短路径,所以j的上一级就是i
parentpath[i][j] = i;
}
if (i == j)
dis[i][j] = 0;
}
}
// 用k作为中转点,试图获取i->k->j的最短路径
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (dis[i][k] != INT_MAX && dis[k][j] != INT_MAX && dis[i][k] + dis[k][j] < dis[i][j])
{
dis[i][j] = dis[i][k] + dis[k][j];
parentpath[i][j] = parentpath[k][j];
}
}
}
}
cout << "结果:" << endl;
for (int i = 0; i < n; i++)
{
cout << _vertices[i] << " min:" << endl;
for (int j = 0; j < n; j++)
{
cout << _vertices[j] << ":" << dis[i][j] << " ";
}
cout << endl;
}
}
private:
vector<V> _vertices; // 储存顶点, O(1)获取顶点信息
map<V, int> _vertice_index; // 通过key与数组下标构建映射关系,是上面O(1)获取顶点效率的前提。
vector<vector<W>> _matrix; // 矩阵构建连接及权值信息。
};
}
namespace list
{
template <class W, W INT_MAX = INT32_MAX>
struct V_Node
{
int _index;
// 权值
W _weigth;
V_Node<W> *_next;
V_Node(int index, const W &weigth = INT_MAX, V_Node<W> *next = nullptr)
: _index(index), _weigth(weigth), _next(next)
{
}
V_Node<W> *GetLast()
{
if (_next == nullptr)
return this;
V_Node<W> *tmp = _next;
while (tmp->_next != nullptr)
tmp = tmp->_next;
return tmp;
}
};
template <class V, class W, W INT_MAX = INT32_MAX, bool Direction = false>
class Graph
{
public:
typedef V_Node<W> v_node;
Graph(const V *vertice, size_t n)
{
for (int i = 0; i < n; i++)
{
_vertices.push_back(vertice[i]);
// 构建顶点与下标的映射关系
_vertice_index[vertice[i]] = i;
}
for (int i = 0; i < n; i++)
{
_list.push_back(new v_node(i));
}
}
~Graph()
{
// 真想用智能指针来负责析构,但类型出错真烦
}
size_t GetIndex(const V &v)
{
auto it = _vertice_index.find(v);
if (it == _vertice_index.end())
{
// 顶点指针错误
// assert(1);
return -1;
}
return it->second;
}
// 手动添加全值
// 约定一下:有向是左 -> 右
void addedge(const V &v1, const V &v2, const W weight)
{
auto v1_index = GetIndex(v1);
auto v2_index = GetIndex(v2);
// 无向图
if (Direction == false)
{
_list[v1_index]->GetLast()->_next = new v_node(v2_index, weight);
_list[v2_index]->GetLast()->_next = new v_node(v1_index, weight);
}
else // 有向图
{
_list[v1_index]->GetLast()->_next = new v_node(v2_index, weight);
;
}
}
void showgrapth()
{
for (auto i : _list)
{
cout << _vertices[i->_index] << "(w:" << i->_weigth << ")" << "-->";
while (i->_next != nullptr)
{
i = i->_next;
cout << _vertices[i->_index] << "(w:" << i->_weigth << ")" << "->";
}
cout << endl;
}
}
private:
vector<V> _vertices;
map<V, int> _vertice_index;
vector<v_node *> _list;
};
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。