图的深度优先搜索遍历实现

1、题目描述

对图的邻接矩阵和邻接表表示分别进行深度优先搜索遍历算法的实现。

2、设计思路

图的邻接矩阵表示方法中有一个记录各个顶点信息的顶点表和一个表示各个顶点之间关系的邻接矩阵。邻接矩阵中若两个顶点之间没有直接的边相连,则置为∞,否则存储边的信息。对于判断某顶点的度,判断两顶点之间是否有边比较方便,但对于稀疏图的存储尤其浪费空间。
图的邻接表中,同一个顶点发出的边链接在同一个边链表中,每一个链结点代表一条边,边结点中有另一顶点的下标dext和指针link,对于带权图,还要保存该边的权值cost。
无向图的邻接表如下图所示:在这里插入图片描述
邻接矩阵代码实现

#define DefaultVertices 20
#define maxWeight 2147483647    //无穷 
#include<iostream>
using namespace std; 
//邻接矩阵
template <class T, class E>
class Graph1
{
public:
	Graph1(int sz = DefaultVertices);
	~Graph1();
	//插入点
	void addVertices(T v);
	//插入边
	void addEdge(int i, int j, E e);
	//深度优先查找
	void DFSTraverse();
	void DFS(int i);
	friend istream& operator >> (istream& in, Graph1<T, E>& G);   //输入 
	friend ostream& operator << (ostream& out, Graph1<T, E>& G);  //输出 
	//顶点表
	T* VerticesList;        
	//邻接矩阵 
	E** Edge;
	//访问标志数组;
	int* visited;
	//图中最大顶点数 
	int maxVertices;  
	//当前顶点数 
	int numVertices; 
	//当前边数  
	int numEdges;  
	//给出顶点vertex在图中位置 
	int getVertexPos(T vertex)
	{      
		for (int i = 0; i < numVertices; i++)
		{
			if (VerticesList[i] == vertex)
			{
				return i;
			}
		}
		return -1;
	};
};

template <class T, class E>
Graph1<T,E>::Graph1(int sz)
{
	maxVertices = sz;
	numVertices = 0;
	numEdges = 0;
	visited = new int[maxVertices];
	int i, j;
	VerticesList = new T[maxVertices];  //创建顶点表   
	//邻接矩阵    
	Edge = (E**) new E * [maxVertices];
	for (i = 0; i < maxVertices; i++)
	{
		Edge[i] = new E[maxVertices];
	}    
	//矩阵初始化  
	for (i = 0; i < maxVertices; i++)
	{
		for (j = 0; j < maxVertices; j++)
		{
			Edge[i][j] = (i == j) ? 0 : maxWeight;
		}
	}

}

template <class T, class E>
Graph1<T, E>::~Graph1()
{
	delete[] VerticesList;
	for (int i = 0; i < numVertices; i++)
	{
		delete[] Edge[i];
	}
	delete[] Edge;
}

template <class T, class E>
void Graph1<T, E>::addVertices(T v)
{
	VerticesList[numVertices] = v;
	numVertices += 1;
}

template <class T, class E>
void Graph1<T, E>::addEdge(int i, int j, E e)
{
	Edge[i - 1][j - 1] = e;
	Edge[j - 1][i - 1] = e;
	numEdges++;
}

template <class T, class E>
void Graph1<T, E>::DFS(int i)
{
	int j;
	visited[i] = 1;
	cout << VerticesList[i] << " ";
	for ( j = 0; j < numVertices; j++)
	{
		if (Edge[i][j] == 1 && Edge[i][j] != maxWeight && !visited[j])
		{
			DFS(j);
		}
	}
}

template <class T, class E>
void Graph1<T, E>::DFSTraverse()
{
	int i;
	for ( i = 0; i < numVertices; i++)
	{
		visited[i] = 0;
	}
	for ( i = 0; i < numVertices; i++)
	{
		if (!visited[i])
		{
			DFS(i);
		}
	}
}

