图的两种存储,两种遍历(邻接表,邻接矩阵,DFS(递归与非递归),BFS)
//软1911
#include<iostream>
#include<queue>
#include<stack>
#include<math.h>
#define VISITED 1
#define UNVISITED 0
using namespace std;
template <class EdgeType>
class Edge//边类型
{
public:
int start, end;
EdgeType weight;
Edge()
{
start = 0;
end = 0;
}
Edge(int st, int en, EdgeType w)
{
start = st;
end = en;
weight = w;
}
bool operator > (Edge oneEdge)
{
return weight > oneEdge.weight;
}
bool operator < (Edge oneEdge)
{
return weight < oneEdge.weight;
}
};
template <class EdgeType>
class Graph//图类型
{
public:
int vertexNum;//图的顶点数目
int edgeNum;//图的边数目
int* Mark;//标记某顶点是否被访问过,访问过为1,没访问为0
Graph(int verticesNum)
{
vertexNum = verticesNum;
edgeNum = 0;
Mark = new int[verticesNum];
for (int i = 0; i < verticesNum; i++)
{
Mark[i] = UNVISITED;
}
}
~Graph()
{
delete[] Mark;
}
virtual Edge<EdgeType> FirstEdge(int onevertex) = 0;//返回与顶点相关联的第一条边
virtual Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge) = 0;//返回与oneedge有相同起点的下一条边
int VerticesNum()//返回图的顶点个数
{
return vertexNum;
}
int edgesnum()//返回边个数
{
return edgeNum;
}
bool Isedge(Edge<EdgeType> oneEdge)//判断是否为边
{
if (oneEdge.weight > 0 && oneEdge.weight < INFINITY && oneEdge.end >= 0)
return true;
else
return false;
}
int StartVertex(Edge<EdgeType> oneEdge)//返回边的始点
{
return oneEdge.start;
}
int EndVertex(Edge<EdgeType> oneEdge)//返回边的终点
{
return oneEdge.end;
}
EdgeType Weight(Edge<EdgeType> oneEdge)//返回边的权重
{
return oneEdge.weight;
}
virtual void setEdge(int start, int end, EdgeType weight) = 0;//设置边
virtual void delEdge(int start, int end) = 0;//删除边
void visit(int v)//访问结点
{
cout << v << ' ';
}
void DFS(int v)//从某顶点开始递归深度优先搜索
{
visit(v);
Mark[v] = VISITED;
for (Edge<EdgeType> e = FirstEdge(v); Isedge(e); e = NextEdge(e))
{
if (Mark[EndVertex(e)] == UNVISITED)
DFS(EndVertex(e));
}
}
void DFStraverse()//图的递归深度优先搜索
{
int i;
for (i = 0; i < VerticesNum(); i++)
Mark[i] = UNVISITED;
for (i = 0; i < VerticesNum(); i++)
{
if (Mark[i] == UNVISITED)
DFS(i);
}
}
void 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.top();
Edge<EdgeType> e;
for (e = FirstEdge(v); Isedge(e); e = NextEdge(e))
{
u = EndVertex(e);
if (Mark[u] == UNVISITED)
{
s.push(u);
visit(u);
Mark[u] = VISITED;
break;
}
}
if (!Isedge(e))
s.pop();
}
}
}
}
void BFS(int v)//从某结点开始广度优先搜索
{
queue<int> Q;
Mark[v] = VISITED;
visit(v);
Q.push(v);
while (!Q.empty())
{
v = Q.front();
Q.pop();
for (Edge<EdgeType> e = FirstEdge(v); Isedge(e); e = NextEdge(e))
{
int u = Mark[EndVertex(e)];
int m = EndVertex(e);
if (u == UNVISITED)
{
visit(m);
Mark[m] = VISITED;
Q.push(m);
}
}
}
}
void BFStraverse()//图的广度优先搜索
{
int v;
for (v = 0; v < VerticesNum(); v++)
Mark[v] = UNVISITED;
for (v = 0; v < VerticesNum(); v++)
{
if (Mark[v] == UNVISITED)
BFS(v);
}
}
};
template <class EdgeType>
class AdjGraph :public Graph<EdgeType>//图的邻接矩阵表示
{
private:
int** matrix;
public:
AdjGraph(int ver) :Graph<EdgeType>::Graph(ver)
{
int i, j;
matrix = (int**)new int* [ver];
for (i = 0; i < ver; i++)
matrix[i] = new int[ver];
for (i = 0; i < ver; i++)
for (j = 0; j < ver; j++)
matrix[i][j] = 0;//存权重
}
~AdjGraph()
{
for (int i = 0; i < this->vertexNum; i++)
delete[]matrix[i];
delete[]matrix;
}
Edge<EdgeType> FirstEdge(int onevertex)//返回与顶点相关联的第一条边
{
Edge<EdgeType> tmpEdge;
tmpEdge.start = onevertex;
for (int i = 0; i < this->vertexNum; i++)
{
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 < this->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)//为图新增一条边
{
if (matrix[start][end] == 0)
this->edgeNum++;
matrix[start][end] = weight;
}
void delEdge(int start, int end)//删除一条边
{
if (matrix[start][end] != 0)
this->edgeNum--;
matrix[start][end] = 0;
}
};
template<class EdgeType>
class listData //邻接表边结点的数据部分定义
{
public:
int vertex; //边的终点
EdgeType weight; //边的权
};
template<class Elem> //定义边结点
class ListNode {
public:
Elem element; //边结点的数据
ListNode<Elem>* next; //边结点指针,指向下一个边结点
ListNode(const Elem& elemval, ListNode<Elem>* nextval = NULL) { element = elemval; next = nextval; }
ListNode(ListNode<Elem>* nextval = NULL) { next = nextval; }
};
template<class Elem>
class EdgeList { //每个顶点所关联的边表
public:
ListNode<Elem>* head; //head指针
EdgeList() { //构造函数
head = new ListNode<Elem>();
}
void removeall() //释放边表所有边结点占据的空间
{
ListNode<Elem>* tmp;
while (head != NULL) //逐步释放每个边结点占据的空间
{
tmp = head;
head = head->next;
delete tmp;
}
}
~EdgeList() { removeall(); } //析构函数
};
template <class EdgeType>
class ListGraph : public Graph<EdgeType> //图的邻接表表示
{
private:
EdgeList<listData<EdgeType>>* graList;
//graList是保存所有边表的数组
public:
ListGraph(int verticesNum) :Graph<EdgeType>::Graph(verticesNum) //构造函数
{//申请空间,有vertexNum个顶点则有vertexNum个边表
graList = new EdgeList<listData<EdgeType>>[this->vertexNum];
}
~ListGraph() //析构函数
{
delete[] graList;
}
Edge<EdgeType> FirstEdge(int oneVertex) //返回顶点oneVertex的第一条边
{
Edge<EdgeType> tmpEdge; //将边tmpEdge作为函数的返回值
tmpEdge.start = oneVertex;
ListNode<listData<EdgeType>>* temp = graList[oneVertex].head; //graList[oneVertex].head保存的是顶点oneVertex的边表, //temp->next指向顶点oneVertex的第一条边(如果temp->next不为null)
if (temp->next != NULL) //顶点oneVertex的第一条边存在
{
tmpEdge.end = temp->next->element.vertex;
tmpEdge.weight = temp->next->element.weight;
}
return tmpEdge;
}
Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)
{//返回与边OneEdge有相同关联顶点的下一条边
Edge<EdgeType> tmpEdge;
tmpEdge.start = oneEdge.start;
ListNode<listData<EdgeType>>* temp = graList[oneEdge.start].head;
//确定边oneEdge在边表中的位置,如果边oneEdge的下一条边确实存在,
//则temp->next指针指向下一条边的表目
while (temp->next != NULL && temp->next->element.vertex <= oneEdge.end)
temp = temp->next;
if (temp->next != NULL) //边oneEdge的下一条边存在
{
tmpEdge.end = temp->next->element.vertex;
tmpEdge.weight = temp->next->element.weight;
}
return tmpEdge;
}
void setEdge(int start, int end, EdgeType weight)//为图设定一条边
{
ListNode<listData<EdgeType>>* temp = graList[start].head;
while (temp->next != NULL && temp->next->element.vertex < end)
//确定边(start,end)或<start,end>在边表中的位置,如果不存在,则边 //(start,end)或<start,end>为新加的一条边
temp = temp->next;
if (temp->next == NULL)
{//边在边表中不存在且在边表中其后已无其他边,
//则在边表中加入这条边
temp->next = new ListNode<listData<EdgeType>>;
temp->next->element.vertex = end;
temp->next->element.weight = weight;
this->edgeNum++;
return;
}
if (temp->next->element.vertex == end) //边在边表中已存在
{
temp->next->element.weight = weight;
return;
}
if (temp->next->element.vertex > end)
{//边在边表中不存在,但在边表中其后存在其他边,
//则在边表中插入这条边
ListNode<listData<EdgeType>>* other = temp->next;
temp->next = new ListNode<listData<EdgeType>>;
temp->next->element.vertex = end;
temp->next->element.weight = weight;
temp->next->next = other;
this->edgeNum++;
}
}
void delEdge(int start, int end) //删掉图的一条边
{
ListNode<listData<EdgeType>>* temp = graList[start].head;
while (temp->next != NULL && temp->next->element.vertex < end)
temp = temp->next;
if (temp->next == NULL) return; //边不存在,不需任何操作
if (temp->next->element.vertex == end)//边存在,将其删掉
{
ListNode<listData<EdgeType>>* other = temp->next->next;
delete temp->next;
temp->next = other;
this->edgeNum--;
}
}
};
int main()
{
AdjGraph <int> tu(8); //图的邻接矩阵实现
//ListGraph <int> tu(8); //图的邻接表实现
tu.setEdge(0, 1, 1);
tu.setEdge(0, 2, 1);
tu.setEdge(1, 0, 1);
tu.setEdge(1, 3, 1);
tu.setEdge(1, 4, 1);
tu.setEdge(2, 0, 1);
tu.setEdge(2, 5, 1);
tu.setEdge(2, 6, 1);
tu.setEdge(3, 1, 1);
tu.setEdge(3, 7, 1);
tu.setEdge(4, 1, 1);
tu.setEdge(4, 7, 1);
tu.setEdge(5, 2, 1);
tu.setEdge(5, 6, 1);
tu.setEdge(6, 2, 1);
tu.setEdge(6, 5, 1);
tu.setEdge(7, 3, 1);
tu.setEdge(7, 4, 1);
cout << "深度优先遍历输出:";
tu.DFStraverse();
cout << endl << "非递归深度优先遍历输出:";
tu.DFSNoReverse();
cout << endl << "广度优先遍历输出:";
tu.BFStraverse();
cout << endl;
return 0;
}
记得给好评哦