图的遍历算法是求解图的连通性问题、拓扑排序和、求关键路径等算法的基础。
图的遍历方法:(适用于无向图和有向图)
- 深度优先搜索遍历
- 广度优先搜索遍历
深度优先搜索遍历(DFS)
类似于树的先根遍历,是树的先根遍历的推广。
设图中的所有顶点都未被访问,则深度优先遍历搜索可从图中的某个顶点P出发,访问该顶点,然后依次从v的未访问的邻接点出发深度优先遍历图,直到所有和P有路径相通的节点都被访问。
邻接矩阵的深度优先搜索:
代码实现为:
bool visited[Max_Num];//全局变量
void Adj_matrix::DFS(int x)//深度优先遍历递归
{
cout << vexs[x] << endl; visited[x] = true;
for (int i = 0; i < vexnum; i++)//遍历邻接矩阵中X的行
{
if (arcs[x][i] == 1 && !visited[x])//邻接矩阵中的值为1,且节点未被访问
{
DFS(i);//递归
}
}
}
void Adj_matrix::DFSTraverse()//深度优先遍历
{
for (int i = 0; i < vexnum; i++) visited[i] = false;//把数组初始化
int s;
cin >> s;//输入起始点
DFS(s);//执行递归算法
}
邻接表的深度优先搜索遍历:
bool visited[Max_Num];//全局变量
void ADList::DFS(int x)//深度优先遍历的递归调用
{
cout << adlist[x].data;//输出节点信息
visited[x] = true;//把节点设置为已访问
table_node* p = adlist[x].firstarc;//用一个指针指向该顶点的弧链表
while (p != NULL)//如果该节点的弧链表不为空
{
if (!visited[p->adjvex])//该弧顶点如果未访问的话
DFS(p->adjvex);//遍历该顶点
p = p->nextarc;//指向下一个链表节点
}
}
void ADList::DFSTraverse()//深度优先遍历
{
for (int i = 0; i < vexnum; i++) visited[i] = false;
int s;
cin >> s;//输入起始点
DFS(s);//执行递归算法
}
邻接矩阵的深度优先遍历的时间复杂度:O(n^2)
邻接表的深度优先遍历的时间复杂度:O(n+e)
广度优先遍历(BFS)
类似于树的层次遍历。
先访问头结点,在依次访问全部邻接点,然后再按照这些顶点被访问的先后次序依次访问 与它们邻接且未被访问的顶点。
邻接矩阵的广度优先遍历:
bool visited[Max_Num];
void Adj_matrix::BFS(int w)
{
for (int i = 0; i < vexnum; i++)visited[i] = false;//初始化数组
cout << vexs[w] << endl;//输出顶点内容
visited[w] = true;//把节点设置为已访问
queue<int> p;//创建一个队列,存放顶点
p.push(w);//把顶点压入队列
while (!p.empty())//队列不为空
{
int Node = p.front();//获取队头元素
p.pop();//移除队头顶点
for (int i = 0; i < vexnum; i++)
{
if (arcs[Node][i] == 1 && !visited[i])//如果矩阵数值为1,且节点未被访问
{
cout << vexs[i];//输出该顶点
visited[i] = true;//把节点设置为已访问
p.push(w);//把顶点压入队列
}
}
}
}
邻接表的广度优先遍历:
bool visited[Max_Num];//全局变量
void ADList::BFS(int x)
{
for (int i = 0; i < vexnum; i++)visited[i] = false;//初始化数组
cout << adlist[x].data << endl;//输出顶点内容
visited[x] = true;//把节点设置为已访问
queue<int> p;//创建一个队列,存放顶点
p.push(x);//把顶点压入队列
while (!p.empty())//队列不为空
{
int Node = p.front();//获取队头元素
p.pop();//移除队头顶点
table_node* H = adlist[Node].firstarc;//用一个指针指向该顶点的首弧位置
while (H != nullptr)//指针不为空的话
{
if (!visited[H->adjvex])//顶点未被访问的话
{
cout<<adlist[H->adjvex].data;//输出数据
visited[H->adjvex]=true;//把顶点设为已访问
p.push(H->adjvex);//把顶点的位置压入栈中
}
H = H->nextarc;
}
}
}