06数据结构——图

news2024/11/16 4:16:29

6.2图的存储及基本操作

6.2.1邻接矩阵法

图的邻接矩阵存储结构定义如下:

#define MaxVertexNUm 100            //顶点数目的最大值
typedef char VertexType;            //顶点的数据类型
typedef int EdgeType;               //带权图中边上权值的数据类型
typedef struct{
    VertexType Ver[MaxVertexNum];   //顶点表
    EdgeType Edge[MaxVertexNum][MaxVertexNum];    //邻接矩阵,边表
    int vexnum,arcnum;                            //图的当前顶点数和弧数
}MGraph;

6.2.2邻接表法

图的邻接表存储结构定义如下:

#define MaxVertexNum 100                //图中顶点数目的最大值
typedef struct ArcNode{                 //边表结点
    int adjvex;                         //该弧所指向的顶点的位置
    struct ArcNode *next;               //指向下一条弧的指针
    //InfoType info;                    //网的边权值
}ArcNode;
typedef struct VNode{                   //顶点表结点
    VertexType data;                    //顶点信息
    ArcNode *first;                     //指向第一条依附该结点的弧的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{
    AdjList vertices;                   //邻接表
    int vexnum,arcnum;                  //图的顶点数和弧数
}ALGraph;                               //ALGraph是以邻接表存储的图类型

6.2.3十字链表

6.2.4邻接多重表

6.2.5图存储小结 


6.3图的遍历 

6.3.1广度优先搜索(BFS)

1.广度优先搜索算法的伪代码如下:

bool visited[MAX_VERTEX_NUM];        //访问标记数组
void BFSTraverse(Graph G){           //对图G进行广度优先遍历
    for(i=0;i<G.vexnum;++i)
        visited[i]=FALSE;            //访问标记数组初始化
    InitQueue(Q);                    //初始化辅助队列Q
    for(i=0;i<G.vexnum;++i)          //从0号顶点开始遍历
        if(!visited[i])              //对每个连通分量调用一次BFS
            BFS(G,i);                //Vi未访问过,从Vi开始BFS
}
void BFS(Graph G,int v){            //从顶点v出发,广度优先遍历图G
    visit(v);                       //访问初始顶点v
    visited[v]=TRUE;                //对v做已访问标记
    EnQueue(Q,v);                   //顶点v入队列Q
    while(!isEmpty(Q)){
        DeQueue(Q,v);               //顶点v出队列
        for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
                                    //检测v所有邻接点
        if(!visited[w]){            //w为v的尚未访问的邻接顶点
            visit(w);               //访问顶点w
            visited[w]=TRUE;        //对w做已访问标记
            EnQueue(Q,w);           //顶点w入队列
        }
    }
}

2.BFS算法求解单源最短路径问题的算法如下:

void BFS_MIN_Distance(Graph G,int u){
    for(i=0;i<G.vexnum;++i)
        d[i]=∞;                    //初始化路径长度
    visited[u]=TRUE; d[u]=0;
    EnQueue(Q,u);
    while(!isEmpty(Q)){            //BFS算法主过程
        DeQueue(Q,u);              //对头元素u出队
        for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w))
            if(!visited[w]){        //w为u的尚未访问的邻接顶点
                visited[w]=TRUE;    //设已访问标记
                d[w]=d[u]+1;        //路径长度加1
                EnQueue(Q,w);       //顶点w入队
            }
     }
}

 6.3.2深度优先搜索(DFS)

1.用递归进行深度优先搜索算法过程如下:

bool visited[MAX_VERTEX_NUM];        //访问标记数组
void DFSTraverse(Graph G){           //对图G进行深度优先遍历
    for(v=0;v<G.vexnum;++v)
        visited[v]=FALSE;            //初始化已访问标记数组
    for(v=0;v<G.vexnum;++v)          //本代码中是从v=0开始遍历
        if(!visited[v])
            DFS(G,v);
}
void DFS(Graph G,int v){            //从顶点v出发,深度优先遍历图G
    visit(v);                       //访问顶点v
    visited[v]=TRUE;                //设已访问标记
    for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
        if(!visited[w]){            //w为v的尚未访问的邻接顶点
            DFS(G,w);
        }
}

6.4图的应用

6.4.1最小生成树

1.通用的最小生成树算法如下:

GENERIC_MST(G){
    T=NULL;
    while T 未形成一棵生成树;
        do 找到一条最小代价边(u,v)并且加入T后不会产生回路;
            T=T∪(u,v);
}

2.Prim算法

 Prim算法的简单实现如下:

void Prim(G,T){
    T=∅;                //初始化空树
    U={w};              //添加任意一个顶点w
    while((V-U)!=∅){    //若树中不含全部顶点
        设(u,v)是使u∈U与v∈(V-U),且权值最小的边;
        T=T∪{(u,v)};    //边归入树
        U=U∪{v};        //顶点归入树
    }
}

