邻接矩阵--------是用一维数组存放顶点的信息,用二维数组存储边的信息.
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
输出: