【数据结构】图的定义,存储,遍历

news2025/1/16 18:42:20

🎊专栏【数据结构】

🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。

🎆音乐分享【Dream It Possible】

大一同学小吉,欢迎并且感谢大家指出我的问题🥰

目录

🍔前言

🎁图的定义 

 🏳️‍🌈有向完全图

🏳️‍🌈无向完全图

🎁存储结构

🏳️‍🌈邻接矩阵 

🎈代码

🏳️‍🌈采用邻接矩阵表示法创建无向  网

🎈算法步骤

🎈算法描述

 🏳️‍🌈采用邻接矩阵表示法创建无向  网

🎁图的遍历

 🏳️‍🌈深度优先遍历

🎈算法步骤

🎈算法描述

🎁广度优先遍历

🎈算法步骤

🎈算法描述

🎁附加 

🏳️‍🌈实验题目

🏳️‍🌈代码

🏳️‍🌈运行结果 


🍔前言

        图是一种比线性表和树更为复杂的数据结构。在线性表中,数据元素之间仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继;在树结构中,数据元素之间有着明显的层次关系,并且每一层中的数据元素可能和下一层中的多个元素(其孩子结点)相关,但只能和上一层中一个元素(其双亲结点)相关;而在图结构中,结点之间的关系可以是任意的,图中任意两个数据元素都可能相关。由此,图的应用极为广泛,已渗入诸如物理、化学、通信、计算机,以及数学等领域。在离散数学中,图论是专门研究图的性质的数学分支,而在数据结构中,则应用图论的知识讨论如何在计算机上实现图的操作,因此本章主要介绍图的存储结构,以及若干图的操作的实现。

🎁图的定义 

        图(Graph)G由两个集合V和E组成,记为G=(V,E),其中V是顶点的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对称为边。V(G)和E(G)通常分别表示图G的顶点集合和边集合,E(G)可以为空集。若E(G)为空,则图G只有顶点而没有边。
        对于图G,若边集E(G)为有向边的集合,则称该图为有向图;若边集E(G)为无向边的集合,则称该图为无向图。
        在有向图中,顶点对<x,y>是有序的,它称为从顶点x到顶点y的一条有向边。因此,<x,y>与1是不同的两条边。顶点对用尖括号括起来,对<x,y>而言,x是有向边的始点,y是有向边的终点。<x,y>也称作一条弧,则x为弧尾,y为弧头。
        在无向图中,顶点对(x,y)是无序的,它称为与顶点x和顶点y相关联的一条边。这条边没有特定的方向,(x,y)与(y,x)是同一条边。为了有别于有向图,无向图的顶点对用一对圆括号括起来。

 🏳️‍🌈有向完全图

有n(n-1)条弧  的图

🏳️‍🌈无向完全图

有n(n-1)/2条边  的图

🎁存储结构

🏳️‍🌈邻接矩阵 

表示顶点之间相邻关系的矩阵,设G(V,E)是具有n个顶点的图,那么G的邻接矩阵有如下性质

(矩阵实在是画不好,绘图能力欠佳,也请大家多多包容🥰) 

 使用邻接矩阵表示图,除了一个用于存储邻接矩阵的二维数组外,还需要一个一维数组来存储顶点信息

🎈代码

//图的 邻接矩阵 存储表示

#define MaxInt 32767     //表示极大值,即 ∞ 
#define MVNum 100        //最大顶点数 
typedef int VerTexType; //设顶点的数据类型为字符型 
typedef int ArcType;     //假设边的权值类型为整型 

typedef struct{
	VerTexType vexs[MVNum];      //顶点表 
	ArcType arcs[MVNum][MVNum];  //邻接矩阵
	int vexnum,arcnum;           //图的当前点数和边数 
}AMGraph; 

🏳️‍🌈采用邻接矩阵表示法创建无向  网

🎈算法步骤

1.输入总顶点数和总边数

2.依次输入点的信息并将其存入顶点表中

3.初始化邻接矩阵,每个权值初始化为最大值

