邻接矩阵表示 深度遍历 广度遍历

简介: 邻接矩阵表示 深度遍历 广度遍历

邻接矩阵表示法是一种图的表示方法,其中每个顶点都有一个唯一的索引,而每条边则由两个顶点之间的连接确定。深度优先遍历(DFS)和广度优先遍历(BFS)是两种常用的图遍历算法。

1. 深度优先遍历(DFS):

深度优先遍历从根节点开始,沿着一条路径尽可能深入地访问节点,直到到达叶子节点。然后回溯到上一个节点,继续访问其他未访问过的节点。这个过程一直持续到所有节点都被访问过为止。

在邻接矩阵表示法中,可以使用递归或栈来实现深度优先遍历。以下是使用栈实现的示例代码:

#include <iostream>
#include <stack>
using namespace std;
void dfs(int matrix[][4], int start, bool visited[]) {
    stack<int> s;
    s.push(start);
    visited[start] = true;
    while (!s.empty()) {
        int node = s.top();
        s.pop();
        cout << node << " ";
        for (int i = 0; i < 4; i++) {
            if (matrix[node][i] == 1 && !visited[i]) {
                s.push(i);
                visited[i] = true;
            }
        }
    }
}
int main() {
    int matrix[4][4] = {
        {0, 1, 1, 0},
        {1, 0, 0, 1},
        {1, 0, 0, 1},
        {0, 1, 1, 0}
    };
    bool visited[4] = {false};
    dfs(matrix, 0, visited);
    return 0;
}

 

2. 广度优先遍历(BFS):

广度优先遍历从根节点开始,首先访问所有与根节点直接相连的节点,然后再访问这些节点的邻居节点,以此类推。这个过程一直持续到所有节点都被访问过为止。

在邻接矩阵表示法中,可以使用队列来实现广度优先遍历。以下是使用队列实现的示例代码:

#include <iostream>
#include <queue>
using namespace std;
void bfs(int matrix[][4], int start, bool visited[]) {
    queue<int> q;
    q.push(start);
    visited[start] = true;
    while (!q.empty()) {
        int node = q.front();
        q.pop();
        cout << node << " ";
        for (int i = 0; i < 4; i++) {
            if (matrix[node][i] == 1 && !visited[i]) {
                q.push(i);
                visited[i] = true;
            }
        }
    }
}
int main() {
    int matrix[4][4] = {
        {0, 1, 1, 0},
        {1, 0, 0, 1},
        {1, 0, 0, 1},
        {0, 1, 1, 0}
    };
    bool visited[4] = {false};
    bfs(matrix, 0, visited);
    return 0;
}

 

3. 邻接矩阵表示 深度遍历 广度遍历

代码如下:

#include <iostream>
#include <stack>
#include <queue>
using namespace std;
#define MaxInt  32767
#define MVNum 100
typedef char VerTexType;
typedef int ArcType;
//邻接矩阵
typedef  struct {
    VerTexType  vexs[MVNum];  /*存储顶点元素*/
    ArcType arcs[MVNum][MVNum];
    /*各顶点之间的关系或权值*/
    int  vexnum, arcnum; /*顶点数,边(或弧)的个数*/
}MGraph;
int visited[MVNum];
int visitedBFS[MVNum];
stack<VerTexType> mystack;
queue<VerTexType> myqueue;
//函数声明
void PrintVisited();
int LocateVex(MGraph& G, VerTexType v); //函数定义
void CreateMGraph(MGraph& G);
void DFS(MGraph& G, VerTexType v);
void BFS(MGraph& G, VerTexType v);
void TestDemoGraph();
//函数定义
void  CreateMGraph(MGraph& G) {
    int i = 0, j = 0, k = 0;
    cout << "输入顶点个数:";
    cin >> G.vexnum;
    cout << "输入边的个数:";
    cin >> G.arcnum;
    for (i = 0; i < G.vexnum; i++) {
        cout << "输入第" << i + 1 << "个顶点的名称:";
        cin >> G.vexs[i];
    }
    for (i = 0; i < G.vexnum; ++i)         //初始化邻接矩阵,
        for (j = 0; j < G.vexnum; ++j)
            G.arcs[i][j] = 0;
    cout << "输入边依附的顶点 ,如 a b " << endl;
    VerTexType v1, v2;
    for (k = 0; k < G.arcnum; ++k) {              //构造邻接矩阵
        cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
        cin >> v1 >> v2;                //输入一条边依附的顶点及权值
        i = LocateVex(G, v1);   //函数调用
        j = LocateVex(G, v2);   //确定v1和v2在G中的位置,即顶点数组的下标
        if (i == -1 || j == -1) {
            cout << "顶点名称错误" << endl;
            k--;
            continue;
        }
        G.arcs[i][j] = 1;               //边<v1, v2>的值为1
        G.arcs[j][i] = G.arcs[i][j];            //置<v1, v2>的对称边<v2, v1>的权值为w
    }//for
}
int LocateVex(MGraph& G, VerTexType v) { //函数定义
    //确定点v在G中的位置
    for (int i = 0; i < G.vexnum; ++i)
        if (G.vexs[i] == v)
            return i;
    return -1;
}//LocateVex
void PrintVexArc(MGraph& G) {
    int i = 0, j = 0;
    cout << "顶点列表:" << endl;
    for (i = 0; i < G.vexnum; i++) {
        cout << "\t" << G.vexs[i];
    }
    cout << endl << "邻接矩阵:" << endl;
    for (i = 0; i < G.vexnum; i++) {
        for (j = 0; j < G.vexnum; j++) {
            cout << "\t" << G.arcs[i][j];
        }
        cout << endl;
    }
}
void PrintVisited() {
    for (int i = 0; i < 6; i++) cout << visited[i] << "\t"; cout << endl;
}
void PrintVisitedBFS() {
    for (int i = 0; i < 6; i++) cout << visitedBFS[i] << "\t"; cout << endl;
}
void DFS(MGraph& G, VerTexType v) {  //从v点开始深度遍历
    int index = LocateVex(G, v);
    if (index == -1) {
        cout << "没有这个结点" << v << endl;
        return;
    }
    if (visited[index] == 1) {  //已经访问过了,就返回。
        return;
    }
    //没有访问过,直接标记访问,操作,没有访问过的邻接点入栈
    visited[index] = 1; //标记当前结点已经访问过了
    cout << v << "\t"; //访问当前结点V,对该结点进行操作,直接输出。
    PrintVisited();
    int j = 0;
    for (j = G.vexnum; j >= 0; j--) {
        if (G.arcs[index][j] == 1 && visited[j] == 0) {
            mystack.push(G.vexs[j]);
        }
    }
    while (!mystack.empty()) {
        VerTexType vex = mystack.top();
        mystack.pop();
        DFS(G, vex);
    }
}
void BFS(MGraph& G, VerTexType v) {   //从v点开始广度遍历
    int index = LocateVex(G, v);
    if (index == -1) {
        cout << "没有这个结点" << v << endl;
        return;
    }
    if (visitedBFS[index] == 1) {
        return;
    }
    //没有被访问过,
    visitedBFS[index] = 1;
    cout << v << "\t";
    PrintVisitedBFS();
    for (int i = 0; i < G.vexnum; i++) {
        if (G.arcs[index][i] == 1 && visitedBFS[i] == 0) {
            //  cout<<"["<<index<<"]["<<i<<"]="<<G.vexs[i]<<endl;
            myqueue.push(G.vexs[i]);
        }
    }
    while (!myqueue.empty()) {
        VerTexType vex = myqueue.front();
        myqueue.pop();
        //cout<<"pop-->"<<vex<<endl;
        BFS(G, vex);
    }
}
void TestDemoGraph() {
    MGraph G;
    CreateMGraph(G);
    PrintVexArc(G);
    cout << "DFS--->" << endl;
    DFS(G, 'b');
    cout << "BFS--->" << endl;
    BFS(G, 'b');
}
int main()
{
    TestDemoGraph();
    return 0;
}
/*
6
8
a
b
c
d
e
f
ab
af
ae
bc
bd
fd
ed
cd
*/

 

