代码随想录算法训练营day50:图论01:图论理论基础;深度优先搜索理论基础;98. 所有可达路径;广度优先搜索理论基础

news2024/11/30 2:51:29

图论理论基础

分类:有向图,无向图,有无权重

度:【无向图】:有几条边连接该节点,该节点就有几度。

【有向图】:每个节点有出度和入度。出度:从该节点出发的边的个数。入度:指向该节点边的个数。

连通情况:

       【无向图】:任意两个点之间都有路径可达——连通图

                             如果有节点不能到达其他节点,则为非连通图 

                             在无向图中的极大连通子图称之为该图的一个连通分量

        【有向图】:任何两个节点是可以相互到达的,我们称之为 强连通图

                                有可能出现1能到2,2不能到1的情况。

                                在有向图中极大强连通子图称之为该图的强连通分量

图的存储:

邻接矩阵

使用 二维数组来表示图结构。

邻接矩阵是从节点的角度来表示图,有多少节点就申请多大的二维数组

例如: grid[2][5] = 6,表示 节点 2 连接 节点5 为有向图,节点2 指向 节点5,边的权值为6。

如果想表示无向图,即:grid[2][5] = 6,grid[5][2] = 6,表示节点2 与 节点5 相互连通,权值为6。

如图:

在一个 n (节点数)为8 的图中,就需要申请 8 * 8 这么大的空间。

图中有一条双向边,即:grid[2][5] = 6,grid[5][2] = 6

这种表达方式(邻接矩阵) 在 边少,节点多的情况下,会导致申请过大的二维数组,造成空间浪费。

而且在寻找节点连接情况的时候,需要遍历整个矩阵,即 n * n 的时间复杂度,同样造成时间浪费。

邻接矩阵的优点:

  • 表达方式简单,易于理解
  • 检查任意两个顶点间是否存在边的操作非常快
  • 适合稠密图,在边数接近顶点数平方的图中,邻接矩阵是一种空间效率较高的表示方法。

缺点:

  • 遇到稀疏图,会导致申请过大的二维数组造成空间浪费
  • 不适合遍历,遍历 边 的时候需要遍历整个n * n矩阵,造成时间浪费

代码:

  

邻接表

邻接表 使用 数组 + 链表的方式来表示。 邻接表是从边的数量来表示图,有多少边 才会申请对应大小的链表。

邻接表的构造如图:

这里表达的图是:

  • 节点1 指向 节点3 和 节点5
  • 节点2 指向 节点4、节点3、节点5
  • 节点3 指向 节点4
  • 节点4指向节点1

有多少边 邻接表才会申请多少个对应的链表节点。

从图中可以直观看出 使用 数组 + 链表 来表达 边的连接情况 。

邻接表的优点:

  • 对于稀疏图的存储,只需要存储边,空间利用率高
  • 遍历节点连接情况相对容易

缺点:

  • 检查任意两个节点间是否存在边,效率相对低,需要 O(V)时间,V表示某节点连接其他节点的数量。
  • 实现相对复杂,不易理解

代码实现:

  

   

图的遍历方式

图的遍历方式基本是两大类: 

  • 深度优先搜索(dfs)
  • 广度优先搜索(bfs)

在讲解二叉树章节的时候,其实就已经讲过这两种遍历方式。

二叉树的递归遍历,是dfs 在二叉树上的遍历方式。

二叉树的层序遍历,是bfs 在二叉树上的遍历方式。

dfs 和 bfs 一种搜索算法,可以在不同的数据结构上进行搜索,在二叉树章节里是在二叉树这样的数据结构上搜索。

而在图论章节,则是在图(邻接表或邻接矩阵)上进行搜索。

深度优先搜索理论基础

二者区别:

  • dfs是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,再换方向(换方向的过程就涉及到了回溯)。
  • bfs是先把本节点所连接的所有节点遍历一遍,走到下一个节点的时候,再把连接节点的所有节点遍历一遍,搜索方向更像是广度,四面八方的搜索过程。

dfs:

  • 搜索方向,是认准一个方向搜,直到碰壁之后再换方向
  • 换方向是撤销原路径,改为节点链接的下一个路径,回溯的过程。

代码:

主要分为三个板块:

1、递归函数、递归参数

二维数组数组结构保存所有路径,需要一维数组保存单一路径,这种保存结果的数组,我们可以定义一个全局变量,避免让我们的函数参数过多。

2、确认终止条件

结束递归,并且收获结果

3、 处理目前搜索节点出发的路径

 

98. 所有可达路径

对于print来说

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h>
#include <string.h>

