Algorithm 大树表递归程序

Algorithm 大树表递归程序,algorithm,pointers,recursion,tree,circular-list,Algorithm,Pointers,Recursion,Tree,Circular List,我遇到了一个有趣的问题,叫做巨树列表问题。问题如下: 在有序二叉树中,每个节点都包含一个数据元素和指向子树的“小”和“大”指针。“小”子树中的所有节点都小于或等于父节点中的数据。“大”子树中的所有节点都大于父节点。循环双链表由上一个指针和下一个指针组成 问题是取一个有序的二叉树,重新排列内部指针,使之成为一个循环的双链表。“小”指针应起“上一个”的作用,“大”指针应起“下一个”的作用。列表的排列方式应使节点的顺序递增。我必须编写一个递归函数&返回指向新列表的头指针 操作应在O(n)时间内完成 我

我遇到了一个有趣的问题,叫做巨树列表问题。问题如下:

在有序二叉树中,每个节点都包含一个数据元素和指向子树的“小”和“大”指针。“小”子树中的所有节点都小于或等于父节点中的数据。“大”子树中的所有节点都大于父节点。循环双链表由上一个指针和下一个指针组成

问题是取一个有序的二叉树,重新排列内部指针,使之成为一个循环的双链表。“小”指针应起“上一个”的作用,“大”指针应起“下一个”的作用。列表的排列方式应使节点的顺序递增。我必须编写一个递归函数&返回指向新列表的头指针

操作应在O(n)时间内完成

我知道递归将沿着树进行,但是如何递归地将小的和大的子树更改为列表,我还必须将这些列表与父节点一起追加


我该如何处理这个问题?。。我只是需要一个解决问题的方向

假设您有一个包含3个节点的简单树

B <--- A ---> C
bc
沿着左右两侧走,获取每个节点的指针,然后

B -> C
B <- C
B->C

其思想是创建一种方法,将包含子树(子节点)的树节点转换为循环。对于已转换子节点的节点(例如,在递归调用返回后),可以通过将最大节点的大指针(下一个)指向最小节点,将最小节点的小指针指向最大节点来创建新循环

可能不完整,但将接近于此:

tree_node {
    small
    large
}

convert(node){
    //base case 1, if leaf node
    if node.small == null && node.large == null
        return (self, self)

    //recursively convert children
    if node.small !=null
        smallest, larger = convert(node.small)
    else
        smallest = larger = self

    if node.large !=null
        smaller, largest = convert(node.large)
    else
        smaller = largest = self

    //wrap the ends of the chain
    largest.large = smallest
    smallest.small = largest
    //wrap the mid part
    smaller.small = larger
    larger.large = small

    //return pointers to the absolute smallest and largest of this subtree
    return (smallest, largest)
}

//actually doing it 
convert(tree.root)

递归编程的关键是想象你已经有了解决方案

因此,您已经有了一个函数
recLink(treet t)
,该函数接收指向树的指针,将树转换为双链接循环列表,并返回指向列表头部(最左侧)节点的指针:


完成边缘案例(空子分支等):

所以“有序二叉树”几乎就像BST?按顺序递归遍历应该可以正常工作。只需确保在访问(修改)节点本身之前存储指向正确子树的指针。我想这应该是O(n),但内存占用可能会变得非常糟糕。(特别是在使用有限堆栈时)解决方案:
recLink( n={Node: left, elt, right}) =  // pattern match tree to a full node
  rt := recLink( right);                // already
  lt := recLink( left);                 //   have it
  n.right := rt;       n.left := lt.left;        // middle node
  lt.left.right := n;  rt.left.right := lt;      // right edges
  lt.left := rt.left;  rt.left := n;      
  return lt;