3.Kruskal算法 

 Kruskal算法的步骤如下:

void Kruskal(V,T){
    T=V;                  //初始化树T,仅含顶点
    numS=n;               //连通分量数
    while(numS>1){        //若连通分量数大于1
        从E中取出权值最小的边(v,u);
        if{v和u属于T中不同的连通分量){
            T=T∪{(v,u)};        //将此边加入生成树中
            numS--;              //连通分量数减1
        }
    }
}

6.4.2最短路径

1.Dijkstra算法求单源最短路径问题 

2.Floyd算法求各顶点之间最短路径问题 

Floyd算法实现如下:

//......准备工作,根据图的信息初始化矩阵A和path(如上图)
for(int k=0;k<n;k++){        //考虑以Vk作为中转点
    for(int i=0;i<n;i++){    //遍历整个矩阵,i为行号,j为列号
        for(int j=0;j<n;j++){
            if(A[i][j]>A[i][k]+A[k][j]){    //以Vk为中转点的路径更短
                A[i][j]=A[i][k]+A[k][j];    //更新最短路径长度
                path[i][j]=k;               //中转点
            }
        }
    }
}

6.4.3求最短路径小结 

6.4.4有向无环图描述表达式 

6.4.5拓扑排序 

拓扑排序算法的实现如下:

bool TopologicalSort(Graph G){
    InitStack(S);                //初始化栈,存储入度为0的顶点
    int i;
    for(i=0;i<G.vexnum;i++)
        if(indegree[i]==0)
            Push(S,i);           //将所有入度为0的顶点进栈
    int count=0;                 //计数,记录当前已经输出的顶点数
    while(!isEmpty(S)){          //栈不空,则存在入度为0的顶点
        Pop(S,i);                //栈顶元素出栈
        print[count++]=i;        //输出顶点i
        for(p=G.vertices[i].firstarc;p;p=p->nextarc){
        //将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈S
            v=p->adjvex;  
            if(!(--indegree[v]))
                Push(S,v);       //入度为0,则入栈
        }
    }//while
    if(count<G.vexnum)
        return false;            //排序失败,有向无环图中有回路
    else
        return true;            //拓扑排序成功
}

 6.4.6关键路径

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

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

相关文章

webrtc-stream编译报错记录

磁盘空间不足错误 错误信息 677.2 fatal: cannot create directory at blink/web_tests/external/wpt: No space left on device说明&#xff1a;这个错误是由于本地在配置docker资源时所给磁盘空间太小导致&#xff0c;直接根据镜像大小合理分配资源大小即可 pushd和popd执…

Android Studio新功能-设备镜像Device mirroring-在电脑侧显示手机实时画面并可控制

下载最新的灰测版本-蜥蜴 成功运行到真机后&#xff0c;点击右侧Running Devices选项卡&#xff0c;再点击号 选中当前设备&#xff1b; 非常丝滑同步&#xff0c;在电脑侧也可以顺畅控制真机 该功能大大方便了我们视线保持在显示器上专注开发&#xff0c;并且便于与UI视觉进行…

【Rust日报】2023-10-22 Korvin - 一个 WASM 前端框架,比基线 vanillajs 实现快了 33%!...

Yazi v0.1.5 发布 - 有史以来最大的更新 Yazi - &#x1f4a5; 用 Rust 编写的基于异步 I/O 的快速终端文件管理器。 嘿伙计&#xff01;我很高兴在这里宣布Yazi v0.1.5 发布了&#xff01; 这是有史以来最大的更新&#xff0c;也是周期最长的更新。该版本带来了许多有意义的变…

【进程VS容器VS虚拟机】

进程 VS 容器 VS 虚拟机 如果站在技术实现原理的角度来看&#xff0c;其实容器更像进程&#xff0c;而非虚拟机。 但是如果我们讨论这门技术的应用场景、解决的问题、终端用户是如何使用的&#xff0c;就会发现容器跟虚拟机非常相似&#xff0c;它们解决的是同样的问题&#…

渗透测试工具-sqlmap

sqlmap是一个开源渗透测试的自动化工具&#xff0c;可以自动检测和利用SQL注入漏洞并接管数据库服务器。它配备了一个强大的检测引擎&#xff0c;许多用于终极渗透测试的利基功能&#xff0c;以及广泛的开关&#xff0c;包括数据库指纹识别、从数据库中获取数据、访问底层文件系…

悟空crm安装搭建 报错[0] RedisException in Redis.php line 56问题处理办法

相信很多朋友进行安装悟空crm的时候 提示错误&#xff1a; [0] RedisException in Redis.php line 56 Connection refused 不知道怎么样处理是吧~~~ $this->options array_merge($this->options, $options);}# redis 密码$password config(cache.password);if (!empty…

1024特别剪辑: 使用Python Turtle 库绘制一棵随机生成的树

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