//如何开辟
typedef struct anode{//边结点,一个anode代表一条从头结点-thisnode的边
    int thisnode;//这条边 的另外一个终点 的编号
    struct anode *nextnode;//指向下一条边
    //int weight;//记录这条边的权重
}Arcnode;

typedef struct vnode{//头结点
    int thisnode;//顶点编号
    Arcnode* firstarc;//指向第一条边
}Vnode;

typedef struct{
    Vnode adjlist[100];//邻接表
    int n,m;//顶点,边数
}gragh;

//dfs的写法
void dfs(gragh *g,int x,int n,int* path,int index){
    if(x==n){
        for(int i=0;i<index-1;i++){
            printf("%d ",path[i]);
        }
        printf("%d\n",path[index-1]);
        return;
    }
    
    Arcnode *p = g->adjlist[x].firstarc;
    while(p!=NULL){
        int w=p->thisnode;
        path[index]=w;
        dfs(g,w,n,path,index+1);
        p=p->nextnode;
    }
}

int main(){
    int n,m;//n是结点,m是边

    gragh *g=(gragh*)malloc(sizeof(gragh));
    scanf("%d%d",&n,&m);
    
    
    g->n=n;
    g->m=m;

    for(int i=1;i<=n;i++) g->adjlist[i].firstarc=NULL;
    
    //如何创建邻接表
    for(int i=0;i<m;i++){
        int s,t;
        scanf("%d%d",&s,&t);
        Arcnode *newnode=(Arcnode*)malloc(sizeof(Arcnode));
        newnode->thisnode = t;
        newnode -> nextnode = g->adjlist[s].firstarc;
        g->adjlist[s].firstarc = newnode;
    }

    for (int i=1;i<=n;i++){
        printf("start %d->",i);
        Arcnode *p=g->adjlist[i].firstarc;
        while(p!=NULL){
            printf("%d",p->thisnode);
            p=p->nextnode;
        }
        printf("\n");
    }
    
    int path[101];
    path[0]=1;

    dfs(g,1,n,path,1);

    return 0;
}

但提交报错,怀疑是没有处理输出-1的情况,加上果然好了^-^很巧妙的逃避了创建个大矩阵

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h>
#include <string.h>
//建立邻接表数据结构:分三步
//存放每条边 终点——arcnode
//存放每个顶点(作为起点)——vnode
//邻接表本体 ——gragh
typedef struct anode{//边结点,一个anode代表一条从头结点-thisnode的边
    int thisnode;//这条边 的另外一个终点 的编号
    struct anode *nextnode;//指向下一条边
    //int weight;//记录这条边的权重
}Arcnode;

typedef struct vnode{//头结点
    int thisnode;//顶点编号
    Arcnode* firstarc;//指向第一条边
}Vnode;

typedef struct{
    Vnode adjlist[100];//邻接表
    int n,m;//顶点,边数
}gragh;

int flag=0;

void dfs(gragh *g,int x,int n,int* path,int index){
    if(x==n){
        flag=1;
        for(int i=0;i<index-1;i++){
            printf("%d ",path[i]);
        }
        printf("%d\n",path[index-1]);
        return;
    }
    
    Arcnode *p = g->adjlist[x].firstarc;
    while(p!=NULL){
        int w=p->thisnode;
        path[index]=w;
        dfs(g,w,n,path,index+1);
        p=p->nextnode;
    }
}

int main(){
    int n,m;//n是结点,m是边

    gragh *g=(gragh*)malloc(sizeof(gragh));
    scanf("%d%d",&n,&m);
    
    //初始化 邻接矩阵:
    //三步走:
    //赋值边数、顶点数
    //firstarc指针全部指向空
    //遍历每条边:创建Arcnode,找到起点对应的g->adjlist[start].firstarc,记录终点arcnode->thisnode=end;尾插法建表
    g->n=n;
    g->m=m;

    for(int i=1;i<=n;i++) g->adjlist[i].firstarc=NULL;

    for(int i=0;i<m;i++){
        int s,t;
        scanf("%d%d",&s,&t);
        Arcnode *newnode=(Arcnode*)malloc(sizeof(Arcnode));
        newnode->thisnode = t;
        newnode -> nextnode = g->adjlist[s].firstarc;
        g->adjlist[s].firstarc = newnode;
    }
    
    
    int path[101];
    path[0]=1;

    dfs(g,1,n,path,1);
    
    if(flag==0) printf("-1");
    return 0;
}

邻接矩阵版:主要是注意矩阵的编号 和 真实顶点的编号

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h>
#include <string.h>

#define max 100

