图的初识·遍历

news2024/11/15 17:19:32

文章目录

  • 深度优先搜索[DFS]
    • 实现代码
  • 广度优先搜索【BFS】
    • 思路图解
    • 代码实现·广度优先遍历【BFS】
      • 图的结构

深度优先搜索[DFS]

  • 并不唯一,只是一种情况 A − > I A->I A>I
    在这里插入图片描述

实现代码

在这里插入图片描述

  • 使用邻接表表示图。遍历的时间复杂度 O ( V + E ) O(V+E) O(V+E);邻接矩阵的时间复杂度为 O ( V 2 ) O(V^2) O(V2)
#include <stdio.h>
#include <stdlib.h>
#define MaxVertex 5
typedef char E;
//结点和头节点分开定义,普通结点记录邻接顶点信息
typedef struct node {
    int nextVertex;
    struct node *next;
} *Node;
//头节点记录元素
struct HeadNode {
    E element;
    struct node * next;
};

typedef struct AdjacencyGraph {
    int vertexCount;//顶点数
    int edgeCount;//边数
    struct HeadNode vertex[MaxVertex];
}* Graph;
//初始化
Graph create();
//添加顶点
void addVertex(Graph graph,E element);
//添加边的关系
void addEdge(Graph graph,int a,int b);
//打印邻接表
void printGraph(Graph graph);
//深度优先搜索算法
int dfs(Graph graph,int startVertex,int targetVertex,int* visited);
#include "Map2.h"
//创建
Graph create() {
    Graph graph=(Graph) malloc(sizeof(struct AdjacencyGraph));
    graph->vertexCount=graph->edgeCount=0;
    return graph;
};
//添加顶点
void addVertex(Graph graph,E element) {
    if(graph->vertexCount>=MaxVertex) return;
    //添加新节点
    graph->vertex[graph->vertexCount].element=element;
    graph->vertex[graph->vertexCount].next=NULL;
    graph->vertexCount++;//顶点数更新
}
void addEdge(Graph graph,int a,int b) {
    //定义一个指向链表的头结点的下一结点指向
    Node node=graph->vertex[a].next;
    //开辟顶点空间
    Node newNode=(Node) malloc(sizeof(struct node));
    newNode->next=NULL;
    newNode->nextVertex=b;
    //如果头结点下面没有东西,就直接连接;否则,就遍历到最后一个结点后,添加新节点
    if(!node) {
        graph->vertex[a].next=newNode;//注意这里不能使用node,因为我们要真实地改变头节点的next指向
    }else {
        do{
            //如果已经连接到对应的结点,直接返回
            if(node->nextVertex==b) {
                free(newNode);
                newNode=NULL;
                return ;
            }
            //否则一直遍历到最后一个结点
            if(node->next) node=node->next;
            else break;//如果遭到了最后一个结点,直接结束
        }while(true);
        node->next=newNode;
    }
    graph->edgeCount++;//边数计数+1
}
//打印
void printGraph(Graph graph) {
    for(int i=0;i<graph->vertexCount;i++) {
        printf("%d | %c",i,graph->vertex[i].element);
        Node node=graph->vertex[i].next;
        while(node) {
            printf("-> %d",node->nextVertex);
            node=node->next;
        }
        printf("\n");
    }
}
/**
 * 深度优先搜索算法
 * @param graph 图
 * @param startVertex 起点顶点下标
 * @param targetVertex 目标顶点下标
 * @param visited 已到达过的顶点数组
 */
int dfs(Graph graph,int startVertex,int targetVertex,int* visited) {
    visited[startVertex]=1;//标记访问过的结点
    //大一当前结点
    printf("%c->",graph->vertex[startVertex].element);
    //如果当前顶点就是要找的顶点,就直接返回
    if(startVertex==targetVertex) return 1;
    //遍历当前顶点所有的分支
    Node node=graph->vertex[startVertex].next;
    while(node) {
        //如果已经到过[做的其他分支、回头路],就停止
        if(!visited[node->nextVertex]) {
            //没到过就继续往下走
            //如果查找成功就返回一,不用再看其他分支。
            if(dfs(graph,node->nextVertex,targetVertex,visited)) {
                return 1;
            }
        }
        node=node->next;
    }
    return 0;//当下的遍历都结束后,还是没有找到就返回零
}
#include "Map2.h"

