这不是家庭作业,我不需要回答,但是现在我变得迷恋了:)
问题是:
大约一年前,我在互联网上找到了解决此问题的方法,但现在我已经忘记了,我想知道:)
据我所记得,这个技巧涉及利用树来实现队列,同时利用算法的破坏性。链接列表时,您还将项目推入队列。
每次尝试解决此问题时,我都会丢失节点(例如,每次将下一个节点链接/添加到队列时),我需要额外的存储空间,或者我无法弄清楚我需要回到的复杂方法具有我需要的指针的节点。
即使是原始文章/帖子的链接对我也将是有用的:) Google并没有给我带来欢乐。
编辑:
Jérémie指出,如果您有一个父指针,则有一个相当简单的答案(众所周知的答案)。虽然我现在认为他对包含父指针的原始解决方案是正确的,但我真的很想解决没有它的问题:)
完善的需求将以下定义用于节点:
struct tree_node { int value; tree_node* left; tree_node* right; };
您可以沿着树的左子级建立链接列表。同时,该列表的右子元素用于保留要插入尾部的下一个子树的队列。
( 编辑:为清楚起见重写 )
root
tail
bubble-to
bubble-from
head
起始树(我相信它应该是一棵完整的树;如果节点丢失,则应该从末尾开始。您可以尝试为其他情况赋予含义,但是有几种不同的可能性,并且涉及到很多摆弄):
1 / \ 2 3 / \ / \ 4 5 6 7 / \ / \ / \ / \ 8 9 A B C D E F
请注意,这些不一定是节点的值,它们只是出于显示目的而编号。
经过1次迭代树(注意列表从形成1到3与植根于子树的队列4和5):
1
3
4
5
head v 1 / \ tail 2 4 v / \ / \ 3 5 8 9 / \ / \ 6 7 A B / \ / \ C D E F
后3次迭代(现在该列表是1到5,并且队列保存植根于子树6到9):
6
9
head v 1 / \ 2 6 / \ / \ 3 7 C D / \ / \ 4 8 E F / \ tail > 5 9 / \ A B
并且经过8次迭代(几乎完成):
head v 1 / \ 2 B / \ 3 C / \ 4 D / \ 5 E / \ 6 F / 7 / 8 / 9 / tail > A
这是节点类:
(defclass node () ((left :accessor left) (right :accessor right) (value :accessor value)))
一个有用的助手:
(defmacro swap (a b) `(psetf ,a ,b ,b ,a))
转换功能( 编辑:为清楚起见而重写 ):
(defun flatten-complete-tree (root) (loop for tail = (and root (left root)) then (left tail) while tail do (swap (left tail) (right root)) (loop for bubble-to = root then (left bubble-to) for bubble-from = (left bubble-to) until (eq bubble-from tail) do (swap (right bubble-to) (right bubble-from)))) root)
我已经重写了上面的内容,以允许任意锯齿状的树。但是,您不能再以此来重建原始树。
(defun flatten-tree (root)
;; 这里的内部循环保持head在尚未展开的子树的根 ; ;; 即第一个分支的节点 ;同时从根部向左熨烫所有东西。 ;; nil当树完全展平时,它结束。
nil
(loop for head = (loop for x = (or head root) then (left x) do (when (and x (null (left x))) (swap (left x) (right x))) until (or (null x) (right x)) finally (return x)) for tail = (and head (left head)) then (left tail) while head do (swap (left tail) (right head))
;; 这个内部循环是 O(n) 队列插入
(loop for bubble-to = head then (left bubble-to) for bubble-from = (left bubble-to) until (eq bubble-from tail) do (swap (right bubble-to) (right bubble-from))))
;; 最后,返回原始根。
root)