【excel技巧】excel单元格内如何换行?

Excel表格&#xff0c;在制作完成之后&#xff0c;在输入数据的时候&#xff0c;总是会遇到内容长度太长导致无法全部显示或者破坏表格整体格式。几天分享4个单元格换行的方法给大家。 方法一&#xff1a; 首先我们先介绍一个&#xff0c;通过调整列宽的方式来达到显示全部内…

xcode The document “...“ could not be saved

Today when I tried to save a file on my project I get an error message saying: The document “nameOfFile.m” could not be saved. I tried reinstalling xcode but no luck. The file can be edited with other editors and I see the same behavior on all my project…

C# Enum.TryParse字符串既可以使用名称也可以使用数字值

var tryParse Enum.TryParse<LicenseType>("0", out var licenseType);以前没留意&#xff0c;以为将字符串装枚举的方法Enum.TryParse的字符串只能填名称&#xff0c;最近发现字符串是数字值也可以转换成相应的枚举

DevOps持续集成-Jenkins(4)

❤️作者简介&#xff1a;2022新星计划第三季云原生与云计算赛道Top5&#x1f3c5;、华为云享专家&#x1f3c5;、云原生领域潜力新星&#x1f3c5; &#x1f49b;博客首页&#xff1a;C站个人主页&#x1f31e; &#x1f497;作者目的&#xff1a;如有错误请指正&#xff0c;将…

【Android Studio】工程中文件Annotate with Git Blame 不能点击

问题描述 工程文件中想要查看代码提交信息但是相关按钮不可点击 解决方法 Android Studio -> Preferences -> Version Control-> 在Unregistered roots里找到你想要的工程文件 点击左上角➕号 然后右下角Apply即可

扩展 Calcite 中的 SQL 解析语法

Calcite中 JavaCC 的使用方法 Calcite 默认采用 JavaCC 来生成词法分析器和语法分析器。 1&#xff09;使用 JavaCC 解析器 Calcite中&#xff0c;JavaCC 的依赖已经被封装到 calcite-core 模块当中&#xff0c;如果使用 Maven 作为依赖管理工具&#xff0c;只需要添加对应的…

PCL 视图变换(OpenGL)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在OpenGL中存在这样一个过程,即模拟人类看东西的过程,通过一种视图变换方式将物体置入观察空间内,以此让我们可以看到这个物体。这个过程有点类似于将一个照相机移到了模型前方的某个位置,然后再设置一下照相机…

【广州华锐互动】VR消防员模拟灭火:身临其境的火场救援

随着科技的不断发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术已经逐渐渗透到各个领域&#xff0c;为我们带来了前所未有的沉浸式体验。在这其中&#xff0c;VR模拟消防员灭火体验无疑是一种极具创新性和实用性的应用。通过这项技术&#xff0c;人们可以亲身体验到消…

RabbitMQ原理(五):消费者的可靠性

文章目录 3.消费者的可靠性3.1.消费者确认机制3.2.失败重试机制3.3.失败处理策略3.4.业务幂等性3.4.1.唯一消息ID3.4.2.业务判断 3.5.兜底方案 3.消费者的可靠性 当RabbitMQ向消费者投递消息以后&#xff0c;需要知道消费者的处理状态如何。因为消息投递给消费者并不代表就一定…

STM32 invalid UTF-8 in comment 警告解决办法

这里写自定义目录标题 STM32 invalid UTF-8 in comment 警告解决办法问题描述解决办法 STM32 invalid UTF-8 in comment 警告解决办法 问题描述 …/…/libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x\stm32f10x.h(18): warning: invalid UTF-8 in comment [-Winvalid-utf8]…

正点原子嵌入式linux驱动开发——Linux PWM驱动

PWM是很常用到功能&#xff0c;可以通过PWM来控制电机速度&#xff0c;也可以使用PWM来控制LCD的背光亮度。本章就来学习一下如何在Linux下进行PWM驱动开发。 PWM驱动解析 不在介绍PWM是什么了&#xff0c;直接进入使用。 给LCD的背光引脚输入一个PWM信号&#xff0c;这样就…

Node编写更新用户信息接口

目录 前言 定义路由和处理函数 验证表单数据 实现更新用户基本信息的功能 前言 继前面几篇文章&#xff0c;本文介绍如何编写更新用户信息接口 定义路由和处理函数 路由 // 更新用户信息接口 router.post(/userinfo, userinfo_handler.updateUserinfo) 处理函数 // 导…

Netty实战-实现自己的通讯框架

通信框架功能设计 功能描述 通信框架承载了业务内部各模块之间的消息交互和服务调用&#xff0c;它的主要功能如下&#xff1a; 基于 Netty 的 NIO 通信框架&#xff0c;提供高性能的异步通信能力&#xff1b;提供消息的编解码框架&#xff0c;可以实现 POJO 的序列化和反序…