哈工大数据结构作业4-图形结构及其应用

本文详细介绍了有向图的邻接矩阵和邻接表存储结构,并提供了相应的建立、转换算法。同时,实现了深度优先搜索(递归与非递归)和广度优先搜索算法,并分析了它们的时间复杂度和空间占用情况。在邻接矩阵和邻接表上分别进行了这两种搜索,展示了搜索结果,并进行了复杂度分析。
摘要由CSDN通过智能技术生成

  本文是笔者2020年秋哈工大数据结构作业4自己的代码,由于本人能力有限,可能存在一些错误,欢迎指出。

  本次作业是有向图和无向图二选一,笔者选的是有向图。

完整源代码链接:https://download.csdn.net/download/qq_45853731/20213288?spm=1001.2014.3001.5503

本文仅供参考,严禁抄袭!

作业题目:图的存储结构的建立与搜索

图的搜索(遍历)算法是图型结构相关算法的基础,本作业要求编写程序演示有向图典型存储结构的建立和搜索(遍历)过程。
 

存储结构

typedef struct {
	vector<char>vertex;
	int Matrix[Maxlength][Maxlength];
	int n, e;
}MTGraph;
typedef struct node{
	int adjvex;
	int cost;
	struct node* next;
}EdgeNode;
typedef struct {
	char vertex;
	EdgeNode* firstedge;
}VertexNode;
typedef struct {
	VertexNode verlist[Maxlength];
	int n, e;
}AdjGraph;
typedef struct {
	char vertex;
	char parent;
}GeneTree;
//下列vector存储搜索树
vector<GeneTree>DFSLinkTree;
vector<GeneTree>DFSLinkRecTree;
vector<GeneTree>DFSMatrixRecTree;
vector<GeneTree>DFSMatrixTree;
vector<GeneTree>BFSLinkTree;
vector<GeneTree>BFSMatrixTree;
bool visit[Maxlength];
int dfsorder[Maxlength];
int countdfs = 1;

 

分别实现有向图的邻接矩阵和邻接表存储结构的建立算法,分析和比较各建立算法的时间复杂度以及存储结构的空间占用情况

void ReadinMatrix(MTGraph &graph)//将图读入邻接矩阵
{
	ifstream in("map.txt");
	string read1,read2;//读入的第一行,存储的是顶点信息;第二行,存储的是边信息
	int i = 0,j = 0, weight, k;
	getline(in, read1);
	while (i < read1.length())
	{
		graph.vertex.push_back(read1[i]);
		graph.n++;
		i += 2;
	}
	getline(in, read2);
	in.close();
	while (j < read2.length())
	{
		weight = 0;
		k = j + 4;
		while (read2[k] <= '9' && read2[k] >= '0')
		{
			weight += int(read2[k] - '0');
			weight *= 10;
			k++;
		}
		weight /= 10;
		graph.Matrix[read2[j] - 'A'][read2[j + 2] - 'A'] = weight;
		graph.e++;
		j = k - 1;
		j += 2;
	}
}
void ReadinLink(AdjGraph& adjgraph)//读入邻接表
{
	ifstream in("map.txt");
	string read1, read2;//读入的第一行,存储的是顶点信息;第二行,存储的是边信息
	int i = 0, j = 0, weight, k;
	getline(in, read1);
	while (i < read1.length())
	{
		adjgraph.verlist[read1[i]-'A'].vertex=read1[i];
		adjgraph.verlist[read1[i] - 'A'].firstedge = NULL;
		adjgraph.n++;
		i += 2;
	}
	getline(in, read2);
	in.close();
	while (j < read2.length())
	{
		weight = 0;
		k = j + 4;
		while (read2[k] <= '9' && read2[k] >= '0')
		{
			weight += int(read2[k] - '0');
			weight *= 10;
			k++;
		}
		weight /= 10;
		EdgeNode* p = new EdgeNode, * q = adjgraph.verlist[read2[j] - 'A'].firstedge;
		if (q == NULL)
		{
			p->adjvex = int(read2[j + 2] - 'A');
			p->cost = weight;
			p->next = NULL;
			adjgraph.verlist[read2[j] - 'A'].firstedge = p;
		}
		else
		{
			while (q->next != NULL)
				q = q->next;
			p->adjvex = int(read2[j + 2] - 'A');
			p->cost = weight;
			p->next = NULL;
			q->next = p;
		}
		adjgraph.e++;
		j = k - 1;
		j += 2;
	}
}

实现有向图的邻接矩阵和邻接表两种存储结构的相互转换算法

