图的两种存储,两种遍历

图的两种存储,两种遍历(邻接表,邻接矩阵,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;
}

记得给好评哦

已标记关键词 清除标记
相关推荐
课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下所示为本权限管理平台的数据库设计: 以下为项目整体的运行效果截: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下所示:
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页