Graph类定义图的基本信息(边与顶点)的相关内容,以及广度优先算法与深度优先算法等。
#pragma once
#include
#include // INT_MAX
#include "../dsa_queue_20200717/queue.h"
#include "../dsa_stack_20200716/stack.h"
namespace dtl
{
// 顶点状态
enum class VertexStatus {
// 未发现
undiscovered,
// 已发现
discovered,
// 已访问
visited,
};
// 边状态
enum class EdgeStatus {
// 未处置
undetermined,
// 树边
tree,
// 跨边
cross,
// 前向边
forward,
// 后向边
backward,
};
// class of GRAPH
template <typename Tv, typename Te>
class Graph
{
private:
// 所有顶点、边的辅助信息复位
void reset() {
for (int i = 0; i < n; i++) {
status(i) = VertexStatus::undiscovered;
dTime(i) = fTime(i) = -1;
parent(i) = -1;
priority(i) = INT_MAX;
for (int j = 0; j < n; j++) {
if (exists(i, j))
type(i, j) = EdgeStatus::undetermined;
}
}
}
// breadth first search
void BFS(int v, int& clock) {
#if DSA_MODE
printf("BFS in with v=%d, clock=%d\n", v, clock);
#endif
Queue<int> queue;
status(v) = VertexStatus::discovered;
queue.enqueue(v);
#if DSA_MODE
printf("vetex v=%d", v); print(vertex(v)); printf(" status changed to VertexStatus::discovered\n");
printf("current Q: "); print(queue);
#endif
while (!queue.empty()) {
int v = queue.dequeue();
dTime(v) = ++clock;
#if DSA_MODE
printf("visiting vertex v=%d", v); print(vertex(v)); printf("["); print(status(v)); printf("] dTime=%d\n", clock);
#endif
for (int u = firstNbr(v); -1 < u; u = nextNbr(v, u)) {
#if DSA_MODE
printf("visiting vertex u=%d", u); print(vertex(u)); printf("["); print(status(u)); printf("]\n");
#endif
if (status(u) == VertexStatus::undiscovered) {
status(u) = VertexStatus::discovered;
queue.enqueue(u);
type(v, u) = EdgeStatus::tree;
parent(u) = v;
} else {
type(v, u) = EdgeStatus::cross;
}
#if DSA_MODE
printf("edge(%d, %d) ", v, u); print(vertex(v)); printf(" ->"); print(vertex(u)); printf(" now is "); print(type(v, u)); printf("\n");
#endif
}
status(v) = VertexStatus::visited;
#if DSA_MODE
printf("vetex v=%d", v); print(vertex(v)); printf(" status changed to VertexStatus::visited\n");
printf("current Q: "); print(queue);
#endif
}
}
//! depth first search
void DFS(int v, int& clock) {
#if DSA_MODE
printf("DFS in with v=%d, clock=%d\n", v, clock);
#endif
dTime(v) = ++clock;
status(v) = VertexStatus::discovered;
#if DSA_MODE
printf("vetex v=%d", v); print(vertex(v)); printf(" status changed to VertexStatus::discovered dTime=%d\n", clock);
#endif
for (int u = firstNbr(v); -1 < u; u = nextNbr(v, u)) {
#if DSA_MODE
printf("visiting vertex u=%d", u); print(vertex(u)); printf("["); print(status(u)); printf("]\n");
#endif
switch (status(u)) {
case VertexStatus::undiscovered:
type(v, u) = EdgeStatus::tree;
parent(u) = v;
DFS(u, clock);
break;
case VertexStatus::discovered:
type(v, u) = EdgeStatus::backward;
break;
default: // VertexStatus::visited
type(v, u) = dTime(v) < dTime(u) ? EdgeStatus::forward : EdgeStatus::cross;
break;
}
#if DSA_MODE
printf("edge(%d, %d) ", v, u); print(vertex(v)); printf(" ->"); print(vertex(u)); printf(" now is "); print(type(v, u)); printf("\n");
#endif
}
status(v) = VertexStatus::visited;
fTime(v) = ++clock;
#if DSA_MODE
printf("vetex v=%d", v); print(vertex(v)); printf(" status changed to VertexStatus::visited fTime=%d\n", clock);
#endif
}
//! topological sort
bool TSORT(int v, int& clock, Stack<Tv>* s) {
assert(0 <= v && v < n);
#if DSA_MODE
printf("TSORT in with v=%d, clock=%d\n", v, clock);
printf("statck="); print(s);
#endif
dTime(v) = ++clock;
status(v) = VertexStatus::discovered;
#if DSA_MODE
printf("vetex v=%d", v); print(vertex(v)); printf(" status changed to VertexStatus::discovered dTime=%d\n", clock);
#endif
for (int u = firstNbr(v); -1 < u; u = nextNbr(v, u)) {
#if DSA_MODE
printf("visiting vertex u=%d", u); print(vertex(u)); printf("["); print(status(u)); printf("]\n");
#endif
switch (status(u)) {
case VertexStatus::undiscovered:
parent(u) = v;
type(v, u) = EdgeStatus::tree;
#if DSA_MODE
printf("edge(%d, %d) ", v, u); print(vertex(v)); printf(" ->"); print(vertex(u)); printf(" now is "); print(type(v, u)); printf("\n");
#endif
if (!TSORT(u, clock, s)) {
return false;
}
break;
case VertexStatus::discovered:
type(v, u) = EdgeStatus::backward;
#if DSA_MODE
printf("edge(%d, %d) ", v, u); print(vertex(v)); printf(" ->"); print(vertex(u)); printf(" now is "); print(type(v, u)); printf("\n");
#endif
return false;
break;
default: // visited
type(v, u) = (dTime(v) < dTime(u)) ? EdgeStatus::forward : EdgeStatus::cross;
#if DSA_MODE
printf("edge(%d, %d) ", v, u); print(vertex(v)); printf(" ->"); print(vertex(u)); printf(" now is "); print(type(v, u)); printf("\n");
#endif
break;
}
}
status(v) = VertexStatus::visited;
s->push(vertex(v));
#if DSA_MODE
printf("vetex v=%d", v); print(vertex(v)); printf(" status changed to VertexStatus::visited\n");
#endif
return true;
}
public:
//! 顶点总数
int n;
//! 插入顶点,返回编号
virtual int insert(Tv const& v) = 0;
//! 删除顶点及其关联边,返回该顶点
virtual Tv remove(int v) = 0;
//! 顶点数据(该顶点的确存在)
virtual Tv& vertex(int v) = 0;
//! 顶点的入度(该顶点的确存在)
virtual int inDegree(int v) = 0;
//! 顶点的出度(该顶点的确存在)
virtual int outDegree(int v) = 0;
//! 顶点的首个邻接顶点
virtual int firstNbr(int v) = 0;
//! 顶点v的(相对于顶点j的)下一个邻接顶点
virtual int nextNbr(int v, int j) = 0;
//! 顶点状态
virtual VertexStatus& status(int v) = 0;
//! 顶点 discovered time
virtual int& dTime(int v) = 0;
//! 顶点 finished time
virtual int& fTime(int v) = 0;
//! 顶点在遍历树中的父亲
virtual int& parent(int v) = 0;
//! 顶点在遍历树中的优先级
virtual int& priority(int v) = 0;
//! 边总数
int e;
//! 边(v,u)是否存在
virtual bool exists(int v, int u) = 0;
//! 在顶点v、u之间插入权重为w的边e
virtual void insert(Te const& e, int w, int v , int u) = 0;
//! 的喊出顶点v、u之间的边e,返回该边信息
virtual Te remove(int v, int u) = 0;
//! 边(v,u)的数据(该边的确存在)
virtual EdgeStatus& type(int v, int u) = 0;
//! 边(v,u)的权重
virtual int& weight(int v, int u) = 0;
//********* algorithms *********************//
//! 广度优先搜索
void bfs(int s) {
reset();
int clock = 0;
int v = s;
do {
if (VertexStatus::undiscovered == status(v)) {
BFS(v, clock);
}
} while (s != (v = (++v % n)));
}
//! 深度优先搜索
void dfs(int s) {
reset();
int clock = 0;
int v = s;
do {
if (VertexStatus::undiscovered == status(v)) {
DFS(v, clock);
}
} while (s != (v = (++v % n)));
}
//! 基于DFS的拓扑排序算法
Stack<Tv>* tsort(int s) {
assert(0 <= s && s < n);
reset();
int clock = 0, v = s;
auto S = new Stack<Tv>();
do {
if (status(v) == VertexStatus::undiscovered) {
if (!TSORT(v, clock, S)) {
S->clear();
break;
}
}
} while (s != (v = (++v % n)));
return S;
}
};
}
graphMatrisx类是图的实现方法之一——邻接矩阵的类。这个类主要致力于实现图这个数据结构。
#pragma once
#include "graph.h"
#include "../dsa_vector_200622/dsa_vector.h"
#include
namespace dtl
{
//! 顶点
template <typename T>
struct Vertex
{
T data;
int inDegree;//入度
int outDegree;//出度
VertexStatus status;//定点状态: 未发现undiscovered// 已发现discovered,// 已访问visited
//! discovered time
int dTime;
//! finished visit time
int fTime;
int parent;
int priority;//优先级
Vertex(T const& data = T(0))
: data(data)
, inDegree(0)
, outDegree(0)
, status(VertexStatus::undiscovered)
, dTime(-1)
, fTime(-1)
, parent(-1)
, priority(INT_MAX)
{}
};
//! 边
template <typename T>
struct Edge
{
T data;//数据
int weight;//权重
EdgeStatus status;//状态
Edge(T const& data, int weight)
: data(data)
, weight(weight)
, status(EdgeStatus::undetermined)
{}
};
//邻接矩阵
template <typename Tv, typename Te>
class GraphMatrix : public Graph<Tv, Te>
{
private:
//! vertexes
Vector<Vertex<Tv>> V;//顶点
//! edges
Vector<Vector<Edge<Te>*>> E;//边
public:
typedef Graph<Tv, Te> GraphType;
GraphMatrix() {
GraphType::n = GraphType::e = 0;
}
~GraphMatrix() {
for (int j = 0; j < GraphType::n; j++) {
for (int k = 0; k < GraphType::n; k++) {
delete E[j][k];
}
}
}
// vertex basic opration
virtual Tv& vertex(int i) { return V[i].data; }
virtual int inDegree(int i) { return V[i].inDegree; }
virtual int outDegree(int i) { return V[i].outDegree; }
virtual VertexStatus& status(int i) { return V[i].status; }
virtual int& dTime(int i) { return V[i].dTime; }
virtual int& fTime(int i) { return V[i].fTime; }
virtual int& parent(int i) { return V[i].parent; }
virtual int& priority(int i) { return V[i].priority; }
virtual int firstNbr(int i) { return nextNbr(i, GraphType::n); }
virtual int nextNbr(int i, int j) {
while ((-1 < j) && (!exists(i, --j))) {}
return j;
}
// vertex dynamic operation
virtual int insert(Tv const& vertex) {
for (int j = 0; j < GraphType::n; j++) {
E[j].insert(nullptr);
}
GraphType::n++;
E.insert(Vector<Edge<Te>*>(GraphType::n, GraphType::n, (Edge<Te>*)nullptr));
return V.insert(Vertex<Tv>(vertex));
}
virtual Tv remove(int i) {
assert(0 <= i && i < GraphType::n);
for (int j = 0; j < GraphType::n; j++) {
if (exists(i, j)) {
delete E[i][j];
V[j].inDegree--;
}
}
E.remove(i);
GraphType::n--;
Tv vBak = vertex(i);
V.remove(i);
for (int j = 0; j < GraphType::n; j++) {
if (Edge<Te>* e = E[j].remove(i)) {
delete e;
V[j].outDegree--;
}
}
return vBak;
}
// edge operation
virtual bool exists(int i, int j) {
return (0 <= i) && (i < GraphType::n) && (0 <= j) && (j < GraphType::n) && E[i][j] != nullptr;
}
virtual EdgeStatus& type(int i, int j) { assert(exists(i, j)); return E[i][j]->status; }
virtual Te& edge(int i, int j) { assert(exists(i, j)); return E[i][j]->data; }
virtual int& weight(int i, int j) { assert(exists(i, j)); return E[i][j]->weight; }
virtual void insert(Te const& edge, int weight, int i, int j) {
if (exists(i, j)) { return; }
E[i][j] = new Edge<Te>(edge, weight);
GraphType::e++;
V[i].outDegree++;
V[j].inDegree++;
}
virtual Te remove(int i, int j) {
assert(exists(i, j));
Te eBak = edge(i, j);
delete E[i][j];
E[i][j] = nullptr;
GraphType::e--;
V[i].outDegree--;
V[j].inDegree--;
return eBak;
}
};
}