PYTHON用[邻接列表]及[邻接矩阵]来存储无向图

# 图可以根据边的性质进行分类:
# 有向图(Directed Graph):在有向图中,边是有方向性的,从一个节点指向另一个节点。这意味着从节点 A 到节点 B 的边与从节点 B 到节点 A 的边可以是不同的,或者根本不存在。有向图通常用于表示具有方向性的关系,例如网页链接、社交关系中的关注关系等。
# 无向图(Undirected Graph):在无向图中,边是没有方向性的,即连接两个节点的边没有箭头指示方向。这意味着节点 A 与节点 B 之间的关系是对称的,从 A 到 B 的边与从 B 到 A 的边是相同的。无向图通常用于表示无方向性的关系,例如交通网络、好友关系等。
# 权重图(Weighted Graph):在权重图中,每条边都有一个与之关联的权重或值。这些权重可以表示连接两个节点的成本、距离、容量等信息。权重图通常用于模拟具有不同代价或度量的关系,例如路线规划中的道路长度、社交网络中的强度等。
# 无权图(Unweighted Graph):与权重图相反,无权图中的边没有相关的权重信息。它们只表示节点之间的连接关系,而不考虑连接的强度或成本。
# 这些不同类型的图可以根据问题的需求进行选择和应用,以更好地描述和解决特定领域的问题。

-------

当我们考虑一个简单的社交网络,其中有几个人以及它们之间的友谊关系时,我们可以使用无向图来表示这种关系。

假设我们有以下人物:

- Alice
- Bob
- Charlie
- David

他们之间的友谊关系如下:

- Alice 和 Bob 是朋友。
- Bob 和 Charlie 是朋友。
- Charlie 和 David 是朋友。

用无向图表示这个社交网络,节点代表人,边代表友谊关系。

这个无向图可以用以下方式表示:

节点集合 V = {Alice, Bob, Charlie, David}

边集合 E = {{Alice, Bob}, {Bob, Charlie}, {Charlie, David}}

这里的每一对节点都表示一个边,例如 {Alice, Bob} 表示 Alice 和 Bob 之间存在一条友谊边,而 {Bob, Charlie} 表示 Bob 和 Charlie 之间也存在一条友谊边。这些边都是无向的,因此没有方向性。

class UndirectedGraph:
    def __init__(self):
        self.adjacency_list = {}

    def add_vertex(self, vertex):
        if vertex not in self.adjacency_list:
            self.adjacency_list[vertex] = []

    def add_edge(self, vertex1, vertex2):
        if vertex1 in self.adjacency_list and vertex2 in self.adjacency_list:
            self.adjacency_list[vertex1].append(vertex2)
            self.adjacency_list[vertex2].append(vertex1)  # 更新顶点 vertex2 的邻接列表
        else:
  
            print("One or both vertices do not exist.")

# 在你提供的代码中,add_edge() 方法用于向图中添加一条边。让我解释一下这段代码的作用:
# if vertex1 in self.adjacency_list and vertex2 in self.adjacency_list::这个条件检查 vertex1 和 vertex2 是否都存在于图的顶点列表中。只有当两个顶点都存在时,才执行接下来的操作。
# self.adjacency_list[vertex1].append(vertex2):这一行将 vertex2 添加到 vertex1 的邻接列表中,表示顶点 vertex1 与顶点 vertex2 之间有一条边。
# self.adjacency_list[vertex2].append(vertex1):这一行实际上是为了保证无向图的连通性,将 vertex1 添加到 vertex2 的邻接列表中,表示顶点 vertex2 与顶点 vertex1 之间也有一条边。这样做是因为无向图的边是双向的,如果有从 vertex1 到 vertex2 的边,也就意味着有从 vertex2 到 vertex1 的边。
# 通过这种方式,add_edge() 方法确保了图是无向图,即添加边的操作同时更新了两个顶点的邻接列表,使得图中的边是双向的。


    def display_graph(self):
        print("Adjacency List:")
        for vertex, neighbors in self.adjacency_list.items():
            print(f"{vertex}: {neighbors}")
        print("\nGraph:")
        for vertex in self.adjacency_list:
            print(vertex, end=" -> ")
            print(" -> ".join(self.adjacency_list[vertex]))


