邻接矩阵存储图的两种遍历方式

下面是用邻接矩阵存储一个无向图的深度优先遍历和广度优先遍历代码,深度优先遍历就是树的先根遍历的一种推广,而广度优先也是和树的层次遍历相似的,用邻接矩阵存储,进行这两种遍历的实现,是比较容易的。

因为用了自己写的循环队列的模版,所以代码看起来有点冗长.

#include<iostream>
#include<string>
using namespace std;

//下面是循环队列模版
template<class T>
class My_queue;

template<class T>
class Node
{
private:
	T data;
	Node<T> *next;
public:
	Node()
	{
		next=0;
	}
	Node(T d)
	{
		data=d;
		next=0;
	}
	friend My_queue<T>;
};

template<class T>
class My_queue
{
private:
	Node<T> *tail;
public:
	My_queue()
	{
		tail=new Node<T>();
		tail->next=tail;
	}

	~My_queue()
	{
		clean();
		delete tail;
	}

	bool empty()
	{
		return (tail->next==tail);
	}

	void push(T d)
	{
		Node<T> *p=new Node<T>(d);
		p->next=tail->next;
		tail->next=p;
		tail=p;
	}

	T front()
	{
		if(empty())
		{
			cout<<"queue is empty!"<<endl;
			exit(0);
		}
		Node<T> *p=tail->next;
		T data=p->next->data;
		return data;
	}

	T back()
	{
		if(empty())
		{
			cout<<"queue is empty!"<<endl;
			exit(0);
		}
		T data=tail->data;
		return data;
	}

	void pop()
	{
		Node<T> *p=tail->next;
		Node<T> *q=p->next;
		p->next=q->next;
		if(q==tail)
			tail=p;
		delete q;
	}

	void clean()
	{
		Node<T> *p=tail->next;
		Node<T> *q=p->next;
		while(q!=p)
		{
			p->next=q->next;
			delete q;
			p->next=q;
		}
	}
};

#define MAX_VERTEX_NUM 20

bool visited[20];//全局数组,用于辅助遍历

struct MGraph
{
	string vexs[MAX_VERTEX_NUM];//顶点数组
	int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
	int vexnum;//顶点数目
	int arcnum;//边数目
};

int Locate_Vex(MGraph G,string x)  //用于确定顶点在顶点数组中的位置
{
	for(int k=0;G.vexs[k]!=x;k++);
	return k;
}

void CreateUDN_MG(MGraph &G)
{
	//采用邻接矩阵表示法,构造无向图
	int i,j,k;
	cout<<"输入图的顶点数和边数:";
	cin>>G.vexnum>>G.arcnum;
	cout<<"输入各个顶点的民称:";
	for(i=0;i<G.vexnum;i++)
		cin>>G.vexs[i];
	
	for(i=0;i<G.vexnum;i++)
		for(int j=0;j<G.vexnum;j++)
			G.arcs[i][j]=0;
	//上面是初始化邻接矩阵
	
	for(k=0;k<G.arcnum;k++)
	{
		cout<<"输入每条边对应的两个顶点:";
		string v1,v2;
		cin>>v1>>v2;
		i=Locate_Vex(G,v1);
		j=Locate_Vex(G,v2);
		while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)
		{
			cout<<"结点位置输入错误,重新输入: ";
			cin>>v1>>v2;
			i=Locate_Vex(G,v1);
			j=Locate_Vex(G,v2);	
		}
		G.arcs[i][j]=1;
		G.arcs[j][i]=G.arcs[i][j]; //置对称边
	}
	cout<<"图构造完成"<<endl;
}

void DFS(MGraph G,int v)
{
	visited[v]=true;
	cout<<G.vexs[v]<<"  ";
	for(int j=0;j<G.vexnum;j++)
		if(G.arcs[v][j] && !visited[j])
			DFS(G,j);
}

//深度优先遍历图
void DFS_Traverse(MGraph G)
{
	//visited数组用来作为是否已访问的标志
	for(int i=0;i<G.vexnum;i++)
		visited[i]=false;
	for(int v=0;v<G.vexnum;v++)
		if(!visited[v])
			DFS(G,v);
}

//广度优先遍历
void BFS_Traverse(MGraph G)
{
	My_queue<int> q;
	int u,w,v;
	for(v=0;v<G.vexnum;v++)
		visited[v]=false;
	for(v=0;v<G.vexnum;v++)
		if(!visited[v])
		{
			visited[v]=true;
			cout<<G.vexs[v]<<"  ";
			q.push(v);
			while(!q.empty())
			{
				u=q.front();
				q.pop();
				for(w=0;w<G.vexnum;w++)
					if(G.arcs[u][w] && !visited[w])
					{
						visited[w]=true;
						cout<<G.vexs[w]<<"  ";
						q.push(w);
					}
			}
		}
}
	