void MatrixToLink(MTGraph matrix,AdjGraph &link)//邻接矩阵转邻接表
{
	for (int i = 0; i < matrix.n; i++)
	{
		link.verlist[i].vertex = matrix.vertex[i];
		link.verlist[i].firstedge = NULL;
		link.n++;
		for (int j = 0; j < matrix.n; j++)
		{
			if (matrix.Matrix[i][j] != 0)
			{
				EdgeNode* p = new EdgeNode, * q = link.verlist[i].firstedge;
				if (q == NULL)
				{
					p->adjvex = j;
					p->cost = matrix.Matrix[i][j];
					p->next = NULL;
					link.verlist[i].firstedge = p;
				}
				else
				{
					while (q->next != NULL)
						q = q->next;
					p->adjvex = j;
					p->cost = matrix.Matrix[i][j];
					p->next = NULL;
					q->next = p;
				}
				link.e++;
			}
		}
	}
}
void LinkToMatrix(MTGraph& matrix, AdjGraph link)//邻接表转邻接矩阵
{
	EdgeNode* p = NULL;
	for (int i = 0; i < link.n; i++)
	{
		matrix.vertex.push_back(link.verlist[i].vertex);
		matrix.n++;
		p = link.verlist[i].firstedge;
		while (p != NULL)
		{
			matrix.Matrix[i][p->adjvex] = p->cost;
			matrix.e++;
			p = p->next;
		}
	}
}

在上述两种存储结构上,分别实现有向图的深度优先搜索(递归和非递归) 和广度优先搜索算法。并以适当的方式存储和显示相应的搜索结果(深度优先或广度优先生成森林(或生成树)、深度优先或广度优先序列和编号)