//邻接矩阵 两步走
//vnode 包括所有每个顶点的信息
//gragh 三部分:顶点、边长信息;
typedef struct node{
    int no;
    //int otherdata;
}vnode;

typedef struct www{
    int excel[max][max];
    vnode list[max];
    int n,e;
}gragh;

int flag=0;
void dfs(gragh *g,int x,int n,int index,int*path){
    if(x==n){
        flag=1;
        for(int i=0;i<index-1;i++){
            printf("%d ",path[i]);
        }
        printf("%d\n",path[index-1]);
        return;
    }
    for(int j=1;j<=n;j++){
        if(g->excel[x-1][j-1]==1){
            path[index]=j;
            dfs(g,j,n,index+1,path);
        }
    }

}

int main(){
    int n,m;
    scanf("%d%d",&n,&m);

    gragh*g=(gragh*)malloc(sizeof(gragh));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++) g->excel[i][j]=0;
        g->list[i].no=i+1;
    }

    for(int i=0;i<m;i++){
        int s,t;
        scanf("%d%d",&s,&t);
        g->excel[s-1][t-1]=1;
    }

    int path[100];
    path[0]=1;
    dfs(g,1,n,1,path);
    if(flag==0) printf("-1");
    

    return 0;
}

广度优先搜索理论基础

适合于解决两个点之间的最短路径问题

广搜是从起点出发,以起始点为中心一圈一圈进行搜索,一旦遇到终点,记录之前走过的节点就是一条最短路

当然,也有一些问题是广搜 和 深搜都可以解决的,例如岛屿问题,这类问题的特征就是不涉及具体的遍历方式,只要能把相邻且相同属性的节点标记上就行

  

  

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

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

相关文章

.net maui安卓开发中适用明文传输(一)

背景:最近在做一个pad上的项目,目的是执行每日点检功能(就是检查设备的各项保养指标);前期用HBuilder做了一个,但是现场的触摸屏选用的是TouchPie 安卓版本是6.0版本,上次开发的软件可以在安卓7.0上完美兼容,但由于触摸屏安卓版本太低不能兼容;询问厂商才知道这款触摸…

前端性能优化的指标

性能优化指标的出现,谷歌在2020年提出的Core Web Vitals 和 Web Vitals 了解谷歌浏览器自带的性能调试工具DCL、L、FP、FCP、LCP,图层(有layout布局就是回流,painting绘制就是重绘) 回流和重绘的理解 页面第一次打开一定回流和重绘,回流一定重绘,回流出现一般是位置改变…

BEV世界:通过统一的BEV潜在空间实现自动驾驶的多模态世界模型

BEVWorld: A Multimodal World Model for Autonomous Driving via Unified BEV Latent Space BEV世界&#xff1a;通过统一的BEV潜在空间实现自动驾驶的多模态世界模型 Abstract World models are receiving increasing attention in autonomous driving for their ability t…

【数据结构】PTA 求链表的倒数第m个元素 C语言

请设计时间和空间上都尽可能高效的算法&#xff0c;在不改变链表的前提下&#xff0c;求链式存储的线性表的倒数第m&#xff08;>0&#xff09;个元素。 函数接口定义&#xff1a; ElementType Find( List L, int m ); 其中List结构定义如下&#xff1a; typedef struct…

什么是机器人快换盘?

机器人快换盘&#xff0c;行业内也称作工具快换盘、换枪盘、快换工具盘、快速更换器、快换器、 快换夹具、治具快换等。是末端执行器快速更换装置&#xff08;End-Of-Arm Tooling&#xff0c;简称EOAT&#xff09;&#xff0c;是工业自动化领域中用于机器人手臂上的一种重要设备…

短视频矩阵工具种类繁多,一招教你轻松做选择!

在当下竞争日益激烈的市场中&#xff0c;选择一个稳定且高效的矩阵营销系统对于企业和实体店来说至关重要&#xff0c;然而众多的工具往往让人难以抉择&#xff0c;今天笔者给大家四个关键筛选点&#xff0c;帮你快速筛选出最合适自己的矩阵营销工具&#xff1a; 1. 功能全面性…

探索AI工作流工具:提升编程效率的三大利器

问题&#xff1a;面对屎山代码&#xff0c;你是如何处理的&#xff1f; 今天我将为你推荐三个强大的AI工作流工具&#xff0c;它们将彻底改变你的编程体验&#xff0c;让你在工作中如鱼得水&#xff0c;事半功倍&#xff01; 1. 代码解释器&#xff1a;解读复杂代码的利器 初…

[CISCN 2023 华北]ez_date

