数据结构与算法-图

  • 🎈2.图的存储结构
      • 📖2.4.2邻接表的存储
        • ✅2.4.2.1逆邻接表
        • ✅2.4.2.2邻接表存储结构的定义
        • ✅2.4.2.3邻接表存储结构的类定义
        • ✅2.4.2.4创建n个顶点m条边的无向网
        • ✅2.4.2.5创建n个顶点m条边的有向网
        • ✅2.4.2.6定位操作-查找定点信息在顶点数组中的下标
        • ✅2.4.2.7计算顶点的度数-以无向网为例
        • ✅2.4.2.8插入操作-以无向网为例
  • 🎈3.图的遍历
    • 🔭3.1深度优先搜索
      • 📖3.1.1深度优先搜索算法(邻接表存储)
    • 🔭3.2广度优先搜索
      • 📖3.2.1广度优先搜索算法(邻接表存储)
    • 🔭3.3以连通无向图为例进行广度优先搜索和深度优先搜索

🎈2.图的存储结构

📖2.4.2邻接表的存储

在这里插入图片描述

🔎根据邻接表的定义可知,对于n个顶点和e条边的无向图,其邻接表有n个表头结点和2e个边结点。对于n个结点和e条边的有向图,其邻接表有n个表头结点和e个边结点。

✅2.4.2.1逆邻接表

在这里插入图片描述

✅2.4.2.2邻接表存储结构的定义
#define MaxVex 20//自定义最大顶点数
typedef enum 
{DG,UDG,DN,UDN
}GraphKind;//有向图,无向图,有向网,无向网
typedef int VElemType;
typedef struct ArcNode//边结点定义
{int adjvex;//终点(或弧尾)在数组表中的下标int info;///该边(弧)相关信息(权值)ArcNode* nextarc;//存储下一条边(或弧)结点的地址
}ArcNode;
typedef struct//表头结点的定义
{VElemType data;ArcNode* firstarc;//存储第一条依附该顶点的边(或弧)结点地址
}VNode;
typedef struct
{VNode vertices[MaxVex];int vexnum;int arcnum;GraphKind kind;
}AdjLGraph;
✅2.4.2.3邻接表存储结构的类定义
class ALGraph
{
private:AdjLGraph ag;
public:void CreateGraph(int n, int m);//创建n个顶点,m条边的图,以无向网为例int LocateVex(VElemType u);//图中存在顶点u,则返回该顶点在数组中的下标,否则返回-1int Degree(VElemType u);//计算顶点u的度数void InsertArcGraph(VElemType u, VElemType v, int info);//插入一条边void BFS(VElemType v);//以v为初始点的连通分量的广度优先搜索void DFS(VElemType v);//以v为初始点的连通分量的深度优先搜索void BFSTraverse();//图的广度优先搜索void DFSTreverse();//图的深度优先搜索int Connected();//计算连通分量的个数Edge* Kruskal();//Kruskal算法求最小生成树Edge* Prim(VElemTyp u);//prim算法求最小生成树int TopSort();//拓扑排序int CriticalPath();//求关键路径AdjLGraph GetAg(){return ag;//返回私有成员}
};
✅2.4.2.4创建n个顶点m条边的无向网
void ALGraph::CreateGraph(int n, int m)//以无向网为例
{ag.vexnum = n;ag.arcnum = m;ag.kind = UDN;int i, j, w, h, t;VElemType u, v;ArcNode* p;for (i = 0; i < n; i++){cout << "请输入" << n << "个顶点:";cin >> ag.vertices[i].data;ag.vertices[i].firstarc = NULL;}for (j = 0; j < m; j++)//建立边集{cin >> u >> v >> w;//输入一条弧<u,v,w>h = LocateVex(u);t = LocateVex(v);p = new ArcNode;p->adjvex = t;p->info = w;p->nextarc = ag.vertices[h].firstarc;ag.vertices[h].firstarc = p;p = new ArcNode;p->adjvex = h;p->info = w;p->nextarc = ag.vertices[t].firstarc;ag.vertices[t].firstarc = p;}
}
✅2.4.2.5创建n个顶点m条边的有向网
void ALGraph::CreateGraph(int n, int m)
{ag.vexnum = n;ag.arcnum = m;ag.kind = UDN;int i, j, w, h, t;VElemType u, v;ArcNode* p;for (i = 0; i < n; i++){cout << "请输入" << n << "个顶点:";cin >> ag.vertices[i].data;ag.vertices[i].firstarc = NULL;}for (j = 0; j < m; j++)//建立边集{cin >> u >> v >> w;//输入一条弧<u,v,w>h = LocateVex(u);t = LocateVex(v);p = new ArcNode;//<u,v>p->adjvex = t;p->info = w;p->nextarc = ag.vertices[h].firstarc;ag.vertices[h].firstarc = p;}
}
✅2.4.2.6定位操作-查找定点信息在顶点数组中的下标
int ALGraph::LocateVex(VElemType u)
{for (int i = 0; i < ag.vexnum; i++){if (u == ag.vertices[i].data)return i;}return -1;
}
✅2.4.2.7计算顶点的度数-以无向网为例
int ALGraph::Degree(VElemType u)
{int h = LocateVex(u);//结点u的下标int count = 0;ArcNode* p = ag.vertices[h].firstarc;//p指向第h条链表的第一个结点while (p){count++;p = p->nextarc;}return count;
}
✅2.4.2.8插入操作-以无向网为例
void ALGraph::InsertArcGraph(VElemType u, VElemType v, int info)//无向网为例
{int h = LocateVex(u);int t = LocateVex(v);ArcNode* p;if (h == -1){ag.vertices[ag.vexnum].data = u;ag.vertices[ag.vexnum].firstarc = NULL;h = ag.vexnum;ag.vexnum++;}if (t == -1){ag.vertices[ag.vexnum].data = v;ag.vertices[ag.vexnum].firstarc = NULL;t = ag.vexnum;ag.vexnum++;}p = new ArcNode;p->adjvex = t;p->info = info;p->nextarc = ag.vertices[h].firstarc;ag.vertices[h].firstarc = p;p = new ArcNode;p->adjvex = h;p->info = info;p->nextarc = ag.vertices[t].firstarc;ag.vertices[t].firstarc = p;ag.arcnum++;
}