4.构造邻接矩阵,依次输入每条边依附的顶点以及其权值,确定两个顶点在图中的位置之后,使相应边赋予相应的权值,同时使其对称边赋予相同的权值

🎈算法描述

int located(AMGraph &G, VerTexType v)
{
    for (int i = 0; i < G.vexnum; i++) {
        if (G.vexs[i] == v) {
            return i;
        }
    }
    return -1; // 未找到,返回 -1
}


int Create(AMGraph &G)
{
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++)
	{
		cin>>G.vexs[i];
	}
	for(i=0;i<G.vexnum;i++)
	{
		for(j=0;j<G.vexnum;j++)
		{
			G.arcs[i][j]=MaxInt;
		}
	}
	for(int k=0;k<G.arcnum;k++)
	{
		cin>>v1>>v2>>w;
		i=located(G,v1);
		j=located(G,v2);
		G.arcs[i][j]=w;
		G.arcs[j][i]=G.arcs[i][j];
	}
	return 1;
}

 🏳️‍🌈采用邻接矩阵表示法创建无向  网

进行两处改动即可

1.初始化邻接矩阵时,把边的权值初始化为0

2.构造邻接矩阵时,把权值w修改为1即可

🎁图的遍历

图的遍历也是从图的某一顶点出发,按照某种方法对图的所有顶点进行访问且访问一次

实质:找每个节点的邻接点

 🏳️‍🌈深度优先遍历

深度优先搜索(DepthFirst Search, DFS)遍历类似于树的先序遍历,是树的先序遍历的推广。

🎈算法步骤

(1)从图中某个顶点v出发, 访问v。
(2)找出刚访问过的顶点的第 个未被访问的邻接点, 访问该顶点。 以该顶点为新顶点,重
复此步骤, 直至刚访问过的顶点没有未被访问的邻接点为止。
(3)返回前 个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的
邻接点, 访问该顶点。
(4)重复步骤 (2) 和(3), 直至图中所有顶点都被访问过,搜索结束

 

🎈算法描述

void DFS(AMGraph G, int v)
{
    printf("%d ", G.vexs[v]);     // 访问顶点 v
    visited[v] = true;            // 标记为已访问
    for (int w = 0; w < G.vexnum; w++)
    {
        if (G.arcs[v][w] != MaxInt && !visited[w])
        {
            DFS(G, w);   // 对未访问的邻接顶点递归调用DFS
        }
    }
}

🎁广度优先遍历

🎈算法步骤

(1) 从图中某个顶点v出发,访问v。
(2)依次访问v的各个未曾访问过的邻接点。
(3)分别从这些邻接点出发依次访问它们的邻接点, 并使 先被访问的顶点的邻接点 先于”后被访问的顶点的邻接点” 被访问。重复步骤(3), 直至图中所有已被访问的顶点的邻接点都被
访间到

 

🎈算法描述

void BFS(AMGraph G, int v)
{
    int front = 0, rear = 0;
    int queue[MVNum];     // 定义队列
    printf("%d ", G.vexs[v]);
    visited[v] = true;
    queue[rear++] = v;    // 将顶点 v 入队
    while (front != rear)
    {
        int k = queue[front++];   // 出队一个顶点 k
        for (int w = 0; w < G.vexnum; w++)
        {
            if (G.arcs[k][w] != MaxInt && !visited[w])
            {
                printf("%d ", G.vexs[w]);     // 访问顶点 w
                visited[w] = true;
                queue[rear++] = w;           // 将顶点 w 入队
            }
        }
    }
}

🎁附加 

🏳️‍🌈实验题目

1.使用邻接矩阵的方式存储上边无向图;

2.以矩阵的形式输出无向图

3.在邻接矩阵的基础上实现深度优先遍历和广度优先遍历。

🏳️‍🌈代码

/*
6 6
1 2 3 4 5 6
1 2 1
2 5 1
5 3 1
3 1 1
1 4 1
4 6 1
*/

#include<iostream>
using namespace std;

