#include<stack>
#include<queue>
#include"Edge.h"
#define VISITED 1 //已经访问过
#define UNVISITED 0 //未访问过
#define AFFINITY 999999 //最大值
using namespace std;
template<class EdgeType> //边的类,包括有向图的边的起始点,终点以及权值
class Edge {
public:
int start, end;
EdgeType weight;
Edge();
Edge(int st = -1, int en = -1, int w = -1) {
start = st;
end = en;
weight = w;
}
bool operator > (Edge oneEdge);//重载>
bool operator < (Edge oneEdge);//重载< //重载函数只给出声明
};
//图的类
template<class EdgeType>
class Graph
{
public:
int vertexNum;//顶点个数
int edgeNum; //表示边的个数
int* Mark; //用进行图的各种算法的辅助数组,并无实际意义
int** matrix; //指向邻接矩阵的指针
Graph(int verticesNum) {//构造函数(包括邻接矩阵的初始化
int i, j;
vertexNum = verticesNum;
edgeNum = 0;
Mark = new int[vertexNum];
for (int i = 0; i < vertexNum; i++) {
Mark[i] = UNVISITED;
}
matrix = (int**)new int*[vertexNum];
for (i = 0; i < vertexNum; i++) {
matrix[i] = new int[vertexNum];
}
for(i = 0;i<vertexNum;i++)
for (j = 0; i < vertexNum; j++) {
matrix[i][j] = 0;
}
}
~Graph() { //图的析构函数,包括析构辅助数组、邻接矩阵
delete[]Mark;
for (int i = 0; i < vertexNum; i++)
delete matrix[i];
delete matrix;
}
Edge<EdgeType> FirstEdge(int oneVertex) {//返回该顶点的第一条边,图的基本函数,为图的算法做准备
Edge<EdgeType> tmpEdge;
tmpEdge.start = oneVertex;
for (int i = 0; i < vertexNum; i++) {//找邻接矩阵当前行不为0的第一个值也就是第一条边
if (matrix[oneVertex][i] != 0) {
tmpEdge.end = i;
tmpEdge.weight = matrix[oneVertex][i];
break;
}
}
return tmpEdge;
}
Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge) {//返回与oneEdge有相同始点的下一条边
Edge<EdgeType> tmpEdge;
tmpEdge.start = oneEdge.start;
for (int i = oneEdge.end + 1; i < vertexNum; i++) {
if (matrix[oneEdge.start][i] != 0) {
tmpEdge.end = i;
tmpEdge.weight = matrix[oneEdge.start][i];
break;
}
}
return tmpEdge;
}
void setEdge(int start, int end,EdgeType weight = 0) {//新增一条边
if (matrix[start][end] == 0) {
edgeNum++;
}
matrix[start][end] = weight;
}
void delEdge(int start, int end) { //删除一条已经存在的边
if (matrix[start][end] != 0) {
edgeNum--;
}
matrix[start][end] = 0;
};
int VerticesNum() { //返回结点的数目
return vertexNum;
}
int EdgeNum() { //返回边的数目
return edgeNum;
}
bool IsEdge(Edge<EdgeType> oneEdge ) { //检测是否是当前图中的一个边
if (oneEdge.weight > 0)
return true;//如果是边,则就返回true
else
return false;
}
int StartVertex(Edge<EdgeType> oneEdge) {//返回始点
return oneEdge.start;
}
int EndVertex(Edge<EdgeType> oneEdge) {//返回结束点
return oneEdge.end;
}
int WeightVertex(Edge<EdgeType> oneEdge) {//返回边的权
return oneEdge.weight;
}
void DfsReverse(); //深度优先搜索递归
void DfsNoReverse(); //深度优先搜索非递归
void BfsNoReverse(int v);//广度优先搜索非递归
}
template<class EdgeType>
void Graph<EdgeType>::DfsReverse() {//递归的深度优先搜索算法
for (int i = 0; i < VerticesNum(); i++)
Mark[i] = UNVISITED;
for (int i = 0; i < VerticesNum; i++) {
if (Mark[i] == UNVISITED) {//检查图中是否有为未访问的结点,
DfsReverse(i); //如果有则从当前节点开始深度优先搜索
}
}
}
template<class EdgeType>
void Graph<EdgeType>::DfsNoReverse() {//深度优先搜索
int i, v, u;
stack <int> s;
for (i = 0; i < VerticesNum(); i++)
Mark[i] = UNVISITED;
for (i = 0; i < VerticesNum(); i++) {
if (Mark[i] == UNVISITED) {
s.push(i);
// visit(i); //访问方式未定
Mark[i] = VISITED;
while (!s.empty()) {
v = s.pop();
for (Edge<EdgeType> e = FirstEdge(v); IsEdge(e); e = NextEdge(e)) {
u = EndVertex(e);
if (Mark[u] == UNVISITED) {
s.push(u);
// visit(i);
Mark[u] = VISITED;
}
}
}
}
}
}
template<class EdgeType>
void Graph<EdgeType>::BfsNoReverse(int v) {
for (int i = 0; i < VerticesNum(); i++)
Mark[i] = UNVISITED;
queue<EdgeType> q;
Mark[v] = VISITED;
// visit(v);
q.push(v);
while (!q.empty()) {
v = q.front();
q.pop();
for (Edge<EdgeType> e = FirstEdge(v); IsEdge(v); e = NextEdge(e)) {
int u = EndVertex(e);
if (Mark[u] == UNVISITED) {
Mark[u]=VISITED;
// visit(EndVertex(e));
q.push(u);
}
}
}
}
在代码段中,展示了有向图的基本操作以及邻接矩阵的构造,邻接矩阵就是一个n*n的二维数组,用以储存边的信息。图的遍历包括广度优先搜索的非递归以及深度优先搜索的递归算法和非递归算法,在本类中也运用了多个辅助函数,譬如FirstEdge()、NextEdge()以及其他为了封装性而创建的函数。图的操作和树的操作具有很强的类似性。