int main()
{
	MGraph G;
	CreateUDN_MG(G);
	cout<<"深度优先遍历图为:";
	DFS_Traverse(G);
	cout<<endl;
	cout<<"广度优先遍历图为:";
	BFS_Traverse(G);
	cout<<endl;
	return 0;
}

测试结果:

输入图的顶点数和边数:8 9
输入各个顶点的民称:v1 v2 v3 v4 v5 v6 v7 v8
输入每条边对应的两个顶点:v1 v2
输入每条边对应的两个顶点:v1 v3
输入每条边对应的两个顶点:v2 v4
输入每条边对应的两个顶点:v2 v5
输入每条边对应的两个顶点:v4 v8
输入每条边对应的两个顶点:v5 v8
输入每条边对应的两个顶点:v3 v6
输入每条边对应的两个顶点:v3 v7
输入每条边对应的两个顶点:v6 v7
图构造完成
深度优先遍历图为:v1  v2  v4  v8  v5  v3  v6  v7
广度优先遍历图为:v1  v2  v3  v4  v5  v6  v7  v8
Press any key to continue

按照上面的输入所生产的图如下所示:


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 深度优先遍历是一种遍历方式,它从一个顶点开始,沿着一条路径走到底,然后回溯到前一个节点,再沿着另一条路径走到底,直到所有的节点都被访问过为止。邻接矩阵是一种存储方式,它用一个二维数组来表示中的节点之间的关系。在邻接矩阵中,每个节点都对应着数组中的一行或一列,如果两个节点之间有边相连,则在对应的行和列上标记为1,否则标记为。深度优先遍历可以通过递归实现,从一个节点开始,先访问它的邻居节点,然后递归访问邻居节点的邻居节点,直到所有的节点都被访问过为止。 ### 回答2: 邻接矩阵存储是一种常见的的表示方法,而深度优先遍历论中一种重要的遍历方法。第一关指的是如何实现邻接矩阵存储的深度优先遍历。 深度优先遍历是一种先沿着一条路径走到底,再回退到前一个结点继续探索的方法。对于邻接矩阵存储,我们可以使用一个布尔数组来记录每个结点是否已经被访问过。然后从起点出发,递归地访问其相邻未访问的结点,直到所有结点都被访问过。 在具体实现时,我们可以通过一个递归函数来实现深度优先遍历,函数的形参包括当前访问的结点、已访问结点的布尔数组和邻接矩阵。首先将当前结点标记为已访问,然后遍历其相邻未访问的结点,递归调用遍历函数。最后回退到前一个结点继续遍历其他相邻结点。 对于无向和有向而言,深度优先遍历本质上是一样的,具体的实现也类似。唯一的区别在于,有向中需要考虑边的方向,只遍历指向未访问的结点的边。 总之,邻接矩阵的深度优先遍历是一种简单而有效的遍历方法。通过标记已访问过的结点,可以遍历到所有的结点。这个实现方法简单高效,非常适合小型的、稠密的,但遍历大型时则不是很适用。 ### 回答3: 邻接矩阵的一种存储方式,它是用一个二维数组来表示顶点之间的关系,其中数组的行和列分别表示中的顶点,而数组中的元素则表示该行和列所对应的顶点是否存在边。邻接矩阵对于求取路径长度、遍历等问题较为方便,其中深度优先遍历是一种重要的遍历方式。 深度优先遍历的思想是从一个起始点开始,一直沿着深度优先的方向遍历到最深的节点。先访问一个未访问过的节点,再递归访问邻接矩阵中该节点的邻居节点。对于邻接矩阵,深度优先遍历可以用递归的方式实现。 具体来说,深度优先遍历过程如下: 1. 选择一个起始顶点作为遍历开始的顶点,将其标记为已访问。 2. 查找当前顶点的第一个邻接点。 3. 如果该邻接点已经被访问过,则返回到第二步,否则将其标记为已访问,并递归访问该邻接点的相邻节点。 4. 不断重复第二步和第三步,直到当前顶点的所有邻接点都被访问过为止。 5. 选择一个未被访问的顶点作为新的起始顶点,重复以上步骤,直到所有顶点都被遍历过为止。 邻接矩阵存储方式的深度优先遍历是一种简单有效的遍历方式,但也存在一些问题。例如,当中的节点数量较大时,邻接矩阵存储空间会很大;而且如果是稀疏的,那么大部分邻接矩阵中的元素都是0,这会导致存储浪费。因此,在实际应用中,需要结合具体问题来选择合适的存储方式遍历方法。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值