template <class T, class E>
ostream& operator << (ostream& out, Graph1<T, E>& G)
{
	int i, j;
	out << "节点个数" << G.numVertices << "边个数是:" << G.numEdges << "\n";
	out << "节点为:" << "\n";
	for ( i = 0; i < G.numVertices; i++)
	{
		out << G.VerticesList[i] << " ";
	}
	out << "\n";
	out << "邻接矩阵为:" << "\n";
	for ( i = 0; i < G.numVertices; i++)
	{
		for ( j = 0; j < G.numVertices; j++)
		{
			out << G.Edge[i][j] << " ";
		}
		out << "\n";
	}
	return out;
}
template <class T, class E>
void print(Graph1<T, E>& G)
{
	int i, j;
	cout << "节点个数" << G.numVertices << "边个数是:" << G.numEdges << "\n";
	cout << "节点为:" << "\n";
	for (i = 0; i < G.numVertices; i++)
	{
		cout << G.VerticesList[i] << " ";
	}
	cout << "\n";
	cout << "邻接矩阵为:" << "\n";
	for (i = 0; i < G.numVertices; i++)
	{
		for (j = 0; j < G.numVertices; j++)
		{
			cout << G.Edge[i][j] << " ";
		}
		cout << "\n";
	}
}

int main()
{
	int n = 0;
	Graph1<char, int> G;
	cout << "输入的节点数:";
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		char str;
		cin >> str;
		G.addVertices(str);
	}
	cout << "输入的边数:";
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		int a, b;
		cin >> a >> b;
		G.addEdge(a, b, 1);
	}
	print(G);  //输出邻接矩阵 
	cout<<"DFS搜索顺序:";
	G.DFSTraverse();
	return 0;
}

邻接表代码实现:

#include<iostream>
#define DefaultVertices 20
#define maxWeight 2147483647    //无穷 
using namespace std;
//邻接表
// 定义边表结点
template <class T, class E>
struct ArcNode
{
	int adjvex;// 邻接点域
	E wight;
	ArcNode<T,E>* next;

	ArcNode()
	{
		next = NULL;
	}

	ArcNode(E e,int i, ArcNode<T, E>* n = NULL)
	{
		wight = e;
		adjvex = i;
		next = n;
	}

};
// 定义顶点表结点
template <class T, class E>
struct VertexNode
{
	T data;
	ArcNode<T, E>* firstedge;

	VertexNode()
	{
		firstedge = NULL;
	}
};

template <class T, class E>
class Graph2
{
public:
	Graph2(int sz = DefaultVertices);
	~Graph2();
	//插入点
	void addVertices(T v);
	//插入边
	void addEdge(int i, int j, E e);
	//深度优先查找
	void DFSTraverse();
	void DFS(int i);
	//顶点表
	VertexNode<T,E>* VerticesList;
	//访问标志数组;
	int* visited;
	//图中最大顶点数 
	int maxVertices;
	//当前顶点数 
	int numVertices;
	//当前边数  
	int numEdges;
	//给出顶点vertex在图中位置 
	int getVertexPos(T vertex)
	{
		for (int i = 0; i < numVertices; i++)
		{
			if (VerticesList[i].data == vertex)
			{
				return i;
			}
		}
		return -1;
	};

};

template <class T, class E>
Graph2<T,E>::Graph2(int sz)
{
	maxVertices = sz;
	numVertices = 0;
	numEdges = 0;
	visited = new int[maxVertices];
	VerticesList = new VertexNode<T, E>[maxVertices];  //创建顶点表   

}

template <class T, class E>
Graph2<T, E>::~Graph2(){}

template <class T, class E>
void Graph2<T, E>::addVertices(T v)
{
	VerticesList[numVertices].data = v;
	numVertices++;
}

template <class T, class E>
void  Graph2<T, E>::addEdge(int i, int j, E e)
{
	ArcNode<T, E>* ptredge1 = NULL;
	ptredge1 = VerticesList[i].firstedge;
	while (ptredge1 != NULL)
	{
		ptredge1 = ptredge1->next;
	}
	ptredge1 = new ArcNode<T, E>(e, j);

	ArcNode<T, E>* ptredge2 = NULL;
	ptredge2 = VerticesList[j].firstedge;
	while (ptredge2 != NULL)
	{
		ptredge2 = ptredge2->next;
	}
	ptredge2 = new ArcNode<T, E>(e, i);
	numEdges++;
}