🎈3.图的遍历

在这里插入图片描述

🔭3.1深度优先搜索

✅深度优先搜索类似于树的先序遍历,是树的先序遍历的推广。深度优先搜索是一个不断探查和回溯的过程,具体过程如下:

  1. 从图中某顶点v出发,访问顶点v
  2. 从v的未被访问过的邻接点中选择一个顶点出发,继续对图进行深度优先遍历。若从图中某个顶点出发的所有邻接点都已被访问过,则退回前一个结点继续上述过程,若退回初始点,则以v为初始点的搜索结束。
  3. 若为非连通图,图中尚有未被访问过的顶点,则另选图中一个未曾访问过的顶点作为初始点,重复上述过程,直到图中所有顶点均被访问为止。

❗说明:

  1. 若无向图是连通图,则一次遍历就能访问图中所有的顶点。
  2. 若无向图是非连通图,则只能访问到初始点所在连通分量中的所有顶点,还需要从其他分量中再选择初始点,分别进行遍历才能访问到图中所有顶点。
  3. 对于有向图来说,若从初始点到图中每个顶点都有路径,则一次遍历能够访问图中所有顶点,否则,同样需要在选择初始点继续进行遍历,直到图中所有顶点均被访问为止。

在这里插入图片描述

📖3.1.1深度优先搜索算法(邻接表存储)