#define MaxInt 32767     //表示极大值,即 ∞ 
#define MVNum 100        //最大顶点数 
typedef int VerTexType; //设顶点的数据类型为字符型 
typedef int ArcType;     //假设边的权值类型为整型 

typedef struct{
	VerTexType vexs[MVNum];      //顶点表 
	ArcType arcs[MVNum][MVNum];  //邻接矩阵
	int vexnum,arcnum;           //图的当前点数和边数 
}AMGraph; //Adjacency Matrix Graph 

int v1,v2,i,j,k,w;

int located(AMGraph &G, VerTexType v)
{
    for (int i = 0; i < G.vexnum; i++) {
        if (G.vexs[i] == v) {
            return i;
        }
    }
    return -1; // 未找到,返回 -1
}


int Create(AMGraph &G)
{
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++)
	{
		cin>>G.vexs[i];
	}
	for(i=0;i<G.vexnum;i++)
	{
		for(j=0;j<G.vexnum;j++)
		{
			G.arcs[i][j]=MaxInt;
		}
	} 
	for(int k=0;k<G.arcnum;k++)
	{
		cin>>v1>>v2>>w;
		i=located(G,v1);
		j=located(G,v2);
		G.arcs[i][j]=w;
		G.arcs[j][i]=G.arcs[i][j];
	}
	return 1;
}

bool visited[MVNum];

// 深度优先遍历
void DFS(AMGraph G, int v)
{
    printf("%d ", G.vexs[v]);     // 访问顶点 v
    visited[v] = true;            // 标记为已访问
    for (int w = 0; w < G.vexnum; w++)
    {
        if (G.arcs[v][w] != MaxInt && !visited[w])
        {
            DFS(G, w);   // 对未访问的邻接顶点递归调用DFS
        }
    }
}

// 广度优先遍历
void BFS(AMGraph G, int v)
{
    int front = 0, rear = 0;
    int queue[MVNum];     // 定义队列
    printf("%d ", G.vexs[v]);
    visited[v] = true;
    queue[rear++] = v;    // 将顶点 v 入队
    while (front != rear)
    {
        int k = queue[front++];   // 出队一个顶点 k
        for (int w = 0; w < G.vexnum; w++)
        {
            if (G.arcs[k][w] != MaxInt && !visited[w])
            {
                printf("%d ", G.vexs[w]);     // 访问顶点 w
                visited[w] = true;
                queue[rear++] = w;           // 将顶点 w 入队
            }
        }
    }
}

int main()
{
    AMGraph G;
    Create(G);
    printf("存储成功\n");

    // 输出邻接矩阵
    for (int i = 0; i < G.vexnum; i++)
    {
        for (int j = 0; j < G.vexnum; j++)
        {
            if (G.arcs[i][j] == MaxInt)
            {
                printf("∞ ");
            }
            else
            {
                printf("%d ", G.arcs[i][j]);
            }
        }
        printf("\n");
    }

    // 初始化访问标记数组
    for (int i = 0; i < G.vexnum; i++)
    {
        visited[i] = false;
    }

    printf("深度优先遍历: ");
    for (int i = 0; i < G.vexnum; i++)
    {
        if (!visited[i])
        {
            DFS(G, i);
        }
    }
    printf("\n");

    // 重置访问标记数组
    for (int i = 0; i < G.vexnum; i++)
    {
        visited[i] = false;
    }

    printf("广度优先遍历: ");
    for (int i = 0; i < G.vexnum; i++)
    {
        if (!visited[i])
        {
            BFS(G, i);
        }
    }
    printf("\n");

    return 0;
}

🏳️‍🌈运行结果 

🥰如果大家有不明白的地方,或者文章有问题,欢迎大家在评论区讨论,指正🥰   

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

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

相关文章

安全中级2:nginx的中间件漏洞

