各种树型结构模型分析与比较

假设我们正在设计一个带有评论的 Bug 记录网站(很像 http://stackoverflow.com/ ),网站的读者可以评论原文甚至可以相互之间回复,因此针对某一主题的讨论可能会延伸出很多分支。刚开始,我们可能会选择一个简单的方案:

CREATE TABLE Comments(
  comment_id SERIAL PRIMARY KEY,
  parent_id BIGNIT UNSIGNED,
  comment TEXT NOT NULL,
  FOREIGN KEY (parent_id) REFERENCES Comments(comment_id)
)

这个方案中的每一条评论都可能都是另一个评论的子孙评论。因此要想使用一条简单的 SQL 语句去查询出一个很长的回复分支是困难的,因为帖子可能的深度是无限深的。

另一种想法是,一次性获取出这一主题的所有评论贴,然后再在应用中通过代码把它整合成传统的树型结构。但是我们的网站每天会发布几十篇文章,每篇文章可能会有数千条评论,因此如果每一次有人访问我们的网站都需要重新整合一次评论,这是不切实际的。

1 分层存储与查询

像树一样层级组织的、存在递归关系的数据在应用系统中很常见。在这样的结构中,每一个实例称为节点。每个节点有多个子节点和一个父节点。最上层的节点称为根节点,它没有父节点。最底层的节点称为叶节点,它没有子节点。所有的中间节点称为非叶节点

我们需要查询树型结构中与整棵树或者其子树相关的特定对象,树型结构的典型示例是:

  • 组织架构:比如一个公司有多个部门,每个部门有多名员工。
  • 评论链:比如某一主题有多个评论,每个评论有多个回复。

2 邻接表模型

最常见的解决方案就是在评论表中添加一个 parent_id 字段,关联同一张表中的其他评论:

假设的范例数据:

comment_idparent_idauthorcomment
1NULLFran为什么会发生这个 Bug ?
21Ollie我觉得是因为空指针
32Fran不是,我跟踪过了
41Kukla我觉得是因为无效输入
54Ollie是这个问题
64Fran确认下吧
76Kukla解决了

2.1 查询

这个模型的问题是,它无法查询出一个节点的所有后代。

可以使用关联查询来获取一条评论和它的直接后代:

SELECT c1.*, c2.*
FROM comments c1 LEFT OUTER comments c2
ON c2.parent_id = c1.comment_id
WHERE c1.comment_id = 1;

上面这个查询只能获取两层的数据。而实际情况下,可能需要查询任意深度的数据,比如需要计算一个评论分支的评论数。在邻接表模型中,每增加一层,都需要一个额外的联结,而这在数据库中是有上限的。因此既不优雅又不实用,比如以下获取四层数据的 SQL 语句:

 SELECTc1.* , c2.* , c3.* , c4.*FROMcommentsc1-- 第一层 LEFTOUTERcommentsc2-- 第二层 ONc2.parent_id=c1.comment_idLEFTOUTERcommentsc3-- 第三层 ONc3.parent_id=c2.comment_idLEFTOUTERcommentsc4-- 第四层 ONc4.parent_id=c3.comment_idWHEREc1.comment_id=1; 

这样的查询很笨,因为没增加一层,都必须同等增加联结的表,这使得执行聚集函数(比如 COUNT() )变得很困难。

另一种方法是,先查询出所有的行,然后在应用程序中自顶向下地构造出这棵树:

SELECT * FROM comments WHERE bug_id = 1;

这种方法非常低效,因为大部分的查询可能只需要一棵子树或者只需要一些聚合信息而已。

2.2 维护

邻接表模型在某些操作上很方便,比如增加一个叶子节点:

INSERT INTO comments (bug_id, parent_id, author, comment)
VALUES (1, 7, 'Deniro', '多谢!');

还比如修改一个节点的位置,或者一棵子树的位置也很简单:

UPDATE comments SET parent_id = 3 WHERE comment_id = 6;

但是,删除一棵子树很复杂,因为必须多次查询来找到所有的后代节点,然后在从低级别处开始删除以满足之前定义的外键约束性:

SELECT comment_id FROM comments WHERE parent_id = 4;//5,6
SELECT comment_id FROM comments WHERE parent_id = 5;//没有
SELECT comment_id FROM comments WHERE parent_id = 6;//7
SELECT comment_id FROM comments WHERE parent_id = 7;//没有

DELETE FROM comments WHERE comment_id IN(7);
DELETE FROM comments WHERE comment_id IN(5,6);
DELETE FROM comments WHERE comment_id IN(4);

可以配置一个级联删除特性的外键约束来自动完成上面的操作。注意,这些节点是被删除而不只是被改动位置。

如果要删除一个非叶子节点的同时,提升它的子节点,或者将它的子节点移动到另一个子节点的情况,都必须先修改子节点的 parent_id,然后才能删除原来的非叶子节点。

SELECT parent_id FROM comments WHERE comment_id = 6;//4,获取当前节点的父节点 ID
UPDATE comments SET parent_id = 4 WHERE parent_id = 6;//把当前节点的子节点关联到父节点
DELETE FROM comments WHERE comment_id = 6;//删除当前节点

这些都必须写很多代码,分多步完成。

2.3 合理使用邻接表模型

邻接表模型的优势在于能够快速获取一个给定节点的父节点,而且可以很容易插入新节点。如果这就是系统对于分层结构的全部操作,那么邻接表模型可以很好地工作。

有些数据库系统(SQL Server 2005、Oracle、DB2、PostgreSQL)可以直接进行递归查询,这使得邻接表模型可以变得更加好用。

可惜的是,MySQL、SQLite、Infomix 不支持直接的递归查询。

3 路径枚举模型

路径枚举是一个由连续的直接层级关系组成的完整路径。

我们在 Comments 表中,使用 path 字段来存储当前节点的最顶层祖先到它自己的路径序列,使用 “/” 作为路径的分隔符。

comment_idpathauthorcomment
11/Fran为什么会发生这个 Bug ?
21/2/Ollie我觉得是因为空指针
31/2/3/Fran不是,我跟踪过了
41/4/Kukla我觉得是因为无效输入
51/4/5/Ollie是这个问题
61/4/6/Fran确认下吧
71/4/6/7/Kukla解决了

3.1 查询

可以通过比较每个节点的路径来查找一个节点的祖先,比如这里要查找 comment_id 为 7 的所有祖先:

SELECT * 
FROM comments AS c
WHERE '1/4/6/7/' LIKE concat(c.path,'%');

上面这条查询语句会匹配到路径 1/4/6/%、1/4/% 以及 1/% 的节点。

查询一个节点的所有后代,比如查找comment_id 为 4 的所有后代:

SELECT *
FROM comments AS c
WHERE c.path LIKE '1/4/%'

一旦我们可以很简单地获取一个节点的所有祖先或者一个节点的所有后代信息,就可以很容易实现聚合操作,比如计算 comment_id 为 4 的评论 扩展出的所有子评论中,每个用户的评论数量:

SELECT COUNT(*)
FROM comments AS c
WHERE c.path LIKE '1/4/%'
GROUP BY c.author;

3.2 维护

插入新节点(这里的 ID 假设是自动生成的,所以需要先插入再更新):

INSERT INTO comments (author, comment) VALUES('deniro','excellent!');

UPDATE comments SET path = CONCAT((SELECT path FROM comments WHERE comment_id = 7),LAST_INSERT_ID(),'/')
WHERE comment_id = LAST_INSERT_ID();

LAST_INSERT_ID() 会返回当前会话中最新插入记录的 ID 值,注意在多线程下,不适用

3.3 优缺点

缺点:

  • 数据库无法确保路径的格式永远正确,也无法保证路径中的节点一定存在,只能由应用程序来验证。
  • 使用 LIKE 查询一个节点的所有祖先或者所有孩子的开销可能会很大。
  • 存在字段的长度限制,无法支持树型结构的无限扩展。

优点:通过比较路径字符串的长度,就可以知道对应层级的深浅。

4 嵌套集模型

嵌套集模型使用 nsleft 和 nsright 来存储子孙节点信息。

  • nsleft 的数值小于该节点所有后代的 ID。
  • nsright 的数值大于该节点所有后代的 ID。

确定这两个值的方法是对树进行一次深度优先遍历:

comment_idnsleftnsrightauthorcomment
1114Fran为什么会发生这个 Bug ?
225Ollie我觉得是因为空指针
334Fran不是,我跟踪过了
4613Kukla我觉得是因为无效输入
578Ollie是这个问题
6912Fran确认下吧
71011Kukla解决了

4.1 查询

搜索哪些节点的 ID 在评论 #4 的 nsleft 与 nsright 范围内,来获取评论 #4 以及它的所有后代:

SELECT  c2.*
FROM comments AS c1 JOIN comments AS c2
ON c2.nsleft BETWEEN c1.nsleft AND c1.nsright
WHERE c1.comment_id = 6;

搜索评论 #6 的 nsleft 在哪些节点的nsleft 与 nsright 范围内,来获取评论 #6 以及它的所有祖先:

SELECT c2.*
FROM comments as c1 JOIN comments AS c2
ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright
WHERE c1.comment_id = 6;

嵌套集模型的好处就是,删除一个非叶子节点,它的后代会自动替代被删除的节点,成为其直接祖先节点的直接后代。

计算给定节点的深度,然后删除它的父节点,当再次计算深度时,它已经自动减少了一层,比如这里删除了评论 #6 前后,计算评论 #7 深度的情况:

-- 计算深度,3
SELECT c1.comment_id, COUNT(c2.comment_id) AS depth 
FROM comment AS c1 JOIN comment AS c2 -- 找出所有 c1 的祖先(包括它自己)
ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright
WHERE c1.commnet_id = 7
GROUP BY c1.comment_id;

-- 删除评论 #6
DELETE FROM comment WHERE comment_id = 6;

-- 计算深度,2
SELECT c1.comment_id, COUNT(c2.comment_id) AS depth 
FROM comment AS c1 JOIN comment AS c2 -- 找出所有 c1 的祖先(包括它自己)
ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright
WHERE c1.commnet_id = 7
GROUP BY c1.comment_id;

但是查询一个节点的直接父节点或者直接子节点,很复杂。

如果要查询一个节点的直接父节点,可以这样考虑:给定一个节点 c 的直接父节点肯定是这个节点的祖先,且这两个节点之间绝不会有任何其他的节点。因此,可以使用一个递归的外连接来查询一个节点 x, 它既是 c 的祖先,同时也是另一个节点 y 的后代,然后我们让 y=x 并继续递归查询,直到查询返回空,即不存在这样的节点,此时的 y 便是 c1 的直接父节点:

比如要查询评论 #6 的直接父亲:

SELECT parent.*
FROM comment AS c JOIN comment AS parent
ON c.nsleft BETWEEN parent.nsleft AND parent.nsright -- 就是图例中的 y
LEFT OUTER JOIN comment AS in_between  -- 就是图例中的 x
ON c.nsleft BETWEEN in_between.nsleft AND in_between.nsright
AND in_between.nsleft BETWEEN parent.nsleft AND parent.nsright
WHERE c.comment_id = 6
AND in_between.comment_id IS NULL; -- 找到的祖先与 c 之间不存在其他节点

4.2 维护

嵌套集模型在插入和移动节点的操作上,比其他模型复杂的多。插入一个新节点时,需要重新计算新插入节点的相邻兄弟节点、祖先节点和祖先节点的兄弟节点的左右值。

假设新插入的节点是一个叶子节点(插入到第 5 个节点下,左右值为8,9):

-- 重新计算受到影响的节点的左右值
UPDATE comment
SET nsleft = CASE WHEN nsleft >=8 THEN nsleft+2 ELSE nsleft END,
    nsright = nsright+2
WHERE nsright >=7;

-- 创建新节点
INSERT INTO comment (nsleft, nsright, author, comment)
VALUES (8,9,'Deniro','厉害');

如果某个应用中,如果简单快速第查询是最重要的功能,那么可以使用嵌套集。然而,在嵌套集中插入和移动节点是复杂的,因为需要重新分配左右值,因此嵌套集不适合需要频繁插入和删除节点的应用场景。

5 闭包表模型

闭包表是一个简单、优雅模型,它记录了树中所有节点的关系。

我们将树中任何具有祖先与后代关系的节点对,都存储在 TreePaths 中,同时我们也把指向节点自身的关系也存储在这张表;为了方便查询某个节点直接父节点或直接子节点,我们还增加一个 path_length 字段,自我引用的节点该值为 0,直接子节点为 1,以此类推:

祖先后代路径长度
110
121
132
141
152
162
173
220
231
330
440
451
461
472
550
560
660
671

  • 实线表示父子关系。
  • 不同颜色表示某个节点与其他节点的关系。

这样画只是为了理解方便,对于 TreePaths 表它们都是祖先与后代的关系(包括指向自己的关系)。

5.1 查询

搜索评论 #4 的所有后代:

SELECT c.*
FROM comments AS c
JOIN TreePaths AS t ON c.comment_id = t.descendant
WHERE t.ancestor = 4;

搜索评论 #6 的所有祖先:

SELECT c.*
FROM comments AS c
JOIN TreePaths AS t ON c.comment_id = t.ancestor
WHERE t.descendant = 6;

搜索评论 #4 的直接子节点:

SELECT *
FROM TreePaths
WHERE ancestor = 4 AND path_length = 1;

5.2 维护

插入新的叶子节点,比如在评论 #5 下新增一个叶子节点,假设叶子节点的 ID 为 8:

INSERT INTO TreePaths(ancestor, descedant)
SELECT t.ancestor, 8 -- 所有后代为 5 的节点,都添加关系
FROM TreePaths AS t
WHERE t.descendant = 5
UNION ALL
SELECT 8,8;-- 指向自己的关系

删除一个叶子节点,比如评论 #7:

DELETE FROM TreePaths WHERE descendant = 7;

删除一棵完全子树,比如评论 #4 和它的所有后代:

DELETE FROM TreePaths
WHERE descendant IN (
    SELECT descendant FROM TreePaths WHERE ancestor = 4
);

注意: 这里的删除只是删除关系,实际的节点并没有删除,因为我们把关系路径存储在一个独立的表中,这种灵活的设计特别适合用于员工组织架构变动的场景。


把一棵子树移动到其他地方:首先找到这棵子树的顶点,然后删除它的所有子节点与它的所有祖先节点之间的关系,比如把评论 #6 移动到评论 #3 下:

-- 删除与评论 #6 相关的所有祖先和后代的关系
DELETE FROM TreePaths
WHERE descendant IN (SELECT descendant FROM TreePaths WHERE ancestor = 6) -- 评论 #6 的所有后代(包括评论 #6 自身)
AND ancestor IN (SELECT ancestor FROM TreePaths WHERE descendant = 6); -- 评论 #6 的所有祖先

-- 把这棵子树与它的新节点以及祖先建立关系
INSERT INTO TreePaths (ancestor,descendant)
SELECT 
FROM TreePaths AS supertree
    CROSS JOIN TreePaths AS subtree
WHERE supertree.descedant = 3
AND subtree.ancestor = 6;

5 最佳实践

每种模型各有优劣,到底选择哪一种取决于具应该体场景,问问自己哪一种操作执行的最频繁?对性能的要求是否能否满足?

模型表数量查询直接节点查询树插入删除保证引用完整性
邻接表(不支持递归)1简单困难简单简单
邻接表(支持递归)1简单简单简单简单
枚举路径1困难简单困难困难
嵌套集1困难简单困难困难
闭包表2简单简单简单简单

总结如下:

  • 如果数据库(比如 Oracle)支持递归查询,建议使用邻接表模型。
  • 如果数据库(比如 MySQL)不支持递归查询,建议使用闭包表模型。它需要一张额外的表来存储关系,是一种典型的采用空间来换时间的方案。
  • 枚举路径模型不能保证引用完整性,因此很脆弱,而且也使得存储的数据变得冗余,所以不建议使用。
  • 嵌套集模型也不能保证引用完整性,建议只在一个对查询性能要求非常高,而对其他操作要求一般的场景下才使用它。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
数学与信息技术学院 实 训 报 告 实验课程名称: 智能家居综合实训 实验项目名称: 需求分析与可行性报告 专 业 班 级 : XXX 学 号 : XXX 姓 名 : XXX 指 导 教 师 : XXX 目录 1引言 1 1.1编写目的 1 1.2背景 1 1.3定义 1 1.4 参考资料 1 2任务概述 2 2.1目标 2 2.2用户的特点 2 2.3假设和依赖 2 3需求规定 2 3.1整体布局 2 3.1.1详细布局 3 3.2 系统设计详细分析 3 3.3技术方案设计 4 3.3.1常用远程无线网络技术 4 3.3.2 Zigbee网络结构及节点 4 3.4精度要求 4 3.5故障处理要求 5 3.6安全性要求 5 4运行环境规定 5 4.1接口 5 4.2控制 5 4.3 局限性 5 软件需求说明书 1引言 1.1编写目的 该研究报告的目的是让用户能够了解单元楼用户智能家居的实施的可行性条件、费用 以及局限性等等,可以使用户很清楚的了解整个智能家居系统的功能用途,而且还可以 让用户根据自己的需求去修改设计智能家居系统,以满足不同用户对智能家居化的不同 要求。 1.2背景 伴随城市人口的增加和人们生活节奏的加快,单元楼用户智能家居系统越来越受到了 人们的重视,随着技术的日益成熟,智能家居系统必将普及到每一个用户家中; 本项目的任务提出者、开发者:华江锋; 用户:主要适用于单元楼用户; 该软件系统使用的是zigbee网络结构,zigbee网络的拓扑结构分为三种:星型、树型 和网络型。在单元楼智能家居系统里,我选择星型结构,此智能家居系统我们选用基于 CC2530的Zigbee网络节点设计。 1.3定义 智能家居:是利用先进的计算机技术、网络通讯技术、综合布线技术、依照人体工 程学原理,融合个性需求,将与家居生活有关的各个子系统如安防、灯光控制、窗帘控 制、煤气阀控制、信息家电、场景联动、地板采暖等有机地结合在一起,通过网络化综 合智能控制和管理,实现"以人为本"的全新家居生活体验。 Zigbee网络:是基于无线传感品网络的技术,它用于网点多、体积小、数据量小、 传输可靠、低功耗等场合。 网络拓扑结构:是指用传输媒体互连各种设备的物理布局,就是用什么方式把网络 中的计算机等设备连接起来。拓扑图给出网络服务器、工作站的网络配置和相互间的连 接,它的结构主要有星型结构、环形结构、总线结构、分布式结构树型结构等。 1.4 参考资料 [1]GB/T-8567-2006计算机软件文档编写规范 [2]ZigBeeE技术及应用. 瞿雷、刘盛德、胡咸斌著. 北京航空航天大学出版社,2008.9 2任务概述 2.1目标概述 随着计算机网络技术的不断革新与应用以及社会经济的发展、生活质量的日益改善和 生活节奏的不断加快,人们的生活日益信息化、智能化,人们对于家居的要求已经不仅 仅是物理意义上的生存空间,更为关注的是一个高度安全性、方便、舒适的生活环境、 先进的通讯设备、完备的信息终端、自动化的智能化的家用电器、信息资源使用的网络 化需求等等,根据用户的这些要求,在科学技术的推动下,智能家居系统已经越来越得 到人们的重视。 智能家居是人类住宅的一场新革命,在我国,高科技和信息技术正在由智能大厦走向 智能住宅小区,进而走进家庭。现代社会的家庭正在以家庭智能化带来的多元化信息和 安全、舒适、便利的生活环境,作为一个理想的目标来追求。而智能家居主要是通过网 络来实现的,智能家居网络通常分为家庭数据网络和家庭控制网络两种,它是住宅系统 的重要组成部分。 本智能家居系统,主要是基于Zigbee网络节点的智能家居系统,它成本低,可扩展性 强,灵活性强,开放高效,安全可靠而且可以实现远程终端控制,真正满足了用户智能 家居化的需求。 2.2用户的特点 该系统的用户主要是单元楼智能家居系统的使用者,他们往往工作时间长,生活节奏快 ,因此所用软件的操作一定要设计简单、易于使用、快捷高效,而且对家居系统的设计 还要尽量做到美观,由于单元楼内部的设计规划可能不尽相同,所以设计时可选定一个 设计方案为模型,不同的户型可以在此基础上进行功能模块扩充。采用本系统后不仅可 以让使用者拥有智能舒适的居住环境,更重要的是可以为他们节省宝贵的时间,实现对 家居的远程控制,缓解生活快速的节奏。而且造价相对上班族来说在可承受范围之内, 因此具有可行性。 2.3假设和依赖 本系统设计要求能实时监控,所以要求较高的网络质量。 3需求规定 3.1整体布局 单元楼用户可选择的户型有多种,但无论哪种户型,其内部总体布局基本如下图所示: 3.1.1详细布局 本智能家居的详细布局以及网络节点,如下图所示: 3.2 系统设计详细分析 上图智能家居设计是一个90平方米的普通单元楼家庭智能家居设计,它主
数 据 结 构 计算机系 计算机系数据结构与算法设计全文共241页,当前为第1页。 第一章 绪 论 1.1 什么是数据结构 1.2 基本概念和术语 1.3 抽象数据类型的表示与实现 1.4 算法和算法分 1.4.1 算法 1.4.2 算法设计的要求 1.4.3 算法效率的度量 1.4.4 算法的存储空间的需求 计算机系数据结构与算法设计全文共241页,当前为第2页。 第一章 绪 论 计算机是一门研究用计算机进行信息表示和处理的科学。这里面涉及到两个问题: 信息的表示 信息的处理 而信息的表示和组又直接关系到处理信息的程序的效率。随着计算机的普及,信息量的增加,信息范围的拓宽,使许多系统程序和应用程序的规模很大,结构又相当复杂。因此,为了编写出一个"好"的程序,必须分析待处理的对象的特征及各对象之间存在的关系,这就是数据结构这门课所要研究的问题。 计算机系数据结构与算法设计全文共241页,当前为第3页。 1.1什么是数据结构 众所周知,计算机的程序是对信息进行加工处理。在大多数情况下,这些信息并不是没有组织,信息(数据)之间往往具有重要的结构关系,这就是数据结构的内容。那么,什么是数据结构呢?先看以下几个例子。 例1、电话号码查询系统 设有一个电话号码薄,它记录了N个人的名字和其相应的电话号码,假定按如下形式安排: (a1,b1)(a2,b2)…(an,bn) 其中ai,bi(i=1,2…n) 分别表示某人的名字和对应的电话号码要求设计一个算法,当给定任何一个人的名字时,该算法能够打印出此人的电话号码,如果该电话簿中根本就没有这个人,则该算法也能够报告没有这个人的标志。 计算机系数据结构与算法设计全文共241页,当前为第4页。 算法的设计,依赖于计算机如何存储人的名字和对应的电话号码,或者说依赖于名字和其电话号码的结构。 数据的结构,直接影响算法的选择和效率。 上述的问题是一种数据结构问题。可将名字和对应的电话号码设计成:二维数组、表结构、向量。 假定名字和其电话号码逻辑上已安排成N元向量的形式,它的每个元素是一个数对(ai,bi), 1 i n 数据结构还要提供每种结构类型所定义的各种运算的算法。 计算机系数据结构与算法设计全文共241页,当前为第5页。 例2、图书馆的书目检索系统自动化问题 例3、教师资料档案管理系统 例4、多叉路口交通灯的管理问题 P3 通过以上几例可以直接地认为:数据结构 就是研究数据的逻辑结构和物理结构以及它们 之间相互关系,并对这种结构定义相应的运算, 而且确保经过这些运算后所得到的新结构仍然 是原来的结构类型。 计算机系数据结构与算法设计全文共241页,当前为第6页。 1.2 基本概念和术语 数据(Data):是对信息的一种符号表示。在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。 数据元素(Data Element):是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。 一个数据元素可由若干个数据项组成。数据项是数据的不可分割的最小单位。 数据对象(Data Object):是性质相同的数据元素的集合。是数据的一个子集。 数据结构(Data Structure):是相互之间存在一种或多种特定关系的数据元素的集合。 计算机系数据结构与算法设计全文共241页,当前为第7页。 数据结构主要指逻辑结构和物理结构 数据之间的相互关系称为逻辑结构。通常分为四类基本结构: 一、集合 结构中的数据元素除了同属于一种类型外,别无其它关系。 二、线性结构 结构中的数据元素之间存在一对一的关系。 三、树型结构 结构中的数据元素之间存在一对多的关系。 四、图状结构或网状结构 结构中的数据元素之间存在多对多的关系。 计算机系数据结构与算法设计全文共241页,当前为第8页。 数据结构的形式定义为:数据结构是一个二元组: Data-Structure=(D,S) 其中:D是数据元素的有限集,S是D上关系的有限集。 例 复数的数据结构定义如下: Complex=(C,R) 其中:C是含两个实数的集合 C1,C2 ,分别表示复数的实部和虚部。R={P},P是定义在集合上的一种关系{〈C1,C2〉}。 数据结构在计算机中的表示称为数据的物理结构,又称为存储结构。 计算机系数据结构与算法设计全文共241页,当前为第9页。 数据对象可以是有限的,也可以是无限的。  数据结构不同于数据类型,也不同于数据对象,它不仅要描述数据类型的数据对象,而且要描述数据对象各元素之间的相互关系。 抽象数据类型:一个数学模型以及定义在该模型上的一组操作。   抽象数据类型实际上就是对该数据结构的定义。因为它定义了一个数据的逻辑结构以及在此结构上的一组算法。   用三元组描述如下:    (D,S,P) 计算机系数据结构与算

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值