排序二叉树转换为循环双向链表

构建一个递归函数treeToList(Node root),将一棵已排序的二叉树,调整内部指针,使之从外面看起来,是一个循环双向链表。其中前向指针存储在"small"区域,后向指针存储在"large"区域。链表需要进行调整进行升序排序,并返回链表头指针。下面的这篇文章详细解释了这个转换的过程。

以下是对这篇文章的翻译:

The Great Tree-List Recursion Problem

内容: 1. Ordered binary tree 2. Circular doubly linked list 3. The Challenge 4. Problem Statement 5. Lessons and Solution Code

介绍:

此问题会使用到两个数据结构 — 一个已排序的二叉树,以及一个循环双向链表。这两者存储的都是已排序的元素,但是看上去完全不同。1. 排序二叉树(Ordered Binary Tree)

在一棵已排序的二叉树中,每个节点包含一个独立的数据元素和指向子树的"small"以及"large"指针(有时这两个指针称为"left"左指针和“right”右指针)。下面所示的是一棵已排序的二叉树,包含元素1到5.

图1 – 已排序的二叉树

其中,"small"子树中的所有节点,小于等于父节点。"large"子树中的所有节点,大于父节点。所以在上述例子中,"small"子树中的节点都会小于等于4,而"large"子树中的所有节点,会大于4. 这条规则对树中的每个节点都适用。而null指针,用来表示一个分支的结束。实际上,null指针代表0个节点的树。树中最顶点的节点称为根节点root。2. 循环双向链表(Circular Doubly Linked List)

下面是1至5的一个循环双向链表

图2 – 循环双向链表

循环双向链表相对普通链表,拥有下面两个额外的特性:a)."双向"代表每个节点拥有两个指针- 后向指针"next"以及前向指针"previous"。

b)."循环"代表链表没有起点和终点。实际上,最后一个节点的后向指针,指向的是首节点。而首节点的前向指针,指向的是最后一个节点。

通常,一个null指针代表一个0个元素的链表。而长度为1的链表看起来会有点奇怪。如下面所示:

图3 – 长度为1的循环双向链表

长度为1的链表中的那个节点,既是首节点,也是最后一个节点(末节点),所以前向指针和后向指针,指向的都是它自己。所以即使长度为1的链表,也遵守了上面的特性。

本质 – 节点在构造时就不同

这里就是Great Tree-List问题的本质:二叉树中的节点,与链表中的节点,都有着相同的类型结构 – 它们都包含了一个元素和两个指针。唯一的区别在于,二叉树中的两个指针标识为"small"和"large",而链表中标识为"previous"和"next"。忽略掉标识后,这两个节点的类型其实是一样的。

3.难题

真正的困难在于将此二叉树转换成循环双向链表。"small"指针代表"previous",而"large"指针代表"next"。转换完成后,需要调整链表来达到升序排序。

图4 – 添加了后向指针(next)后的二叉树

上面的这个图中,黑色线条表示原始二叉树中的后向指针,即链表中用箭头表示的。前向指针没有进行演示。

完整的调整演示:

图5 – 添加了前向指针与后向指针的二叉树

最可怕的敌人,就是没有坚强的信念。

排序二叉树转换为循环双向链表

相关文章:

你感兴趣的文章:

标签云: