#ifndef HEAD_H_
#define HEAD_H__
#include <iostream>
#include <array>
#include <vector>
#include <queue>
#include <cassert>
#include <string>
#include <fstream>
#include<numeric>
#include<cmath>
#include<algorithm>
template <typename T>
using grap = std::vector<std::vector<T>>;
template <typename T>
class Graph
{
protected:
enum color
{
White,
black,
gray
};
struct Node
{
//T data;
struct Node* next;
struct Node* parents;
std::size_t index; //顶点编号
int color; //顶点得颜色,记录访问标志
double distance; //距离指标记号
int full_time;
Node(std::size_t i) : index(i)
{
next = nullptr;
parents = nullptr;
color = White;
distance = 0;
full_time = 0; //深度优先遍历之用
}
};
using node = struct Node;
using pnode = struct Node*;
std::size_t size;
std::vector<pnode> Matrix;
std::vector<std::vector<T>> Weight; //权重矩阵
void insert(pnode& phead, pnode pnew);
pnode root; //广度优先树的根节点
std::vector<std::string>area;
int find_index(std::string area_);
//打印路径
private:
//bool success(); //检验邻接表是否创建成
//自定义排序函数(冒泡排序规则)
void Sort(std::vector<pnode>& Array);
grap<T> graph; //邻接矩阵
void Initialize_Graph(); //初始化图
void DFS_VISIT(pnode vertex); //DFS辅助函数
void convert_to_list(); //将邻接矩阵转换为邻接表的形式
void printMinDistance(std::size_t i,bool f);
//Bellman-Ford算法的部分
//建立边的存储的数据结构
struct edge {
std::size_t from;
std::size_t to;
T weight;
edge(std::size_t f, std::size_t t,T w) :from(f), to(t),weight(w) {}
};
//使用邻接表建立最小路径树
//case1 建立边的存储
std::vector<edge>E;
void build_edge();
//路径松弛函数(Bellman_ford算法的松弛函数)
bool RELAX(edge e);
bool Bellman_Ford(std::size_t i);
//狄杰特斯拉算法的松弛函数
void RELAX(pnode& u, pnode& v);
//算法的具体步骤
void Dijsktra(std::size_t i);
void print_path(std::size_t i, std::size_t j);//打印路径的函数
public:
Graph() = default;
Graph(grap<T> g) : graph(g) { convert_to_list(); };
Graph(grap<T>g, grap<T>w) :graph(g),Weight(w) {
convert_to_list();
};
Graph(std::string path);
//重载一个从文件读入邻接矩阵和权重矩阵的构造函数
Graph(std::string path1, std::string path2);
void check_AToB(std::string area_);
void print_Graph();
void BFS(std::size_t i,bool print); //广度优先遍历
void DFS(); //时间复杂度为\Theta(|V|+|E|)
void MIN_RODD(std::size_t index,std::size_t mode,bool road);
};
template <typename T>
void Graph<T>::convert_to_list()
{
size = graph.size();
//初始化邻接矩阵
for (std::size_t t = 0; t < size; t++)
{
Matrix.push_back(new Node(t)); //从0开始编号
}
//根据邻接矩阵构造邻接表
for (std::size_t i = 0; i < size; i++)
{
for (std::size_t j = 0; j < size; j++)
{
if (graph[i][j] == 1)
{
//i-->j存在边得话
pnode pnew = new Node(j);
insert(Matrix[i], pnew);
}
}
}
//assert(success() == true);
}
template<typename T>
void Graph<T>::Sort(std::vector<pnode>& Array)
{
for (size_t i = 0; i < Array.size(); i++)
{
for (size_t j = Array.size() - 1; j >= i + 1; j--)
{
if (Array[j]->distance >= Array[j - 1]->distance)
{
std::swap(Array[j], Array[j - 1]);
}
}
}
}
template<typename T>
void Graph<T>::Initialize_Graph()
{
//初始化邻接表即可
for (auto s : Matrix)
{
pnode pcur = s;
while (pcur != nullptr)
{
pcur->parents = nullptr;
pcur->full_time = 0;
pcur->distance = 0;
pcur->color = White;
pcur = pcur->next;
}
}
}
template <typename T>
void Graph<T>::printMinDistance(std::size_t i,bool f)
{
if (f == false) {
for (auto m : Matrix)
{
std::cout << m->index << "-->" << i << "min:" << m->distance << std::endl;
}
}
else if (f == true)
{
//按照文件中的区域打印
for (auto m : Matrix)
{
std::cout << area[m->index] << "-->" << area[i] << "min:" << m->distance << std::endl;
}
}
}
template<typename T>
void Graph<T>::build_edge()
{
//根据邻接表建立边的存储
for (size_t i = 0; i < graph.size(); i++)
{
for (size_t j = 0; j < graph[i].size(); j++)
{
if (graph[i][j] == 1)
{
auto e = edge(i, j, Weight[i][j]);
E.push_back(e);
}
}
}
}
template<typename T>
bool Graph<T>::RELAX(edge e)
{
if (Matrix[e.to]->distance > (Matrix[e.from]->distance + e.weight))
{
Matrix[e.to]->distance = (Matrix[e.from]->distance + e.weight);
Matrix[e.to]->parents = Matrix[e.from];
return true;
}
return false;
}
template<typename T>
void Graph<T>::RELAX(pnode& u, pnode& v)
{
if (Matrix[v->index]->distance > (Matrix[u->index]->distance + Weight[u->index][v->index]))
{
Matrix[v->index]->distance = (Matrix[u->index]->distance + Weight[u->index][v->index]);
Matrix[v->index]->parents = Matrix[u->index];
}
}
template<typename T>
void Graph<T>::Dijsktra(std::size_t i)
{
//初始化图
for (size_t j = 0; j < Matrix.size(); j++)
{
if (j != i)
{
Matrix[j]->distance = INFINITY;
Matrix[j]->parents = nullptr;
}
if (j == i)
{
Matrix[j]->distance = 0;
Matrix[j]->parents = nullptr;
}
}
std::vector<pnode>S;//swap
auto f = [](pnode p1, pnode p2)
{
if (p1->distance >= p2->distance)
{
return true;
}
return false;
};
std::vector<pnode>Matrix1 = Matrix;
while (!Matrix1.empty())
{
Sort(Matrix1);
auto index = Matrix1.size() - 1;
auto pcur1 = Matrix1[index];
auto pcur2 = Matrix1[index]->next;
Matrix1.pop_back();
S.push_back(pcur1);
while (pcur2!=nullptr)
{
RELAX(pcur1, pcur2);
pcur2 = pcur2->next;
}
}
}
template<typename T>
Graph<T>::Graph(std::string path1, std::string path2)
{
//读入邻接矩阵
std::string P = path1;
std::ifstream FILE(P, std::ios::in);
std::string line;
int flag1 = 0;
int flag2 = 0;
std::vector<std::vector<int>>Matrix;
while (std::getline(FILE, line))
{
std::istringstream L(line);
std::string n;
if (flag1 == 0)
{
while (std::getline(L, n, ','))
{
area.push_back(n);//加入地区
}
flag1++;
}
else
{
flag2 = 0;
std::vector<int>temp;
while (std::getline(L, n, ','))
{
if (flag2 != 0)
{
//读入邻接矩阵即可
temp.push_back(std::stoi(n));
}
flag2++;
}
Matrix.push_back(temp);
}
}
graph = Matrix;
convert_to_list();
FILE.close();//关闭文件
//读入权重矩阵
std::ifstream FILE2(path2, std::ios::in);
std::string line2;
int flag3 = 0;
std::vector<std::vector<int>>G;
while (std::getline(FILE2, line2))
{
std::vector<int>p;
std::stringstream ss(line2);
std::string n;
flag3 = 0;
while (std::getline(ss, n, ',')) {
if (flag3 != 0) { p.push_back(std::stoi(n)); }
flag3++;
}
G.push_back(p);
}
//开始填补空缺的部分
auto size = G.size();
for (std::size_t i = 0; i < G.size(); i++)
{
if (G[i].size() != size)
{
auto size2 = G[i].size();
for (size_t j = 0; j < size - size2; j++)
{
G[i].push_back(0);
}
}
}
Weight = G;
}
template<typename T>
void Graph<T>::check_AToB(std::string area_)
{
int limit;//限制的最小路径
auto index = find_index(area_);
assert(index != -1);
if (index != -1)
{
BFS(index,false);
}
//打印节点
std::cout << "Please enter a minimum limit path length:";
std::cin >> limit;
std::vector<int>p;
for (auto s:Matrix)
{
p.push_back(s->distance);
}
if ((std::accumulate(p.begin(), p.end(), 0)) >(limit * p.size()))
{
std::cout << "not exist" << std::endl;
}
else
{
std::cout << "exists" << std::endl;
printMinDistance(index,true);
}
}
template <typename T>
void Graph<T>::DFS()
{
Initialize_Graph();
for (auto s : Matrix)
{
if (s->color == White)
{
DFS_VISIT(s);
}
}
std::cout << std::endl;
auto check = [](std::vector<pnode> Matrix) {
auto len = 0;
for (auto s : Matrix)
{
if (s->color == black)
{
len++;
}
}
if (len == Matrix.size())
{
return true;
}
else
{
return false;
}
};
assert(check(Matrix) == true); //检验DFS得正确性是否成立
}
template<typename T>
void Graph<T>::MIN_RODD(std::size_t index, std::size_t mode,bool road)
{
/*
par1: index确定从哪一个顶点作为起始的顶点开始打印
par2: mode确定选择哪一个算法作为最短路径算法
par3: 是否打印最短路径(之前必须初始化area容器)
*/
assert(mode == 1 || mode == 2);//mode=1调用FORD算法 mode=2调用Dijstra算法
if (mode == 1)
{
Bellman_Ford(index);
}
else if(mode == 2)
{
Dijsktra(index);
}
//打印路径
if (road == true)
{
//printMinDistance(index, true);
for (size_t i = 0; i < area.size(); i++)
{
if (i != index)
{
print_path(index,i);
}
}
}
}
template<typename T>
bool Graph<T>::Bellman_Ford(std::size_t i)
{
//初始化
build_edge();
for (size_t j = 0; j < Matrix.size(); j++)
{
if (j != i)
{
Matrix[j]->distance = INFINITY;
Matrix[j]->parents = nullptr;
}
if (j == i)
{
Matrix[j]->distance = 0;
Matrix[j]->parents = nullptr;
}
}
//算法的部分
bool update;
for (size_t k = 1; k <Matrix.size(); k++)
{
for (std::size_t k2 = 0; k2 < E.size(); k2++)
{
//进行松弛
RELAX(E[k2]);
}
}
//检查算法的正确性
for (size_t p = 0; p <E.size() ; p++)
{
auto index_u = E[i].from;
auto index_v = E[i].to;
if (Matrix[index_v]->distance > (Matrix[index_u]->distance + Weight[index_u][index_v]))
{
return false;
}
}
return true;
}
template <typename T>
void Graph<T>::DFS_VISIT(pnode vertex)
{
vertex->color = gray;
Matrix[vertex->index]->color = gray;
std::cout << vertex->index << "\t";
pnode pcur = vertex->next;
while (pcur != nullptr)
{
if (pcur->color == White)
{
Matrix[pcur->index]->parents = vertex;
DFS_VISIT(pcur);
}
}
vertex->color = black;
Matrix[vertex->index]->color = black;
}
template <typename T>
void Graph<T>::BFS(std::size_t i,bool print)
{
Initialize_Graph();
std::size_t sum = Matrix.size(); //图得总共得节点得个数有多少
pnode first = Matrix[i]; //选择起始得节点
root = first; //设置广度优先树的根节点
first->color = gray;
std::queue<pnode> Q;
Q.push(first);
//开始遍历
std::cout << first->index << "\t";
std::size_t run_size = 1;
while (!Q.empty())
{
pnode e = Q.front();
Q.pop();
pnode pcur = e; //前驱
e = e->next;
while (e != nullptr)
{
auto index = e->index;
if (Matrix[index]->color == White)
{
Matrix[index]->color = gray;
std::cout << Matrix[index]->index << "\t";
Matrix[index]->distance = Matrix[pcur->index]->distance + 1;
Q.push(Matrix[index]);
run_size++;
}
e = e->next;
}
}
std::cout << std::endl;
if (print == true)
{
printMinDistance(i,false);
}
assert(run_size == sum);
}
template<typename T>
Graph<T>::Graph(std::string path)
{
std::string P = path;
std::ifstream FILE(P, std::ios::in);
std::string line;
int flag1 = 0;
int flag2 = 0;
std::vector<std::vector<int>>Matrix;
while (std::getline(FILE, line))
{
std::istringstream L(line);
std::string n;
if (flag1 == 0)
{
while (std::getline(L, n, ','))
{
area.push_back(n);//加入地区
}
flag1++;
}
else
{
flag2 = 0;
std::vector<int>temp;
while (std::getline(L, n, ','))
{
if (flag2 != 0)
{
//读入邻接矩阵即可
temp.push_back(std::stoi(n));
}
flag2++;
}
Matrix.push_back(temp);
}
}
graph = Matrix;
convert_to_list();
}
template <typename T>
void Graph<T>::print_Graph()
{
for (auto s : Matrix)
{
while (s != nullptr)
{
if (s->next == nullptr)
{
std::cout << s->index;
}
else
{
std::cout << s->index << "->";
}
s = s->next;
}
std::cout << std::endl;
}
std::cout << "-------------Adj-Matrix---------------" << std::endl;
for (auto s : graph)
{
for (auto s1 : s)
{
std::cout << s1 << "\t";
}
std::cout << std::endl;
}
std::cout << "---------------Weight-Matrix-------------" << std::endl;
for (auto w : Weight)
{
for (auto w1 : w)
{
std::cout << w1 << "\t";
}
std::cout << std::endl;
}
}
template <typename T>
void Graph<T>::insert(pnode &phead, pnode pnew)
{
assert(phead != nullptr);
pnode pcur = phead;
while (pcur->next != nullptr)
{
pcur = pcur->next;
}
pcur->next = pnew;
}
template<typename T>
int Graph<T>::find_index(std::string area_)
{
for (int i = 0; i < area.size(); i++)
{
if (area[i] == area_)
{
return i;
}
}
return -1;
}
template<typename T>
void Graph<T>::print_path(std::size_t i, std::size_t j)
{
//i是源节点 j是目的节点
pnode pcur = Matrix[j];
//保存到文件
std::ofstream FILE("out.txt", std::ios::app);
while (pcur!=Matrix[i]&&pcur!=nullptr)
{
//std::cout << pcur->index << "->";
std::cout << area[pcur->index] << "->";
FILE<< area[pcur->index] << "->";
pcur = pcur->parents;
}
/*for (auto s : Matrix) {
std::cout << s->distance << std::endl;
}*/
std::cout<<area[Matrix[i]->index]<< std::endl;
FILE << area[Matrix[i]->index] << "\n";
FILE.close();
}
#endif