根据列表表示的序列自然地概括为表示其序列的序列
元素本身可以是序列。例如,我们可以看到由((1 2) 3 4)
构造的对象(cons (list 1 2) (list 3 4))
。序列的元素是树的分支,本身序列的元素是子树。
我不明白。我想看((1 2) (3 4))
和二叉树,但这是三元树(不是二进制)。
列表结构被视为树。
/\\
/\ 3 4
1 2
为什么它不是以下?
/ \
/\ /\
1 2 3 4
答案 0 :(得分:4)
在源自类似Scheme的原始Lisp的语言中,您没有 列表或树作为原始数据结构,但只有 cons cells , 可以用不同的方式来表示更复杂的数据 结构。
例如,没有什么能阻止你将一系列数字表示为 不正确的清单,即将序列1 2 3 4表示为:
(cons 1 (cons 2 (cons 3 4))) ; => '(1 2 3 . 4)
[*|*]--->[*|*]--->[*|*]--->4
| | |
v v v
1 2 3
比通常的正确列表表示更有效:
(cons 1 (cons 2 (cons 3 (cons 4 '())))) = (list 1 2 3 4) ; => '(1 2 3 4)
[*|*]--->[*|*]--->[*|*]--->[*|*]--->()
| | | |
v v v v
1 2 3 4
(例如,考虑一个您必须管理数百万的应用程序 小清单。)
通常使用正确的列表,因为绝大多数原语 函数只为它们定义(例如,如果你尝试,你会得到一个错误 反转'(1 2 3.4)),因此使用起来更方便。
另一方面,对于树木来说,情况更复杂,因为你 可以有不同种类的树,例如:二叉树,其中信息仅存在于树叶中(如示例所示),
二进制树,其中信息出现在每个节点中,
n-ary树,其中的信息存在于每个节点或 在树叶里,
二进制或n-ary树,其中信息是列表,或更复杂的结构(例如另一棵树),
等
由您来决定手头问题的正确表示。 例如,在上面的情况(2)中,这比情况(1)更常见,您可以将树表示为三个元素的列表(信息,左子树,右子树)(并且在此你可以选择一个正确的列表或一个不正确的列表,或者你可以使用一个包含三个字段的结构,甚至是一个包含三个元素的数组。
总结一下,重要的是以这种方式定义一棵树 最适合您的需求(可能会看到是否有预定义的功能或可用的库 已经提供了你需要的运算符),然后定义了基本运算符来处理它,比如在answer of Sylwester中运算符来构建树并使用它的组件,而总是使用它们来编写你的程序。通过这种方式,您可以获得Abstract Data Type方法的所有常见好处,例如,您可以在不修改程序的情况下更改树的表示形式。
答案 1 :(得分:2)
为了更好地理解,将列表翻译成点对:
(cons (list 1 2) (list 3 4)) ; ==
((1 2) 3 4) ==
((1 . (2 . '())) . (3 . (4 . '()))) ; ==
/\
/ \
/\ \
/ \ /\
1 /\ 3/\
2 ()4 ()
您正在绘制的树将是:
((1 . 2) . (3 . 4)) ; but the general way of displaying it would be
((1 . 2) 3 . 4)
我假设一对是汽车正确且cdr是左侧的节点。基本上是:
(define make-tree cons)
(define tree-right car)
(define tree-left cdr)
(define tree? pair?)
(define *tree-null* '())
现在你可以这样建模这样的树:
(define make-tree list)
(define tree-right car)
(define tree-left cadr)
(define tree? list?)
(define *tree-null* '())
然后同一棵树看起来像这样:
((1 2) (3 4))
这并不重要,但第一个例子是常用的方式,因为它占用的空间更少。无论如何,这些都是一样的:
(define (accumulate-tree tree term combiner null-value)
(let rec ((tree tree))
(cond ((eq? *tree-null* tree) null-value)
((not (tree? tree)) (term tree))
(else (combiner (rec (tree-left tree))
(rec (tree-right tree)))))))
(define (copy-tree tree)
(accumulate-tree tree values make-tree *tree-null*))
(define (aritmetric-sum-tree tree)
(accumulate-tree tree values + 0))
(define (reverse-tree tree)
(accumulate-tree tree
values
(lambda (left right) (make-tree right left))
*tree-null*))
修改强>
SICP仅提供不同的方式来查看相同的结构,而不是二叉树。节点是子节点列表,子节点是列表是新节点。了解盒子并且链式缺点有一种奇怪的显示方式,这一点非常重要。注意框子是如何与我的树相似的。
了解使用cons
可以为任何抽象数据结构建模,在创建自己的数据结构时,您将更改如何将元素映射到cons
,这一点非常重要。因此,相同的列表结构可能代表其他东西,具体取决于您如何使用它们。例如。如果你有一个LZW树,你在查找中迭代树,你通常只需要一个父。从而。一对可能是父对象,这个节点值。