# 这段代码是用来打印图的边的。让我解释一下:
# for vertex in self.adjacency_list::这个循环遍历图中的每个顶点,vertex 变量在每次迭代中都代表一个顶点名称。
# print(vertex, end=" -> "):这一行打印当前顶点的名称,然后用箭头符号 "->" 结束输出,使得下一个顶点的名称在同一行显示。
# print(" -> ".join(self.adjacency_list[vertex])):这一行使用 join() 方法将当前顶点的邻接列表连接成一个字符串,并使用箭头符号 "->" 将它们分隔开。然后,将连接后的字符串打印出来,显示当前顶点与其相邻顶点之间的连接关系。
# 所以,这段代码实际上是在打印图的邻接表,以边的形式显示图的结构。
# string.join(iterable)是一个字符串方法,用于将可迭代对象中的元素连接成一个字符串;
# string 是用来连接元素的字符串,而 iterable 则是要连接的可迭代对象,通常是列表或元组


# 创建一个无向图对象
graph = UndirectedGraph()

# 添加顶点
graph.add_vertex("Alice")
graph.add_vertex("Bob")
graph.add_vertex("Charlie")
graph.add_vertex("David")

# 添加边 /输出的顺序与添加边的顺序有关。
graph.add_edge("Alice", "Bob")
graph.add_edge("Bob", "Charlie")
graph.add_edge("Charlie", "David")

# 显示图
graph.display_graph()


# 图可以根据边的性质进行分类:
# 有向图(Directed Graph):在有向图中,边是有方向性的,从一个节点指向另一个节点。这意味着从节点 A 到节点 B 的边与从节点 B 到节点 A 的边可以是不同的,或者根本不存在。有向图通常用于表示具有方向性的关系,例如网页链接、社交关系中的关注关系等。
# 无向图(Undirected Graph):在无向图中,边是没有方向性的,即连接两个节点的边没有箭头指示方向。这意味着节点 A 与节点 B 之间的关系是对称的,从 A 到 B 的边与从 B 到 A 的边是相同的。无向图通常用于表示无方向性的关系,例如交通网络、好友关系等。
# 权重图(Weighted Graph):在权重图中,每条边都有一个与之关联的权重或值。这些权重可以表示连接两个节点的成本、距离、容量等信息。权重图通常用于模拟具有不同代价或度量的关系,例如路线规划中的道路长度、社交网络中的强度等。
# 无权图(Unweighted Graph):与权重图相反,无权图中的边没有相关的权重信息。它们只表示节点之间的连接关系,而不考虑连接的强度或成本。
# 这些不同类型的图可以根据问题的需求进行选择和应用,以更好地描述和解决特定领域的问题。

Adjacency List:
Alice: ['Bob']
Bob: ['Alice', 'Charlie']
Charlie: ['Bob', 'David']
David: ['Charlie']

Graph:
Alice -> Bob
Bob -> Alice -> Charlie
Charlie -> Bob -> David
David -> Charlie
[Finished in 603ms]

无向图可以使用多种方式来进行存储,其中两种最常见的方式是邻接列表和邻接矩阵。

1. **邻接列表(Adjacency List)**:
   邻接列表是一种将图中每个节点的邻居节点列表存储起来的方式。对于每个节点,将其邻居节点以列表、链表或其他数据结构的形式存储在该节点的条目中。这种方式可以有效地节省空间,尤其适用于稀疏图,即节点之间的边相对较少的情况。Python 中可以使用字典或哈希表来实现邻接列表。