template <class T, class E>
void Graph2<T, E>::DFSTraverse()
{
	int i;
	for ( i = 0; i < numVertices; i++)
	{
		visited[i] = 0;
	}
	for (i = 0; i < numVertices; i++)
	{
		if (!visited[i])
		{
			DFS(i);
		}
	}
}

template <class T, class E>
void Graph2<T, E>::DFS(int i)
{
	ArcNode<T, E>* ptredge = NULL;
	visited[i] = 1;
	cout << VerticesList[i].data << " ";
	ptredge = VerticesList[i].firstedge;
	while (ptredge != NULL)
	{
		if (!visited[ptredge->adjvex])
		{
			DFS(ptredge->adjvex);
		}
		ptredge = ptredge->next;
	}
}

int main()
{
	
	int n = 0;
	Graph2<char, int> G;
	cout << "输入的节点数:";
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		char str;
		cin >> str;
		G.addVertices(str);
	}
	cout << "输入的边数:";
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		int a, b;
		cin >> a >> b;
		G.addEdge(a, b, 1);
	}
	cout << "DFS搜索序列:";
	G.DFSTraverse();
	cout << endl;
	return 0;
}

2. 系统设计 1.用到的抽象数据类型的定义 的抽象数据类型定义: ADT Graph{ 数据对象V:V是具有相同特性的数据元素的集合,称为顶点集 数据关系R: R={VR} VR={<v,w>|v,w∈V且P(v,w),<v,w>表从v到w的弧, 谓词P(v,w)定义了弧<v,w>的意义或信息} 基本操作P: CreatGraph(&G,V,VR) 初始条件:V是的顶点集,VR是中弧的集合 操作结果:按VVR的定义构造G DestroyGraph(&G) 初始条件:G存在 操作结果:销毁G InsertVex(&G,v) 初始条件:G存在,v中顶点有相同特征 操作结果:在G中增添新顶点v …… InsertArc(&G,v,w) 初始条件:G存在,vw是G中两个顶点 操作结果:在G中增添弧<v,w>,若G是无向的则还增添对称弧<w,v> …… DFSTraverse(G,Visit()) 初始条件:G存在,Visit是顶点的应用函数 操作结果:对进行深度优先遍历,在遍历中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 BFSTraverse(G,Visit()) 初始条件:G存在,Visit是顶点的应用函数 操作结果:对进行广度优先遍历,在遍历中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 }ADT Graph 栈的抽象数据类型定义: ADT Stack{ 数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0} 数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n} 约定an端为栈顶,ai端为栈底 基本操作: InitStack(&S) 操作结果:构造一个空栈S DestroyStack(&S) 初始条件:栈S已存在 操作结果:将S清为空栈 StackEmpty(S) 初始条件:栈S已存在 操作结果:若栈S为空栈,则返回TRUE,否则FALSE …… Push(&S,e) 初始条件:栈S已存在 操作结果:插入元素e为新的栈顶元素 Pop(&S,&e) 初始条件:栈S已存在且非空 操作结果:删除S的栈顶元素,并用e返回其值 StackTraverse(S,visit()) 初始条件:栈S已存在且非空 操作结果:从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则操作失效 }ADT Stack 队列的抽象数据类型定义: ADT Queue{ 数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0} 数据关系:Rl={<ai-1,ai>|ai-1,ai∈D,i=2,…,n} 约定其中ai端为队列头,an端为队列尾。 基本操作: InitQueue(&Q) 操作结果:构造一个空队列Q DestroyQueue(&Q) 初始条件:队列Q已存在 操作结果:队列Q被销毁,不再存在 QueueEmpty(Q) 初始条件:队列Q已存在 操作结果:若Q为空队列,则返回TRUE,否则FALSE …… EnQueue(&Q,e) 初始条件:队列Q已存在 操作结果:插入元素e为Q的新的队尾元素 DeQueue(&Q,&e) 初始条件:Q为非空队列 操作结果:删除Q的队头元素,并用e返回其值 }ADT Queue 2.主序的流: 调用CreateDN函数创建邻接表G; 调用PrintDN函数输出邻接表G; 调用DFSTraverse函数深度优先遍历; 调用BFSTraverse函数广度优先遍历
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值