int main() {
    Graph graph1 = create();
    for (int c = 'A'; c <= 'F'; c++) {
        addVertex(graph1, (char) c);
    }
    addEdge(graph1, 0, 1);//A->B
    addEdge(graph1, 1, 2);//B->C
    addEdge(graph1, 1, 3);//B->D
    addEdge(graph1, 1, 4);//D->E
    //addEdge(graph1, 4, 5);//E->F
    printGraph(graph1);
    int arr[graph1->vertexCount];
    for(int i=0;i<graph1->vertexCount;i++) {
        arr[i]=0;
    }
    printf("\n%d",dfs(graph1,0,5,arr));

    return 0;
}

在这里插入图片描述

广度优先搜索【BFS】

  • 先探索顶点的所有分支,然后再去看这些分支的所有分支。
  • 实质上是更尽可能地探索更广的范围。

思路图解

从 A 结 点 开 始 探 索 , A 入 队 列 。 队 列 状 态 : A 然 后 , 再 将 其 下 一 个 结 点 B 入 队 , A 出 队 。 队 列 状 态 : B 从A结点开始探索,A入队列。\\ 队列状态:A\\ 然后,再将其下一个结点B入队,A出队。\\ 队列状态:B\\ AAABAB
在这里插入图片描述
将 B 的 下 一 级 结 点 入 队 队 列 状 态 : B − > H − > G − > K 将 B 出 队 队 列 状 态 : H − > G − > K 将B的下一级结点入队\\ 队列状态:B->H->G->K\\ 将B出队\\ 队列状态:H->G->K BB>H>G>KBH>G>K
在这里插入图片描述
依 次 按 照 队 头 到 队 尾 的 顺 序 , 将 其 子 节 点 入 队 , 本 结 点 出 队 。 C 入 队 队 列 状 态 : H − > G − > K − > C H 出 队 对 列 状 态 : G − > K − > C 依次按照队头到队尾的顺序,将其子节点入队,本结点出队。\\ C入队\\ 队列状态:H->G->K->C\\ H出队\\ 对列状态:G->K->C CH>G>K>CHG>K>C
在这里插入图片描述
D 、 F 入 队 ; C 已 入 队 , 所 以 无 需 再 次 入 队 。 队 列 状 态 : G − > K − > C − > D − > F G 出 队 对 列 状 态 : K − > C − > D − > F D、F入队;C已入队,所以无需再次入队。\\ 队列状态:G->K->C->D->F\\ G出队\\ 对列状态:K->C->D->F\\ DF;CG>K>C>D>FGK>C>D>F
在这里插入图片描述
K 没 有 下 一 个 结 点 , 所 以 直 接 将 K 出 队 。 队 列 状 态 : C − > D − > F K没有下一个结点,所以直接将K出队。\\ 队列状态:C->D->F KKC>D>F
在这里插入图片描述
再 依 次 遍 历 队 头 的 下 一 个 结 点 E 入 队 队 列 状 态 : C − > D − > F − > E C 出 队 队 列 状 态 : D − > F − > E 再依次遍历队头的下一个结点\\ E入队\\ 队列状态:C->D->F->E C出队\\ 队列状态:D->F->E EC>D>F>ECD>F>E
在这里插入图片描述
因 为 D 、 F 没 有 下 一 级 邻 接 点 , 所 以 将 D 、 F 出 队 即 可 队 列 状 态 : E 因为D、F没有下一级邻接点,所以将D、F出队即可\\ 队列状态:E DFDFE

在这里插入图片描述
I 、 J 入 队 队 列 状 态 : E − > I − > J E 出 队 队 列 状 态 : I − > J I、J入队\\ 队列状态:E->I->J E出队\\ 队列状态:I->J IJE>I>JEI>J
在这里插入图片描述
最 后 再 将 队 列 的 内 容 全 部 出 队 队 列 状 态 : 空 结 束 搜 索 最后再将队列的内容全部出队\\ 队列状态:空\\ 结束搜索

代码实现·广度优先遍历【BFS】

  • 存储结构:邻接表

图的结构

在这里插入图片描述

typedef int T;
struct QueueNode{
    T element;
    struct QueueNode * next;
};
typedef struct QueueNode* QNode;
struct Queue{
    QNode front,rear;
};
typedef struct Queue* LinkedQueue;
int initQueue(LinkedQueue queue) {
    QNode node=(QNode) malloc(sizeof(struct QueueNode));
    if(node==NULL) return 0;
    queue->front=queue->rear=node;
    return 1;
}

int offerQueue(LinkedQueue queue,T element) {
    QNode node=(QNode) malloc(sizeof(struct QueueNode));
    if(node== NULL) return 0;
    node->element=element;
    queue->rear->next=node;
    queue->rear=node;
    return 1;
}
int isEmpty(LinkedQueue queue){
    return queue->front==queue->rear;
};
T pollQueue(LinkedQueue queue) {
    T e=queue->front->next->element;
    QNode node=queue->front->next;
    queue->front->next=queue->front->next->next;
    if(queue->rear==node) queue->rear=queue->front;
    free(node);
    return e;
}
  • BFS