2. **邻接矩阵(Adjacency Matrix)**:
   邻接矩阵是一个二维数组,其中行和列分别代表图中的节点,矩阵的元素表示节点之间是否存在边。如果节点 i 和节点 j 之间存在边,则矩阵的第 i 行和第 j 列的元素为 1;否则为 0。这种方式相对于邻接列表来说更加直观,但是在图比较稀疏的情况下会浪费大量的空间。

在前面的代码示例中,我使用了邻接列表来存储无向图。每个节点都有一个列表,其中存储了与该节点相邻的其他节点。

----------

邻接矩阵是一种常见的图的表示方法,尤其适用于稠密图,因为它提供了直观的方式来表示节点之间的连接关系。下面是如何使用邻接矩阵来表示你提供的社交网络:

在这个邻接矩阵中,每一行和每一列分别代表一个节点,而矩阵中的值表示节点之间是否存在边。例如,第一行表示 Alice 与其他节点的连接关系,其中 1 表示 Alice 与 Bob 相连,而其他值为 0 表示 Alice 与 Charlie 和 David 不相连。

这种表示方式虽然直观易懂,但在图比较稀疏的情况下会占用大量的空间,因为矩阵的大小与节点数量的平方成正比。相对而言,邻接列表在这种情况下可能更为高效,因为它只需要存储实际存在的边。

class SocialNetwork:
    def __init__(self, num_nodes):
        self.num_nodes = num_nodes
        self.adj_matrix = [[0] * num_nodes for _ in range(num_nodes)]
# 这段代码在 SocialNetwork 类的构造函数中初始化了社交网络的属性:
# self.num_nodes = num_nodes: 这一行将社交网络的节点数量设置为传入的参数 num_nodes。这样,我们就可以知道社交网络有多少个节点。
# self.adj_matrix = [[0] * num_nodes for _ in range(num_nodes)]: 这一行创建了一个大小为 num_nodes × num_nodes 的二维列表(即矩阵),并将其用于表示社交网络的邻接矩阵。初始时,所有的边都被设置为 0,表示没有边相连。
# 通过这两行代码,我们在创建 SocialNetwork 对象时就初始化了社交网络的基本结构,为后续添加边和展示邻接矩阵做好了准备。
    def add_edge(self, node1, node2):
        if node1 < self.num_nodes and node2 < self.num_nodes:
            self.adj_matrix[node1][node2] = 1
            self.adj_matrix[node2][node1] = 1
        else:
            print("Invalid node index.")

# 这段代码是用来在邻接矩阵中添加边的方法。让我解释一下它的工作原理:
# 首先,检查给定的节点索引 node1 和 node2 是否有效,即它们是否在社交网络的节点范围内。
# 如果节点索引有效,则将邻接矩阵中索引为 (node1, node2) 和 (node2, node1) 的位置的值设为 1,表示节点 node1 和 node2 之间存在一条边。
# 这里之所以要同时设置 (node1, node2) 和 (node2, node1) 的值是因为这是一个无向图,边不区分方向,所以节点 node1 和 node2 之间的连接关系是相互的。
# 这样,当我们调用add_edge(0, 1)时,会将邻接矩阵中的 (0, 1) 和 (1, 0) 的位置的值都设为 1,表示 Alice 和 Bob 之间存在一条边。

    def display_adj_matrix(self):
        for row in self.adj_matrix:
            print(" ".join(map(str, row)))


# 创建一个包含4个节点的社交网络
social_network = SocialNetwork(4)

# 添加边
social_network.add_edge(0, 1)  # Alice 和 Bob 是朋友
social_network.add_edge(1, 2)  # Bob 和 Charlie 是朋友
social_network.add_edge(2, 3)  # Charlie 和 David 是朋友

# 显示邻接矩阵
print("邻接矩阵表示的社交网络:")
social_network.display_adj_matrix()


# [[0] * num_nodes for _ in range(num_nodes)]
# 这行代码是一个列表推导式,用于创建一个二维列表(矩阵),其维度为 num_nodes × num_nodes。让我解释一下它的工作原理:

# [[0] * num_nodes for _ in range(num_nodes)]: 这一整个表达式是一个嵌套的列表推导式。外层的 for _ in range(num_nodes) 循环了 num_nodes 次,每次都会生成一个包含 num_nodes 个 0 的列表。这样就生成了一个 num_nodes × num_nodes 的二维列表,其中每个元素都是 0。

# 总的来说,这段代码的作用是创建一个大小为 num_nodes × num_nodes 的二维列表,并将其初始化为全 0,用于表示社交网络的邻接矩阵。

 邻接矩阵表示的社交网络:
0 1 0 0
1 0 1 0
0 1 0 1
0 0 1 0
[Finished in 563ms]

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

58岁第一代「晶女郎」激罕现身

90年代性感女神关秀媚在2006年拍完内地剧集《暴雨梨花》后更全面息影&#xff0c;而且更甚少现身于人前。日前曾志伟庆祝71岁生日&#xff0c;举行盛大慈善素宴广邀圈中好友&#xff0c;为寺庙重建工程筹募经费。女神关秀媚便罕有接受访问透露近况。 当天关秀媚将头发盘起&…

【大数据】LSM树,专为海量数据读写而生的数据结构

目录 1.什么是LSM树&#xff1f; 2.LSM树的落地实现 1.什么是LSM树&#xff1f; LSM树&#xff08;Log-Structured Merge Tree&#xff09;是一种专门针对大量写操作做了优化的数据存储结构&#xff0c;尤其适用于现代大规模数据处理系统&#xff0c;如NoSQL数据库&#xff…

【Java--数据结构】“从扑克到程序:深入探讨洗牌算法的原理与魅力“

前言 以下是学习Java顺序表的一个实例应用———简单的洗牌算法。 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 定义每张扑克牌的属性 生成一副扑克牌&#xff08;不包含大小王&#xff09; 洗牌方法 发牌方…

AI视频下载:零基础2小时学会开发 Chrome扩展程序

无论您是有抱负的Web开发人员、AI爱好者还是生产力黑客&#xff0c;本课程都提供了宝贵的见解和实践经验&#xff0c;帮助您利用AI和Chrome扩展的力量来简化Web自动化&#xff0c;改善各个行业和领域的用户体验&#xff0c;解锁AI驱动生产力的潜力&#xff01; 此课程面向以下…

如何计算加速开发的实际价值

投资回报率&#xff08;ROI&#xff09;已成为在企业中引进工具、方法或者策略时必须考虑的关键指标。 尽管如此&#xff0c;在某些情况下&#xff0c;ROI 很容易衡量&#xff0c;而在其他情况下&#xff0c;则往往只衡量结果——金钱。这种评估角度是有效且必要的&#xff0c…

K-means聚类算法:如何在杂乱无章的数据中找出规律?

什么是K-means聚类算法&#xff1f; 在编程的世界里&#xff0c;K-means聚类算法就像一位无私的指路人&#xff0c;它不需要我们给出明确的指示&#xff0c;只需要我们提供数据&#xff0c;它就能帮助我们找到数据的归属&#xff0c;找到数据的“家”。 K-means聚类算法的名字…

石化盈科PMO总经理任志婷受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 石化盈科信息技术有限责任公司运营管理部总经理兼PMO总经理任志婷女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“组织级项目管理的初心和使命——打造卓越的IT企业PMO”。大会将于5月25-26日在北京举办&#xff0c;…

碳课堂|什么是碳市场?如何进行碳交易?

近年来&#xff0c;随着全球变暖问题日益受到重视&#xff0c;碳达峰、碳中和成为国际社会共识&#xff0c;为更好地减缓和适应气候变化&#xff0c;同时降低碳关税风险&#xff0c;以“二氧化碳的排放权利”为商品的碳交易和碳市场应时而生。 一、什么是碳交易、碳市场 各国…

BootStrap框架学习

1、BootStrap是一套现成的css样式集合 中文文档&#xff1a;www.bootcss.com 响应式布局&#xff1a;pc端&#xff0c;手机端都可适配 特点&#xff1a;集成了html,css,javascript工具集&#xff0c;12列格网&#xff0c;基于jquery&#xff0c; 下载&#xff1a;http://v3…