目录 一、nginx解析php的流程 1.原理 2.CGI、FastCGI、PHP-FPM、PHP-CG、WrapperI的定义 二、Fastcgi协议 1.Fastecgi Record 2.Fastcgi Type 3.PHP-FPM(FastCGI进程管理器) 4.总结FastCGI解析的流程 三、nginx配置错误导致的漏洞 1.CRLF注入漏洞&#xff08;$uri解…

rk3568 适配rk809音频

rk3568 适配rk809音频 RK809是一款集成了多种功能的电源管理芯片&#xff0c;主要用于笔记本电脑、平板电脑、工控机等设备的电源管理。以下是RK809的详细功能介绍&#xff1a; 电源管理&#xff1a;控制电源的开关、电压、电流等参数&#xff0c;保证设备的稳定运行。音频管…

开放原子训练营(第三季)inBuilder低代码开发实验室之人人都是开发者

目录 前言: 一、知己知彼 1.1全场景 全角色 多终端 快速开发 1.2直觉化 响应式 1.3所见即所得 1.4全栈开发 二、百战百胜 2.1inBuilder开发入门 2.2点火启动&#xff0c;新的征程 三、实战表现 3.1实战总结 3.2实战效果 四、总结 前言: 2023年&#xff0c;是我们摘…

chatgpt赋能Python-python_embedded_null_character

Python中嵌入空字符的介绍 在Python编程语言中&#xff0c;空字符是一种特殊的字符&#xff0c;它在字符串中表示为空格或空行。不过&#xff0c;在某些情况下添加一个空字符是非常必要的&#xff0c;例如在编码时需要将字符串以空字符分隔&#xff0c;或者在数据库存储中需要…

CC++——深入探究动态内存管理

文章目录 总述C&C程序内存区域划分C内存管理方式运用new/delete操作内置类型new和delete操作自定义类型 operator new与operator delete函数new和delete操作符的实现原理自定义类型 malloc/free 和 new/delete 的区别 总述 俗话说&#xff0c;没有理解过底层的c&c程序员…

性能测试——服务端监控工具nmon

这里写自定义目录标题 一、性能监控工具nmon介绍二、nmon可监控的数据类型三、nmon特点四、Linux下安装1、检查安装环境2、下载nmon3、解压 五、运行nmon1、启动nmon2、常用nmon快捷命令3、nmon命令行参数4、命令行例子5、重点 六、查看 nmon 监控结果1、nmon_analyser 介绍2、…

AI:Vue2和Vue3的对比

1. 什么是Vue.js以及Vue.js在前端开发中的重要性。 Vue.js是一个遵循MVVM&#xff08;Model-View-ViewModel&#xff09;模式的前端JavaScript框架&#xff0c;它采用了双向数据绑定和组件化的思想&#xff0c;使得前端开发变得更加简洁、高效、可维护。Vue.js由中国工程师尤雨…

chatgpt赋能Python-python_dlib

Python Dlib&#xff1a;从入门到实践 Python Dlib 是一个用于人脸检测、跟踪和姿态估计的高性能C库&#xff0c;提供 Python 接口方便调用。它是一个开源项目&#xff0c;被广泛应用于计算机视觉、图像处理和机器学习等领域。本文将从介绍Dlib的原理、特点以及应用场景等方面…

Rshiny基本函数(交互式web应用)

Rshiny基础函数 引言shiny包的下载shinyApp的构成ui的设计函数HTML类比img函数无法加载图片控件函数ui设计的输出对象 server总结 引言 R语言shiny包可以帮助我们轻松的制作交互式的web应用&#xff0c;并且可以搭建为独立的桌面可执行程序&#xff0c;非常方便制作和分享&…

人工智能(柴玉梅)第四章课后部分习题答案(仅供参考)

注释部分只是复习用&#xff0c;不是答案 第五题 注释&#xff1a;便于复习 本来想搜个类似的&#xff0c;结果发现r1这种人家都带括号&#xff01;&#xff01;&#xff01;额&#xff0c;没括号那我就从前往后算了&#xff0c;按顺序算准没错~ CF&#xff08;H&#xff09;的…

Python logging使用

