【问题标题】:why an adjacency list might not be preferred for a tree?为什么邻接表可能不适合一棵树?
【发布时间】:2020-04-22 16:09:23
【问题描述】:

由于树是没有循环的稀疏图,邻接表不是首选表示是否有原因? 为什么最常使用链接结构来表示树?​​p>

【问题讨论】:

  • 我不确定这是否完全正确。根据我的阅读,语言将树 - BST - 红黑树实现为链接结构(指向节点的节点)而不是邻接列表。如果兄弟姐妹之间的顺序很重要,那么我们可能会使用链接结构,否则我们可以使用邻接列表。
  • 所以在 n-ary 的情况下,hashmap(adj 列表)的优点是我们可以访问任何节点及其 adj。 o(1) 中的列表。我什么时候更喜欢使用指针(节点本身存储其子数组)作为 n 元?
  • 好的,谢谢。这很好地回答了我的问题。

标签: tree


【解决方案1】:

将邻居(子项)的数据保留在外部邻接列表中,而不是节点对象中的字段,这是关于将数据放置在何处的设计决策,这样最有利于支持数据结构的典型操作。

Adjacency lists 通常实现为 node => node[] 对的哈希,其中每个节点都指向一个列表或一组邻居(在树中,孩子)。这种表示在graphs 中比树更典型(trees 是一种特定类型的有向图,它是非循环的,除根之外的所有节点都只有一个传入边)。

将邻接列表中的数据外部化的主要优点是易于对其进行聚合操作或提供对任何成员的恒定时间访问。这些属性在图上更为重要,例如,您可能会从图中的每个节点开始运行BFS。另一方面,树使用根作为其操作的单个入口点(traversals、插入、删除、旋转等),并且节点基本上不需要随机访问,除非作为这样的一个步骤从根开始操作。

在树中,有 binary trees 和 n 叉树,其中每个节点最多有 n 子节点。根据后续 cmets,您提到 BSTs 和 red-black 树(均为二叉树)作为使用子指针(即 this.leftthis.right)而不是邻接列表的示例。

对于二叉树,node.leftnode.right 是非常明确的属性。为左右子节点保留两个单独的哈希并使用 leftChildren[node]rightChildren[node] 访问它们是冗长的,增加了额外的状态并导致哈希查找开销没有明显的优点。

红黑树会变得更糟,因为它与父母和其他关系有关,每一个都需要一个额外的“邻接”哈希。对于二叉树或具有node.leftnode.right 属性的任何东西,邻接列表(或任何列表/数组)基本上不适用,但对于n 叉树来说仍然存在,node.children 属性很多更类似于tree[node]children[node]

除了访问字段之外,当属性位于外部数据结构中时,函数头和状态通常会变得更加复杂。考虑def inorder(tree, root)def inorder(root)tree 可以成为类成员,但这并不能改变额外状态需要以某种方式传递和管理的事实。

另一个考虑因素是某些语言(例如 C)没有对哈希映射、集合或动态列表的原生支持。可以给节点 0..n 个 id 字段并索引到数组中,但指针方法在低级语言中很自然。

在某些情况下,图或树中的数据非常简单(例如,连续整数),可以完全消除节点,以支持单独的邻接表或二维数组。 binary heap 是树数据的一个很好的例子,它非常适合作为平面结构工作,强化了选择最有意义的表示的想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 2018-03-29
    • 1970-01-01
    相关资源
    最近更新 更多