/**
 *
 * @param graph 图
 * @param startVertex 起点顶点下标
 * @param targetVertex 目标顶点下标
 * @param visited 已到达过的顶点数组
 * @param queue 辅助作用的队列
 * @return
 */
int bfs(Graph graph,int startVertex,int targetVertex,int* visited,LinkedQueue queue) {
    offerQueue(queue,startVertex);//头节点入队
    visited[startVertex]=1;//立马已标记
    //当队列不为空时,进行操作
    while(!isEmpty(queue)) {
        int next= pollQueue(queue);//从队列中取出一个顶点打印
        printf("%c->",graph->vertex[next].element);
        Node node=graph->vertex[next].next;//下一个结点
        //当当前结点的下一个结点存在时,进行入队操作
        while(node) {
            //如果找到目标结点,返回true
            if(node->nextVertex==targetVertex) return true;
            if(!visited[node->nextVertex]) {//!0==1未访问
                offerQueue(queue,node->nextVertex);//入队列
                visited[node->nextVertex]=1;//访问标记
            }
            node=node->next;//进行下一个结点
        }
    }
    return false;
}
  • Main.cpp
Graph graph1 = create();
for (int c = 'A'; c <= 'F'; c++) {
    addVertex(graph1, (char) c);
}
addEdge(graph1, 0, 1);//A->B
addEdge(graph1, 1, 2);//B->C
addEdge(graph1, 1, 3);//B->D
addEdge(graph1, 1, 4);//D->E
addEdge(graph1, 4, 5);//E->F
printGraph(graph1);
int arr1[graph1->vertexCount];
for(int i=0;i<graph1->vertexCount;i++) {
    arr1[i]=0;
}
struct Queue queue;
initQueue(&queue);
bfs(graph1,0,5,arr1,&queue);

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/56757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 Python 和 OpenCV 制作反应游戏

在本文中&#xff0c;将向你展示如何使用 OpenCV 在 Python 中制作一个反应游戏&#xff0c;你可以动手来玩。你可能已经熟悉 OpenCV&#xff0c;OpenCV 基本上允许进行各种图像处理。你可以在下面的视频中看到最终结果&#xff0c;并且可以在此处获取文件&#xff1a;https://…

jsp4S店管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 4S店管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开 发&#xff0c;数据库为Mysql&#xff0c;使用ja…

海带软件分享——日常办公学习软件下载安装(百度网盘 | 收藏)

>>>深度学习Tricks&#xff0c;第一时间送达<<< &#x1f680; 写在前面 &#x1f431;‍&#x1f3cd; 本期开始&#xff0c;小海带会定期推荐一些日常办公学习软件及趣味网址&#xff08;内含安装教程&#xff09;&#xff0c;供大家学习交流参考 ~ 小伙…

三层交换技术

数据来源 一、三层交换技术出现背景&#xff1a; 解决之前给网段划分VLAN控制端口&#xff0c;然后使用路由器设置单臂路由的让不同VLAN可以通信的缺点&#xff0c; 单臂路由缺点&#xff1a; 1&#xff09;容易出现网络瓶颈 2&#xff09;容易发生单点物理故障 3&a…

[附源码]Python计算机毕业设计Django海南与东北的美食文化差异及做法的研究展示平台

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

设计一个互联网交换设备的SNMP MIB库“X-MIB”

设计一个互联网交换设备的SNMP MIB库“X-MIB”&#xff1a; 问题描述 设备型号&#xff1a;字符串类型 设备生产厂商&#xff1a;字符串类型 设备名称&#xff1a;字符串类型 设备位置&#xff1a;字符串类型 设备运行时间&#xff1a;Timeticks 类型 设备队列数&#xff…

Find My资讯|苹果Find My帮助美警察逮捕连环盗车嫌犯

报道称&#xff0c;美国Shelby County Sheriff警方于11月13日搜查了Shady Ridge的5300街区的一处住宅&#xff0c;成功逮捕了现年20岁的嫌疑人Michael Walker。根据警方通告&#xff0c;该地区近期发生了多起盗车案件。而案件的突破口是发生在Pleasantwood 6800街区的一件盗车事…

【JUC】循环屏障 CyclicBarrier 详解