void DFSMainLinkRec(AdjGraph link, int i)//递归对邻接表进行深度优先搜索
{
	EdgeNode* p = NULL;
	GeneTree node;
	DFSLinkRecTree.back().vertex = link.verlist[i].vertex;
	cout << countdfs<<":"<<link.verlist[i].vertex<<" ";
	visit[i] = true;
	dfsorder[i] = countdfs;
	countdfs++;
	p = link.verlist[i].firstedge;
	while (p)
	{
		if (!visit[p->adjvex])
		{
			node.parent = link.verlist[i].vertex;
			DFSLinkRecTree.push_back(node);
			DFSMainLinkRec(link, p->adjvex);
		}
		p = p->next;
	}
}
void DFSLinkRec(AdjGraph link)//递归深度优先搜索邻接表主程序
{
	GeneTree node;
	for (int i = 0; i < link.n; i++)
	{
		visit[i] = false;
	}
	for (int i= 0; i < link.n; i++)
	{
		if (!visit[i])
		{
			node.parent = '#';
			if(!DFSLinkRecTree.empty())
				DFSLinkRecTree.pop_back();
			DFSLinkRecTree.push_back(node);
			DFSMainLinkRec(link, i);
		}
	}
	cout << endl;
	cout << "深搜树或森林为:"<<endl;
	for (auto x : DFSLinkRecTree)
		cout << "节点为" << x.vertex << "," << "它的父节点为:" << x.parent << endl;
	cout << endl;
}
void DFSMainLink(AdjGraph link, int i)//非递归深度优先搜索邻接表
{
	EdgeNode* p = link.verlist[i].firstedge;
	char ch;
	stack<VertexNode>STACK;
	GeneTree node;
	DFSLinkTree.back().vertex = link.verlist[i].vertex;
	ch = link.verlist[i].vertex;
	cout << countdfs << ":" << link.verlist[i].vertex<<" ";
	visit[i] = true;
	dfsorder[i] = countdfs;
	countdfs++;
	STACK.push(link.verlist[i]);
	while (countdfs<=link.n)
	{
		while (p)
		{
			if (!visit[p->adjvex])
			{
				node.parent = ch;
				node.vertex = link.verlist[p->adjvex].vertex;
				DFSLinkTree.push_back(node);
				cout << countdfs << ":" << link.verlist[p->adjvex].vertex<<" ";
				visit[p->adjvex] = true;
				dfsorder[p->adjvex] = countdfs;
				countdfs++;
				STACK.push(link.verlist[p->adjvex]);
			}
			else
			{
				p = p->next;
				continue;
			}
			ch = link.verlist[p->adjvex].vertex;
			p = link.verlist[p->adjvex].firstedge;
		}
		STACK.pop();
		if (STACK.empty())
			break;
		else
		{
			p = STACK.top().firstedge;
			ch = STACK.top().vertex;
		}
	}
}
void DFSLink(AdjGraph link)//非递归深度优先搜索邻接表主程序
{
	GeneTree node;
	for (int i = 0; i < link.n; i++)
	{
		visit[i] = false;
	}
	countdfs = 1;
	for (int i = 0; i < link.n; i++)
	{
		if (!visit[i])
		{
			node.parent = '#';
			if (!DFSLinkTree.empty())
				DFSLinkTree.pop_back();
			DFSLinkTree.push_back(node);
			DFSMainLink(link, i);
		}
	}
	cout << endl;
	cout << "深搜树或森林为:" << endl;
	for (auto x : DFSLinkTree)
		cout << "节点为" << x.vertex << "," << "它的父节点为:" << x.parent << endl;
	cout << endl;
}
void DFSMainMatrix(MTGraph matrix, int i)//非递归深度优先搜索邻接矩阵
{
	stack<char>STACK;
	int j = 0, k=0;
	char ch;
	GeneTree node;
	DFSMatrixTree.back().vertex = matrix.vertex[i];
	cout << countdfs << ":" << matrix.vertex[i]<<" ";
	visit[i] = true;
	dfsorder[i] = countdfs;
	countdfs++;
	STACK.push(matrix.vertex[i]);
	j = i;
	while (countdfs <= matrix.n)
	{
		while(k<matrix.n)
		{
			if (matrix.Matrix[j][k]!=0&&!visit[k])
			{
				node.parent = matrix.vertex[j];
				node.vertex = matrix.vertex[k];
				DFSMatrixTree.push_back(node);
				cout << countdfs << ":" << matrix.vertex[k] << " ";
				visit[k] = true;
				dfsorder[k] = countdfs;
				countdfs++;
				STACK.push(matrix.vertex[k]);
				j = k;
				k = 0;
				continue;
			}
			k++;
		}
		STACK.pop();
		if (STACK.empty())
			break;
		else
		{
			ch = STACK.top();
			j = int(ch - 'A');
			k = 0;
		}
	}
}
void DFSMatrix(MTGraph matrix)//非递归深度优先搜索邻接矩阵主程序
{
	GeneTree node;
	for (int i = 0; i < matrix.n; i++)
	{
		visit[i] = false;
	}
	countdfs = 1;
	for (int i = 0; i < matrix.n; i++)
	{
		if (!visit[i])
		{
			node.parent = '#';
			if (!DFSMatrixTree.empty())
				DFSMatrixTree.pop_back();
			DFSMatrixTree.push_back(node);
			DFSMainMatrix(matrix, i);
		}
	}
	cout << endl;
	cout << "深搜树或森林为:" << endl;
	for (auto x : DFSMatrixTree)
		cout << "节点为" << x.vertex << "," << "它的父节点为:" << x.parent << endl;
	cout << endl;
}
void DFSMainRec(MTGraph matrix, int i)//递归深度优先搜索邻接矩阵
{
	GeneTree node;
	DFSMatrixRecTree.back().vertex = matrix.vertex[i];
	cout << countdfs << ":" << matrix.vertex[i] << " ";
	visit[i] = true;
	dfsorder[i] = countdfs;
	countdfs++;
	for (int j = 0; j < matrix.n; j++)
	{
		if (matrix.Matrix[i][j] != 0 && visit[j] == false)
		{
			node.parent = matrix.vertex[i];
			DFSMatrixRecTree.push_back(node);
			DFSMainRec(matrix, j);
		}
	}
}
void DFSMatrixRec(MTGraph matrix)//递归深度优先搜索邻接矩阵主程序
{
	countdfs = 1;
	GeneTree node;
	for (int i = 0; i < matrix.n; i++)
	{
		visit[i] = false;
	}
	countdfs = 1;
	for (int i = 0; i < matrix.n; i++)
	{
		if (!visit[i])
		{
			node.parent = '#';
			if (!DFSMatrixRecTree.empty())
				DFSMatrixRecTree.pop_back();
			DFSMatrixRecTree.push_back(node);
			DFSMainRec(matrix, i);
		}
	}
	cout << endl;
	cout << "深搜树或森林为:" << endl;
	for (auto x : DFSMatrixRecTree)
		cout << "节点为" << x.vertex << "," << "它的父节点为:" << x.parent << endl;
	cout << endl;
}
void BFSMainLink(AdjGraph link, int i)//广度优先搜索邻接表
{
	GeneTree node;
	EdgeNode* p = link.verlist[i].firstedge;
	VertexNode v;
	queue<VertexNode>QUEUE;
	cout << countdfs << ":" << link.verlist[i].vertex<<" ";
	visit[i] = true;
	dfsorder[i] = countdfs;
	countdfs++;
	QUEUE.push(link.verlist[i]);
	while (!QUEUE.empty())
	{
		v = QUEUE.front();
		node.parent = v.vertex;
		p = v.firstedge;
		QUEUE.pop();
		while (p)
		{
			if (!visit[p->adjvex])
			{
				cout << countdfs << ":" << link.verlist[p->adjvex].vertex<<" ";
				visit[p->adjvex] = true;
				dfsorder[p->adjvex] = countdfs;
				countdfs++;
				node.vertex = link.verlist[p->adjvex].vertex;
				BFSLinkTree.push_back(node);
				QUEUE.push(link.verlist[p->adjvex]);
			}
			p = p->next;
		}
	}
}
void BFSLink(AdjGraph link)//广度优先搜索邻接表主程序
{
	GeneTree node;
	for (int i = 0; i < link.n; i++)
	{
		visit[i] = false;
	}
	countdfs = 1;
	for (int i = 0; i < link.n; i++)
	{
		if (!visit[i])
		{
			node.parent = '#';
			node.vertex = link.verlist[i].vertex;
			BFSLinkTree.push_back(node);
			BFSMainLink(link, i);
		}
	}
	cout << endl;
	cout << "广搜树或森林为:" << endl;
	for (auto x : BFSLinkTree)
		cout << "节点为" << x.vertex << "," << "它的父节点为:" << x.parent << endl;
	cout << endl;
}
void BFSMainMatrix(MTGraph matrix, int i)//广度优先搜索邻接矩阵
{
	queue<char>QUEUE;
	GeneTree node;
	char ch;
	int j=0;
	cout << countdfs << ":" << matrix.vertex[i]<<" ";
	visit[i] = true;
	dfsorder[i] = countdfs;
	countdfs++;
	QUEUE.push(matrix.vertex[i]);
	while (!QUEUE.empty())
	{
		ch = QUEUE.front();
		node.parent = ch;
		j = 0;
		while (j < matrix.n && matrix.Matrix[ch - 'A'][j] == 0)
			j++;
		QUEUE.pop();
		while (j<matrix.n)
		{
			if (matrix.Matrix[ch-'A'][j]!=0&&!visit[j])
			{
				cout << countdfs << ":" << matrix.vertex[j]<<" ";
				visit[j] = true;
				dfsorder[j] = countdfs;
				countdfs++;
				node.vertex = matrix.vertex[j];
				BFSMatrixTree.push_back(node);
				QUEUE.push(matrix.vertex[j]);
			}
			j++;
		}
	}
}
void BFSMatrix(MTGraph matrix)//广度优先搜索邻接矩阵主程序
{
	GeneTree node;
	for (int i = 0; i < matrix.n; i++)
	{
		visit[i] = false;
	}
	countdfs = 1;
	for (int i = 0; i < matrix.n; i++)
	{
		if (!visit[i])
		{
			node.parent = '#';
			node.vertex = matrix.vertex[i];
			BFSMatrixTree.push_back(node);
			BFSMainMatrix(matrix, i);
		}
	}
	cout << endl;
	cout << "广搜树或森林为:" << endl;
	for (auto x : BFSMatrixTree)
		cout << "节点为" << x.vertex << "," << "它的父节点为:" << x.parent << endl;
	cout << endl;
}

复杂度分析

一、对邻接表进行深度优先搜索和广度优先搜索的复杂度分析:
  对邻接表进行深度优先搜索(广度优先搜索)的时间复杂度为O(n+e),n为顶点数,e为边数,这是因为,算法对每个顶点都访问一次,这部分的开销为O(n),而图的遍历过程是对每个顶点通过边查找邻接顶点的过程,这一过程开销为O(e),故总的时间复杂度为O(n+e);
  而空间复杂度为O(n),这是因为最坏的情况下需要将所有的顶点进入栈(队列).
二、对邻接矩阵进行深度优先搜索和广度优先搜索的复杂度分析:
  对邻接矩阵进行深度优先搜索(广度优先搜索)的时间复杂度为O(n^ 2),这是因为,在搜索过程中需要对邻接矩阵中的所有点进行判断,而邻接矩阵中一共有n^2个点;
  而空间复杂度为O(n),这是因为最坏的情况下需要将所有的顶点进入栈(队列).

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值