目录 logging模块 logging核心组件 logger handler StreamHandler&#xff1a;把日志内容在控制台中输出 FileHandler&#xff1a;把日志内容写入到文件中 filter formatter 注意日志级别的继承问题 logger.exception 上述样例的整体代码 日志的配置文件及其模板 lo…

用Python爬取了三大相亲软件评论区,结果…

小三&#xff1a;怎么了小二&#xff1f;一副愁眉苦脸的样子。 小二&#xff1a;唉&#xff01;这不是快过年了吗&#xff0c;家里又催相亲了 ... 小三&#xff1a;现在不是流行网恋吗&#xff0c;你可以试试相亲软件呀。 小二&#xff1a;这玩意靠谱吗&#xff1f; 小三&#…

使用Gradle7.6.1 + SpringBoot3.0.2 + java17创建微服务项目(学习)

这是一个大胆的决定 这里是导航 技术栈开发工具一、创建gradle父子项目&#xff08;deity&#xff09;1.0 简单流程示意1.1、IDEA中主要图示1.1.1 项目结构图1.1.2 IDEA中 Gradle配置 1.2、deity父项目build.gradle文件1.3、deity父项目settings.gradle文件1.4、子项目build.g…

计算机底层知识

汇编语言&#xff08;机器语言&#xff09;的执行过程 汇编语言的本质&#xff1a;机器语言的助记符 其实他就是机器语言 计算机通电->CPU读取内存中程序&#xff08;电信号输入&#xff09; ->时钟发生器不断震荡通电 ->推动CPU内部一步一步执行&#xff08;执行多…

elementUI,自定义表头,多层级表头,表头合并,行内容一致的合并行

先上效果&#xff1a; 1.自定义表头&#xff1a; 通过设置 slot"header" 来自定义表头。 slot-scope"scope" 这一行千万不要因为没有再template中使用到scope&#xff0c;vscode报红而删除&#xff0c;这会导致input框不能输入任何内容&#xff01; &l…

软考网工计算题总结(一):总共27类题型,进来复习啦!

题型一&#xff1a; 1.地址编号从80000H到BFFFFH且按字节编址的内存容量为&#xff08;5&#xff09;KB,若用16KX4bit的存储芯片够成该内存&#xff0c;共需&#xff08;6&#xff09;片。 (5)A.128 B.256 C.512 D.1024 (6)A.8 B.16 C.32 D.64 【答案】B C 【解析】本题…

写一个自己的MyGPT app

chatGPT大火之后&#xff0c;国内外一众玩家撸起袖子热火朝天干了起来。 借助开源的GPT可以轻松的拥有自己的专属GPT&#xff0c;装装逼还是很好用的&#xff0c;也算赶一下chatGPT的风口。 这里使用ANYGPT&#xff0c;打造自已的GPT&#xff0c;AnyGPT API 开发者文档 语雀…

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出 概述窗口看门狗 (WWDG)WWDG_SR 状态寄存器WWDG 配置与使用使用 WWDG 进行故障检测案例 概述 在嵌入式开发中, 可靠性和稳定性是至关重要的. 这就是为什么许多单片机, 比如 STM32, 提供了窗口看门狗 (Window Watchdog, WW…

redis 源码记录

正好最近时间富裕&#xff0c;看一看redis源码&#xff0c;简单的记录一下。也有可能说的是不全面的&#xff0c;自行斟酌&#xff0c;只能通过debug来简单的梳理本次测试流程&#xff0c;而不是全量的覆盖的所有测试用例&#xff0c;时不时更新&#xff0c;争取一天学一点点。…

基于Web的水果蔬菜销售系统的设计与实现(论文+源码)_kaic

摘 要 随着互联网经济与技术进程的不断推进&#xff0c;网上购物方式受到公众的普遍关注和欢迎。传统的樱桃线下销售模式缺陷不断暴露&#xff0c;难以满足公众不断加快的生活节奏和生活方式的需求。本文根据目前大众的实际需要&#xff0c;根据网上商城的特点、现状以及主要功…