int visited[MaxVex];//访问标志数组,初始化所有元素值为0
void ALGraph::DFS(VElemType v)//以v为初始点的连通分量的深度优先搜索算法如下
{ArcNode* p;int h = LocateVex(v);cout << v;//访问该顶点visited[h] = 1;//置访问标记为1for (p = ag.vertices[h].firstarc; p; p = p->nextarc){if (visited[p->adjvex] == 0)DFS(ag.vertices[p->adjvex].data);}
}
void ALGraph::DFSTreverse()//对图作深度优先搜索
{int i;for (i = 0; i < ag.vexnum; i++){visited[i] = 0;//访问标志初始化}for (i = 0; i < ag.vexnum; i++){if (!visited[i])//对尚未访问的顶点调用DFSDFS(ag.vertices[i].data);}
}

🔭3.2广度优先搜索

🔎广度优先搜索类似于树的层次遍历方法,其搜索过程如下:

  1. 访问初识顶点v
  2. 访问与v相邻的所有未被访问的邻接点w1,w2,w3…wk
  3. 依次从这些邻接点出发,访问它们的所有未被访问的邻接点。
  4. 依次类推,直到连通图中所有访问过的顶点的邻接点都被访问。
  5. 若为非连通图,图中尚有未被访问过的顶点,则另选图中的一个未曾访问过的顶点作为初始点,重复上述过程,直到图中所有顶点均被访问过为止。

在这里插入图片描述

📖3.2.1广度优先搜索算法(邻接表存储)

void ALGraph::BFS(VElemType v)//以v为初始点的连通分量的广度优先搜索
{int h = LocateVex(v);ArcNode* p;LinkQueue lq;lq.DeQueue(h);visited[h] = 1;while (!lq.EmptyQueue()){lq.DeQueue(h);cout << ag.vertices[h].data;for (p = ag.vertices[h].firstarc; p; p = p->nextarc){if (!visited[p->adjvex]){lq.EnQueue(p->adjvex);visited[p->adjvex] = 1;}}}
}
void ALGraph::BFSTraverse()
{int i;for (i = 0; i < ag.vexnum; i++){visited[i] = 0;}for (i = 0; i < ag.vexnum; i++){if (!visited[i])BFS(ag.vertices[i].data);}
}

🔭3.3以连通无向图为例进行广度优先搜索和深度优先搜索

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <queue>
using namespace std;
#define MaxVex 20//自定义最大顶点数
typedef char VElemType;
typedef struct ArcNode//边结点定义
{int adjvex;//终点(或弧尾)在数组表中的下标int info;///该边(弧)相关信息(权值)ArcNode* nextarc;//存储下一条边(或弧)结点的地址
}ArcNode;
typedef struct//表头结点的定义
{VElemType data;ArcNode* firstarc;//存储第一条依附该顶点的边(或弧)结点地址
}VNode;
typedef struct
{VNode vertices[MaxVex];int vexnum;int arcnum;
}AdjLGraph;
class ALGraph
{
private:AdjLGraph ag;
public:void CreateGraph(int n, int m);//创建n个顶点,m条边的图,以无向网为例int LocateVex(VElemType u);//图中存在顶点u,则返回该顶点在数组中的下标,否则返回-1int Degree(VElemType u);//计算顶点u的度数void InsertArcGraph(VElemType u, VElemType v, int info);//插入一条边void BFS(VElemType v);//以v为初始点的连通分量的广度优先搜索void DFS(VElemType v);//以v为初始点的连通分量的深度优先搜索void BFSTraverse();//图的广度优先搜索void DFSTreverse();//图的深度优先搜索AdjLGraph GetAg(){return ag;//返回私有成员}
};
void ALGraph::CreateGraph(int n, int m)//以无向网为例
{ag.vexnum = n;ag.arcnum = m;int i, j, w, h, t;VElemType u, v;ArcNode* p;cout << "请输入" << n << "个顶点:";for (i = 0; i < n; i++){cin >> ag.vertices[i].data;ag.vertices[i].firstarc = NULL;}cout << "请输入" << m << "条边(u,v,w):" << endl;for (j = 0; j < m; j++)//建立边集{cin >> u >> v >> w;//输入一条弧<u,v,w>h = LocateVex(u);t = LocateVex(v);p = new ArcNode;//<u,v>p->adjvex = t;p->info = w;p->nextarc = ag.vertices[h].firstarc;ag.vertices[h].firstarc = p;p = new ArcNode;//<v,u>p->adjvex = h;p->info = w;p->nextarc = ag.vertices[t].firstarc;ag.vertices[t].firstarc = p;}
}
int ALGraph::LocateVex(VElemType u)
{for (int i = 0; i < ag.vexnum; i++){if (u == ag.vertices[i].data)return i;}return -1;
}
int ALGraph::Degree(VElemType u)
{int h = LocateVex(u);//结点u的下标int count = 0;ArcNode* p = ag.vertices[h].firstarc;//p指向第h条链表的第一个结点while (p){count++;p = p->nextarc;}return count;
}
void ALGraph::InsertArcGraph(VElemType u, VElemType v, int info)//无向网为例
{int h = LocateVex(u);int t = LocateVex(v);ArcNode* p;if (h == -1){ag.vertices[ag.vexnum].data = u;ag.vertices[ag.vexnum].firstarc = NULL;h = ag.vexnum;ag.vexnum++;}if (t == -1){ag.vertices[ag.vexnum].data = v;ag.vertices[ag.vexnum].firstarc = NULL;t = ag.vexnum;ag.vexnum++;}p = new ArcNode;p->adjvex = t;p->info = info;p->nextarc = ag.vertices[h].firstarc;ag.vertices[h].firstarc = p;p = new ArcNode;p->adjvex = h;p->info = info;p->nextarc = ag.vertices[t].firstarc;ag.vertices[t].firstarc = p;ag.arcnum++;
}
int visited[MaxVex];//访问标志数组,初始化所有元素值为0
void ALGraph::DFS(VElemType v)//以v为初始点的连通分量的深度优先搜索算法如下
{ArcNode* p;int h = LocateVex(v);cout << v;//访问该顶点visited[h] = 1;//置访问标记为1for (p = ag.vertices[h].firstarc; p; p = p->nextarc){if (visited[p->adjvex] == 0)DFS(ag.vertices[p->adjvex].data);}
}
void ALGraph::DFSTreverse()//对图作深度优先搜索
{cout << "深度优先搜索的序列为:";int i;for (i = 0; i < ag.vexnum; i++){visited[i] = 0;//访问标志初始化}for (i = 0; i < ag.vexnum; i++){if (!visited[i])//对尚未访问的顶点调用DFSDFS(ag.vertices[i].data);}cout << endl;
}
void ALGraph::BFS(VElemType v)//以v为初始点的连通分量的广度优先搜索
{int h = LocateVex(v);ArcNode* p;queue<VElemType> lq;lq.push(h);visited[h] = 1;while (!lq.empty()){h = lq.front();lq.pop();cout << ag.vertices[h].data;for (p = ag.vertices[h].firstarc; p; p = p->nextarc){if (!visited[p->adjvex]){lq.push(p->adjvex);visited[p->adjvex] = 1;}}}
}
void ALGraph::BFSTraverse()
{cout << "广度优先搜索的序列为:";int i;for (i = 0; i < ag.vexnum; i++){visited[i] = 0;}for (i = 0; i < ag.vexnum; i++){if (!visited[i])BFS(ag.vertices[i].data);}cout << endl;
}
int main()
{ALGraph p;p.CreateGraph(8, 9);p.BFSTraverse();p.DFSTreverse();return 0;
}

✅运行示例:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统:操作系统教程第六版(骆斌、葛季栋、费翔林)习题一计算机操作系统概述

目录 前言1. 思考题2. 应用题 前言 本系列文章是针对操作系统教程第六版&#xff08;骆斌、葛季栋、费翔林&#xff09;的习题解答&#xff0c;其中简答题部分为博主自己搜索整理的&#xff0c;错漏之处在所难免。应用题部分有答案为依据。 1. 思考题 &#xff08;1&#xf…

【深度学习实验】注意力机制(一):注意力权重矩阵可视化(矩阵热图heatmap)

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 理论介绍a. 认知神经学中的注意力b. 注意力机制&#xff1a; 1. 注意力权重矩阵可视化&#xff08;矩阵热图&#xff09;a. 导入必要的库b. 可视化矩阵热图&#xff08;show_heatmaps&#xff0…

pythongui实时闹钟

# codinggbk import tkinter as tk from time import strftime# 创建一个主窗口 root tk.Tk() root.title("实时闹钟")# 设置窗口的大小不可变 root.resizable(False, False)# 设置窗口始终保持在最上层 root.attributes(-topmost, True)# 更新时间的函数 def time(…

三菱PLC 模拟量输出模拟量转换功能块S_RTI(内嵌ST)

模拟量输出模拟量转换功能块S_RTI算法原理和公式介绍请参考下面文章链接: PLC模拟量输出 模拟量转换FC S_RTI-CSDN博客文章浏览阅读5.3k次,点赞2次,收藏11次。1、本文主要展示西门子博途模拟量输出转换的几种方法, 方法1:先展示下自编FC:计算公式如下:intput intput Rea…

大模型的语言能力

NLP作为一个领域为基础模型开辟了道路。虽然这些模型在标准基准测试中占据主导地位&#xff0c;但这些模型目前获得的能力与那些将语言描述为人类交流和思维的复杂系统的能力之间存在明显的差距。针对这一点&#xff0c;我们强调语言变异的全部范围&#xff08;例如&#xff0c…

元素水平垂直居中

方法一&#xff1a;定位transform 方法二&#xff1a;flex布局 方法三&#xff1a;定位margin【需要child 元素自身的宽高】 相关HTML代码&#xff1a; <div class"parent"><div class"child"></div> </div> 方法一&#xff1a…

华媒舍:怎样成为谷歌竞价排名羸家?10个方法

谷歌竞价排名是一种线上广告方式&#xff0c;企业通过推广广告来提高在搜索结果中的排名。这类排名方法帮助企业吸引更多浏览量和潜在用户。以下属于10个能够帮助你在谷歌竞价排名中获得成功的基石方法&#xff1a; 关键字科学研究&#xff1a;挑选与你产品和服务相关的关键词至…

k8s的高可用集群搭建,详细过程实战版

kubernetes高可用集群的搭建 前面介绍过了k8s单master节点的安装部署 今天介绍一下k8s高可用集群搭建 环境准备&#xff1a; vip &#xff1a;192.168.121.99 keeplive master01&#xff1a;192.168.121.153 centos7 master02&#xff1a;192.168.121.154 centos7 master03&a…

DSP2335的LED工程笔记

首先是确定时钟 在技术参考中&#xff0c;找到时钟章节 只能观察每个寄存器&#xff0c;才能看到寄存器控制那个外设的时钟 第二找到对应GPIO以及寄存器&#xff1b; 在我板子里面的原理图是 但是TI的提供的库函数是分ABC的&#xff0c;刚开始就不知道怎麽分。GPIO68到GPIO6…

Transformer笔记

Transformer encoder-decoder架构 Encoder&#xff1a;将输入序列转换为一个连续向量空间中的表示。Encoder通常是一个循环神经网络&#xff08;RNN&#xff09;或者卷积神经网络&#xff08;CNN&#xff09;&#xff0c;通过对输入序列中的每个元素进行编码&#xff0c;得到…

思维模型 留白效应

本系列文章 主要是 分享 思维模型 &#xff0c;涉及各个领域&#xff0c;重在提升认知。因留白而遐想。 1 留白效应的应用 1.1 留白效应在艺术领域的应用 欧洲的艺术和设计领域有很多经典的实际案例&#xff0c;其中荷兰画家文森特梵高的作品《星夜》是一幅非常著名的油画&am…

(动手学习深度学习)第13章 计算机视觉---微调

文章目录 微调总结 微调代码实现 微调 总结 微调通过使用在大数据上的恶道的预训练好的模型来初始化模型权重来完成提升精度。预训练模型质量很重要微调通常速度更快、精确度更高 微调代码实现 导入相关库 获取数据集 数据增强 定义和初始化模型 微调模型 训练模型