运行结果:

加油各位!!

目录
相关文章
|
异构计算
Magisk模块:停用HW叠加层
Magisk模块:停用HW叠加层
6781 0
Magisk模块:停用HW叠加层
|
9月前
|
云安全 人工智能 安全
Ollama漏洞引发的“血案”—自建LLM的安全思考
「云安全技术观察」聚焦云计算时代安全技术前沿与实践,涵盖AI大模型风险、云原生安全体系建设及攻防对抗等内容,提供落地技术参考与前瞻性洞察。
1074 0
|
存储 Java Nacos
Seata常见问题之springboot 2.3.7 和高版本 seata 2.0.0,1.6.1不兼容如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
1819 0
|
10月前
|
运维 Prometheus 监控
别再盲选了!开源运维工具选型这事儿,咱得说人话
别再盲选了!开源运维工具选型这事儿,咱得说人话
586 7
|
8月前
鸿蒙 HarmonyOS NEXT星河版APP应用开发-阶段二
本文介绍鸿蒙应用界面开发中的弹性布局(Flex)、绝对定位、层叠布局及ArkTS语法进阶,涵盖字符串拼接、类型转换、数组操作、条件与循环语句,并结合B站视频卡、支付宝首页等案例,深入讲解点击事件、状态管理与界面交互功能。
460 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-阶段二
|
测试技术 API 持续交付
如何免费解决 Postman 集合限制
这里有几种方法可以解决 Postman 集合运行器 (Postman Collection Runner) 的限制。然而,使用 Apifox 创建你的集合没有任何限制,而且是免费的。
如何免费解决 Postman 集合限制
|
10月前
|
XML 人工智能 Java
java通过自定义TraceId实现简单的链路追踪
本文介绍了如何在Spring Boot项目中通过SLF4J的MDC实现日志上下文traceId追踪。内容涵盖依赖配置、拦截器实现、网关与服务间调用的traceId传递、多线程环境下的上下文同步,以及logback日志格式配置。适用于小型微服务架构的链路追踪,便于排查复杂调用场景中的问题。
514 0
|
JavaScript
vite的快的原因居然如此简单!探秘其依赖预加载机制
【8月更文挑战第1天】探秘vite预加载机制
382 4
vite的快的原因居然如此简单!探秘其依赖预加载机制
|
机器学习/深度学习 搜索推荐 人机交互
智能语音交互技术的突破与未来展望###
【10月更文挑战第27天】 本文聚焦于智能语音交互技术的最新进展,探讨了其从早期简单命令识别到如今复杂语境理解与多轮对话能力的跨越式发展。通过深入分析当前技术瓶颈、创新解决方案及未来趋势,本文旨在为读者描绘一幅智能语音技术引领人机交互新纪元的蓝图。 ###
877 0
|
XML 安全 Java
走进Java接口测试之测试框架TestNG
TestNG 是一个受 JUnit 和 NUnit 启发的测试框架,旨在简化广泛的测试需求,从单元测试到接口测试。但引入了一些新功能,使其更强大,更易于使用。
2583 1
走进Java接口测试之测试框架TestNG

热门文章

最新文章