图的两种存储,两种遍历

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

记得给好评哦

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值