【大语言模型LLM】- Meta开源推出的新一代大语言模型 Llama 3

&#x1f525;博客主页&#xff1a;西瓜WiFi &#x1f3a5;系列专栏&#xff1a;《大语言模型》 很多非常有趣的模型&#xff0c;值得收藏&#xff0c;满足大家的收集癖&#xff01; 如果觉得有用&#xff0c;请三连&#x1f44d;⭐❤️&#xff0c;谢谢&#xff01; 长期不…

在 Slurm 上运行 Jupyter

1. 背景介绍 现在的大模型训练越来越深入每个组了&#xff0c;大规模集群系统也应用的愈发广泛。一般的slurm系统提交作业分为2种&#xff0c;一种是srun&#xff0c;这种所见即所得的申请方式一般适用于短期的调试使用&#xff0c;大概一般允许的时间从几个小时到1天左右&…

使用 FFMPEG 实现录屏和录音

FFmpeg 是一个非常强大的开源工具&#xff0c;它可以用来处理音频和视频。 要使用 FFmpeg 进行录屏和录音&#xff0c;需要首先确保你的系统已经安装了 FFmpeg。在大多数 Linux 发行版中&#xff0c;可以通过包管理器&#xff08;如 apt 或 yum&#xff09;来安装。在 Windows …

Linux复习提纲2

Linux复习提纲 Linux概述 shell&#xff1a;交互式命令解释程序&#xff1b;用户和内核间交互的桥梁Shell不仅是交互式命令解释程序&#xff0c;还是一种程序设计语言shell是一种命令解释程序&#xff0c;批处理shell是linux的外壳&#xff0c;默认是bash2.1 Linux基础概念 log…

2024深圳杯(东三省)数学建模挑战赛D题:音板的振动模态分析与参数识别思路代码成品论文分析

​ 更新完整代码和成品完整论文 《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓ https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 问题重述 深圳杯&#xff08;东三省&#xff09;数学建模挑战赛2024D题&#xff1a;音板的振动模态分析与…

【iOS开发】(五)react Native路由和导航20240421-22

【iOS开发】(五)react Native 路由和导航Navigation 20240421 在&#xff08;一&#xff09;&#xff08;二&#xff09;中我们 Reactnative搭建了开发环境、学习了 基础语法、状态管理&#xff0c;JSX、组件、状态和生命周期以及样式布局等。 在&#xff08;三&#xff09;&a…

2024 OceanBase 开发者大会:OceanBase 4.3正式发布,打造PB级实时分析数据库

4月20日&#xff0c;2024 OceanBase开发者大会盛大召开&#xff0c;吸引了50余位业界知名的数据库专家和爱好者&#xff0c;以及来自全国各地的近600名开发者齐聚一堂。他们围绕一体化、多模、TP与AP融合等前沿技术趋势展开深入讨论&#xff0c;分享场景探索的经验和最佳实践&a…

STM32H750外设ADC之动态低功耗特性

目录 概述 1 模式实现&#xff08;AUTDLY&#xff09; 2 自动注入模式 (JAUTO1) 3 AUTDLY 模式 4 实现案例 概述 本文主要介绍STM32H750外设ADC之动态低功耗特性相关的内容。包括&#xff1a;模式实现&#xff08;AUTDLY&#xff09;、自动注入模式 (JAUTO1)、 AUTDLY 模…

【1646】医院人员管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

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

力扣经典150题(3)

文章目录 17.电话号码的字母组合77.组合46.全排列74.搜索二维矩阵215.数组中的第K个最大元素 17.电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相…

金融风控信用评分卡建模(Kaggle give me credit数据集)

1 数据预处理数据 数据来源于Kaggle的Give Me Some Credit&#xff0c;包括25万条个人财务情况的样本数据 1.1 导包读数据 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import RandomForestRegressor import seaborn as …