前言 jdk 中提供了许多的并发工具类&#xff0c;大家可能比较熟悉的有CountDownLatch&#xff0c;主要用来阻塞一个线程运行&#xff0c;直到其他线程运行完毕。而 jdk 还有一个功能类似并发工具类CyclicBarrier&#xff0c;你知道它的作用吗&#xff1f;和CountDownLatch有什…

MySQL学习记录(6)索引02

2.6、索引的使用 2.6.1、最左前缀法则 如果索引了多列&#xff08;联合索引&#xff09;&#xff0c;要遵循最左前缀法则。最左前缀法则指的是查询从索引的最左列开始&#xff0c;并且不跳过索引的列&#xff0c;如果跳跃某一列&#xff0c;索引将会部分失效&#xff08;后面…

大二Web课程设计:HTML+CSS学校静态网页设计——南京师范大学泰州学院(11页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

[附源码]Python计算机毕业设计SSM开心鲜花系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Java外卖小程序管理系统源码带小程序前端+后端搭建教程

这套系统已经完成了线下配送的大部分功能 技术架构 技术框架&#xff1a;springboot ssm mysql redis 运行环境&#xff1a;IntelliJ IDEA 2022 jdk1.8 Mysql5.7.4 maven nginx 宝塔面板 后端搭建教程 1.下载源码后打开小皮面板&#xff0c;安装mysql5.7数据库&#x…

LIO-SAM源码解析(二):代码结构

1. 代码整体框架 首先看看工程目录结构&#xff0c;主要有五个文件&#xff0c;分别是utility.h&#xff0c;featureExtraction.cpp&#xff0c; imageProjection.cpp&#xff0c;imuPreintegration.cpp&#xff0c;mapOptmization.cpp LIO-SAM/config/params.yaml …

如何借助低代码开发平台 YonBuilder 填补应用开发 “产能缺口”?

低代码平台本身是各类模型、引擎的重新组合&#xff0c;目的是为了填补应用开发需求远超开发者产能这一缺口&#xff0c;那如何理解填补应用开发需求和开发者产能的缺口&#xff1f; 完成一个企业级的应用复杂度随着技术的进步、需求的细化、业务要求的变化并不是逐渐降低而是…

原创|对接三方服务商回调鉴权的程序代码设计

文章目录一、背景二、详细设计1、UML设计2、程序设计2.1、AuthenticateActionEnum2.2、AuthenticateDispatcher2.3、BaseAuthenticateContext<Request>2.3.1、ActivityStatusChangeAuthenticateContext2.3.2、VodEventNotifyAuthenticateContext2.4、AbstractAuthenticat…

【Python+Appium】自动化测试(十一)location与size获取元素坐标

目录 前言 一&#xff0c;获取元素坐标的方法 1&#xff0c;size获取元素的宽、高 2&#xff0c;location获取元素左上角坐标 3&#xff0c;由此可以计算出元素其他的坐标 二&#xff0c;使用场景 结语 前言 appium做app自动化测试过程中&#xff0c;有时需要获取控件元…

git clean 命令详解

1. git clean 介绍 2. git clean 使用 3. clean 和 reset 命令 1. git clean 介绍 git clean 命令用于删除工作目录中没有被 tracked 的文件 这个命令很多人都不知道&#xff0c;也不去用它&#xff0c;而是通过手动去删除这些文件 这个命令一定要慎用&#xff0c;当你对这…

智源社区AI周刊No.108:Meta发布玩外交游戏的Cicero,登Science;Neuralink实现猴子意念打字...

汇聚每周AI热点&#xff0c;不错过重要资讯&#xff01;欢迎扫码&#xff0c;关注并订阅智源社区AI周刊。Meta发布外交谈判策略系统Cicero&#xff1a;模拟人类参与战略决策&#xff0c;已登《Science》期刊近日&#xff0c;Meta发布人工智能系统Cicero&#xff0c;该系统结合神…

【云原生】k8s 管理平台 rancher

文章目录一、概述二、Rancher 架构三、安装 Rancher1&#xff09;安装Helm2&#xff09;安装ingress-controller3&#xff09;为 Rancher 创建命名空间4&#xff09;选择 SSL 配置5&#xff09;安装 cert-manager6&#xff09;通过 Helm 安装 Rancher2&#xff09;添加 Helm Ch…

电子签名-为你的数据签字画押

博主&#xff1a;爱码叔 个人博客站点&#xff1a; icodebook 公众号&#xff1a;漫话软件设计 专注于软件设计与架构、技术管理。擅长用通俗易懂的语言讲解技术。对技术管理工作有自己的一定见解。文章会第一时间首发在个站上&#xff0c;欢迎大家关注访问&#xff01; 更多密…