C/C++ 图---邻接矩阵存储,深度/广度优先遍历

  邻接矩阵--------是用一维数组存放顶点的信息,用二维数组存储边的信息.

1.先定义图的变量信息。

#include<iostream>
using namespace std;
#include<queue>
#define MaxSize 100

typedef struct{
	int vertex[MaxSize];            //数组中存储节点的信息 
	int arc[MaxSize][MaxSize];      //这个二维数组保存邻接矩阵
	int vertexnum;                  //记录图中节点个数 
	int arcnum; 	                // 记录图中边的个数 
}Graph;

int visited[MaxSize];   //全局遍历,用于记录节点是否被访问过 
//当进行一次遍历后,visited[]数组的值就需要重新赋值, 否则再次遍历的时候visited[]数组就是之前的值,

2.图的创建

1)首先确定图的定点数n 和边数e;

2)图有4个信息分别是vertex[], arc[][], vertexnum, arcnum, 和一个全局变量visited[]数组。

对这几个信息分别初始化。

首先是vertex[]数组,这里面保存的是顶点信息,所以用arr[]数组赋值即可

arc[][]数组保存的是顶点间是否有边, 如arc[1][2]=1表示顶点1到顶点2两个顶点间有边。

vertexnum表示节点个数,用n赋值即可

arcnum表示边的个数,用e赋值即可。

注意,无向图,a->b有边,则b->a也有边,矩阵是对称的。

 

void Creat_Graph(Graph &G, int n, int e, int arr[])   //要传入图G的引用。否则创建图不成功 
{
	G.vertexnum=n;
	G.arcnum=e;
	
	for(int i=0; i<G.vertexnum; i++)  //把数组中的每个节点值保存在图中 
	{
		G.vertex[i]=arr[i];
	}

	//让visited[i]数组值为0, 表示顶点i没有被访问。 
	for(int i=0; i<G.vertexnum; i++)
	{
		visited[i]=0;
	}
	
    //初始化为0, 表示各个顶点之间,一开始都不存在边
	for(int i=0; i<G.vertexnum; i++) 
	{
		for(int j=0; j<G.vertexnum; j++)
		{
			G.arc[i][j]=0;
		}
	}
	
	//开始生成图  无向图中,如果1->2有条边,则2->1也有条边, 
	for(int i=0; i<G.arcnum; i++)
	{
		int a,b;
		cin>>a>>b;
		
		G.arc[a][b]=1;
		G.arc[b][a]=1;	
	 } 
}

深度优先遍历伪代码:

        1.访问顶点V, 设置visited[v]=1, 表示V顶点已经被访问过了

        2.w=顶点v的第一个邻接点,

        3. while(w存在 并且 未被访问时)

                3.1 以w为根节点, 递归访问w节点,直到没有邻接点后返回

void DFSTraverse(Graph G, int v)   
{
	cout<<G.vertex[v];
	visited[v]=1;
	
    //每个顶点都可能与其余的n-1个顶点相连,所以每次以顶点v开始,都要遍历所有顶点
	for(int i=0; i<G.vertexnum; i++)
	{

        //G.arc[v][i]==1  表示顶点V到顶点i有一条边,
        //visited[i]==0   表示顶点i未被访问/
		if(G.arc[v][i]==1 && visited[i]==0)  
		{
			DFSTraverse(G,i);
		}
	}
}

广度优先伪代码:

        1.初始化队列Q

        2. 访问顶点V,设置visited[v]=1,并且将顶点V入队

        3.while(队列不为空)

                3.1  w=顶点v的第一个邻接点,

                while(w存在)

                        访问顶点w的邻接点 visited[w]=1

                        w的邻接点入队

                w=顶点v的下一个邻接点    

                直到顶点v的邻接点都访问完毕,退出内循环。

void BFSTraverse(Graph G, int v, queue<int> Q)
{
	cout<<G.vertex[v];
	visited[v]=1;
	
	Q.push(G.vertex[v]);
	
	while(!Q.empty())
	{
		int val = Q.front();   //队列是队头出队,队尾进队  这是访问头节点 
		Q.pop();                //删除 头节点元素
		
        //弹出一个val节点后,要遍历所有节点,查看val和哪些节点有边且没被访问过。
		for(int i=0; i<G.vertexnum; i++)
		{
			if(G.arc[val][i]==1 && visited[i]==0)
			{
				cout<<G.vertex[i];
				visited[i]=1;
				Q.push(G.vertex[i]);
			}
		}
	 } 
	
 } 

完整代码:

//无向图创建与遍历 

#include<iostream>
using namespace std;
#include<queue>
#define MaxSize 100

typedef struct{
	int data;
	int vertex[MaxSize];    //数组中存储保存的节点值 
	int arc[MaxSize][MaxSize];   //这个二维数组保存邻接矩阵
	int vertexnum;   //记录图中节点个数 
	int arcnum; 	// 记录图中边的个数 
}Graph;



int visited[MaxSize];   //全局遍历,用于记录节点是否被访问过 

void DFSTraverse(Graph G, int v)   
{
	cout<<G.vertex[v];
	visited[v]=1;
	
	for(int i=0; i<G.vertexnum; i++)
	{
		if(G.arc[v][i]==1 && visited[i]==0)  //arc[v][i]=1表示: 顶点v到邻接点i有边,且这个邻接点没有被访问过。 则深度优先递归访问这个邻接点。 
		{
			DFSTraverse(G,i);
		}
	}
}