[CISCN 2023 华北]ez_date 点开之后是一串php代码&#xff1a; <?php error_reporting(0); highlight_file(__FILE__); class date{public $a;public $b;public $file;public function __wakeup(){if(is_array($this->a)||is_array($this->b)){die(no array);}if( (…

初级python代码编程学习----简单的图形化闹钟小程序

我们来创建一个简单的图形化闹钟程序通常需要使用图形用户界面&#xff08;GUI&#xff09;库。以下是使用Python的Tkinter库创建一个基本闹钟程序的步骤&#xff1a; 环境准备 确保已安装Python。安装Tkinter库&#xff08;Python 3.8及以上版本自带Tkinter&#xff0c;无需…

计算机毕业设计选题推荐-餐馆满意度分析-Python爬虫-K-means算法-nlp情感分析

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

亿玛科技:TiDB 6.1.5 升级到 7.5.1 经验分享

作者&#xff1a; foxchan 原文来源&#xff1a; https://tidb.net/blog/6e628afd 为什么要升级&#xff1f; 本次升级7.5的目的如下&#xff1a; 1、tidb有太多的分区表需要归档整理。7.5版本这个功能GA了。 2、之前集群tikv节点的region迁移过慢&#xff0c;影响tikv节…

http连接未释放导致生产故障

凌晨4点运维老大收到报警&#xff08;公司官网页面超时&#xff0c;上次故障因为运维修改nginx导致官网域名下某些接口不可用后&#xff0c;运维在2台nginx服务器上放了检测程序&#xff0c;检测官网页面&#xff09;&#xff0c;运维自己先看了看服务器相关配置&#xff0c;后…

linux 安装MAT(MemoryAnalyzerTool),并且分析java dump的方法

当我们的java进程出现异常的时候&#xff0c;我们第一件想做的事情是什么呢&#xff1f;应该就是要分析java的内存了。假如说&#xff0c;我们已经有了一个java内存的dump文件&#xff0c;有哪些的方法&#xff0c;可以对这个导出的dump文件进行分析呢&#xff1f; 比如&#…

Vue插值:双大括号标签、v-text、v-html、v-bind 指令

创建应用程序实例后&#xff0c;需要通过插值进行数据绑定。数据绑定是 Vue.js 最核心的一个特性。建立数据绑定后&#xff0c;数据和视图会相互关联&#xff0c;当数据发生变化时&#xff0c;视图会自动进行更新。这样就无须手动获取 DOM 的值&#xff0c;使代码更加简洁&…

【Python_PyQtGraph 学习笔记(十一)】基于ImageExporter更改导出图片的大小

基于ImageExporter更改导出图片的大小 前言正文1、ImageExporter 类介绍1.1 ImageExporter 类特点1.2 ImageExporter 类用法2、示例代码3、遇到的问题前言 在 基于PyQtGraph设置槽函数,实现保存图片到本地的功能 一文中我们成功地将 PyQtGraph 绘制的图形以图片形式保存到本地…

ChatGPT与Discord的完美结合——团队协作的得力助手

本文将教你如何集成Discord Bot&#xff0c;助力团队在工作中实现更高效的沟通与协作。通过充分发挥ChatGPT的潜力&#xff0c;进一步提升工作效率和团队协作能力。无需编写任何代码即可完成本文所述的操作&#xff0c;进行个性化定制只需对参数进行微调即可。 方案介绍 如果在…

【Python系列】中位数计算

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

鸿蒙开发5.0【基于AVCodecKit】音视频解码及二次处理播放

1&#xff1a;场景描述 场景&#xff1a;基于VideoCoder的音视频解码及二次处理播放。 首先导入选择器picker模块&#xff0c;使用PhotoViewPicker方法拉起图库选择视频文件&#xff0c;将视频文件传递到native侧使用Demuxer解封装器进行解封装&#xff0c;再使用OH_VideoDec…

Yolov8:模型部署到安卓端

1. 项目准备 1.1 先安装JDK和Android studio &#xff08;1&#xff09;JDK下载&#xff1a; 官网站&#xff1a;https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 同意协议后&#xff0c;下载相应版本的JDK 我这里没有下载JDK21版的&a…

作品集图片美化处理网站推荐

今天要做作品集的时候发现单一的截屏很单调&#xff0c;想着看能不能添加一些边框之类的元素使图片更加精美有活力&#xff0c;于是就找到了一个个人认为非常好用的网站镜头 - 创建惊人的模型 (shots.so)&#xff0c;它利用的是ai算法&#xff0c;使用起来非常便捷&#xff0c;…