void BFSTraverse(Graph G, int v, queue<int> Q)
{
	cout<<G.vertex[v];
	visited[v]=1;
	
	Q.push(G.vertex[v]);
	
	while(!Q.empty())
	{
		int val = Q.front();   //队列是队头出队,队尾进队 
		Q.pop();
		
		for(int i=0; i<G.vertexnum; i++)
		{
			if(G.arc[val][i]==1 && visited[i]==0)
			{
				cout<<G.vertex[i];
				visited[i]=1;
				Q.push(G.vertex[i]);
			}
		}
	 } 
	
 } 

void Creat_Graph(Graph &G, int n, int e, int arr[])   //如果不是在类里面,要传入图G的引用。否则创建图不成功 
{
	G.vertexnum=n;
	G.arcnum=e;
	
	for(int i=0; i<G.vertexnum; i++)  //把数组中的每个节点值保存在图中 
	{
		G.vertex[i]=arr[i];
	}
	//让visited[]数组值为0, 表示没有被访问过。 **调用过一次深度遍历或广度遍历,都需要重新给visited赋值, 
//	for(int i=0; i<G.vertexnum; i++)
//	{
//		visited[i]=0;
//	}
	
	for(int i=0; i<G.vertexnum; i++)    //当有n的节点的时候, n*n的矩阵,初始值都为0,表示任何两个顶点之间都没边 
	{
		for(int j=0; j<G.vertexnum; j++)
		{
			G.arc[i][j]=0;
		}
	}
	
	//开始生成边  无向图中,如果1->2有条边,则2->1也有条边, 
	for(int i=0; i<G.arcnum; i++)
	{
		int a,b;
		cin>>a>>b;
		
		G.arc[a][b]=1;
		G.arc[b][a]=1;	
	 } 
}


void set_visited(Graph G)
{
	for(int i=0; i<G.vertexnum; i++)
	{
		visited[i]=0;
	}
 } 

int main()
{
	queue<int> Q;
	int n,e;   //n是节点数,e是边数 
	Graph G;
	cin>>n>>e;
	
	int arr[n];
	for(int i=0; i<n; i++)
	{
		cin>>arr[i];
	}
	
	Creat_Graph(G,n,e,arr);
	set_visited(G);
	cout<<" DFSTraverse: ";
	DFSTraverse(G,0);
	set_visited(G);
	cout<<endl<<" BFSTraverse: ";
	BFSTraverse(G, 0, Q);
	return 0; 
}


练习:

输入:

5 7

0 1 2 3 4

0 1

0 3

0 4

1 2

1 4

2 3

3 4

输出:

 

  • 10
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++实现邻接矩阵存储深度优先遍历以及广度优先遍历的代码示例: 1. 邻接矩阵存储 ```c++ #define MAXVEX 100 // 最大顶点数 #define INFINITY 65535 // 用65535来代表无穷大 typedef struct { int vexs[MAXVEX]; // 存储顶点的数组 int arc[MAXVEX][MAXVEX]; // 存储边的二维数组 int numVertexes, numEdges; // 中当前的顶点数和边数 } MGraph; // 创建邻接矩阵 void CreateMGraph(MGraph *G) { int i, j, k, w; printf("请输入顶点数和边数:\n"); scanf("%d,%d", &G->numVertexes, &G->numEdges); for (i = 0; i < G->numVertexes; i++) { printf("请输入第%d个顶点:", i + 1); scanf("%d", &G->vexs[i]); } for (i = 0; i < G->numVertexes; i++) { for (j = 0; j < G->numVertexes; j++) { G->arc[i][j] = INFINITY; // 初始化邻接矩阵 } } for (k = 0; k < G->numEdges; k++) { printf("请输入边(vi,vj)的下标i,下标j和权值w:\n"); scanf("%d,%d,%d", &i, &j, &w); G->arc[i][j] = w; G->arc[j][i] = G->arc[i][j]; // 无向对称 } } ``` 2. 深度优先遍历 ```c++ bool visited[MAXVEX]; // 记录顶点是否被访问过 // 邻接矩阵深度优先递归算法 void DFS(MGraph G, int i) { int j; visited[i] = true; printf("%d ", G.vexs[i]); for (j = 0; j < G.numVertexes; j++) { if (G.arc[i][j] != INFINITY && !visited[j]) { DFS(G, j); } } } // 邻接矩阵深度遍历操作 void DFSTraverse(MGraph G) { int i; for (i = 0; i < G.numVertexes; i++) { visited[i] = false; } for (i = 0; i < G.numVertexes; i++) { if (!visited[i]) { DFS(G, i); } } } ``` 3. 广度优先遍历 ```c++ // 邻接矩阵的广度遍历算法 void BFSTraverse(MGraph G) { int i, j; queue<int> Q; for (i = 0; i < G.numVertexes; i++) { visited[i] = false; } for (i = 0; i < G.numVertexes; i++) { if (!visited[i]) { visited[i] = true; printf("%d ", G.vexs[i]); Q.push(i); while (!Q.empty()) { int k = Q.front(); Q.pop(); for (j = 0; j < G.numVertexes; j++) { if (G.arc[k][j] != INFINITY && !visited[j]) { visited[j] = true; printf("%d ", G.vexs[j]); Q.push(j); } } } } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值