Recursion 有人能给我解释一下这种递归吗?

Recursion 有人能给我解释一下这种递归吗?,recursion,binary-tree,binary-search-tree,pseudocode,Recursion,Binary Tree,Binary Search Tree,Pseudocode,我想了解递归。 我理解数学中愚蠢的例子,但我不确定它的本质 我有一个例子,我不明白它是如何工作的: TREE-ROOT-INSERT(x, z) if x = NIL return z if z.key < x.key x.left = TREE-ROOT-INSERT(x.left, z) return RIGHT-ROTATE(x) else x.right = TREE-ROOT-INSERT(x.right, z) return LEFT-ROTA

我想了解递归。 我理解数学中愚蠢的例子,但我不确定它的本质

我有一个例子,我不明白它是如何工作的:

TREE-ROOT-INSERT(x, z)

if x = NIL
   return z
if z.key < x.key
   x.left = TREE-ROOT-INSERT(x.left, z)
   return RIGHT-ROTATE(x)
else 
   x.right = TREE-ROOT-INSERT(x.right, z)
   return LEFT-ROTATE(x)
TREE-ROOT-INSERT(x,z)
如果x=NIL
返回z
如果z键
我知道该代码的作用: 首先在BST中插入一个节点,然后每次旋转一次,使新节点成为根节点

但在我分析代码时,我认为它将节点插入到它必须去的地方,然后只旋转树一次


怎么可能每次都旋转树?

您需要在树的每个级别的递归调用中保持您的位置。当您第一次点击“返回右旋转”(或“左旋转”)时,您还没有完全完成;您获取由
ROTATE
函数生成的树,并将其放置在递归
tree-ROOT-INSERT
调用在堆栈中更高一级的代码中。然后再次旋转,将当前树返回堆栈中更高一级的位置,直到到达树的原始根

理解递归最重要的是将递归函数视为一个抽象黑盒。换句话说,在阅读或推理递归函数时,您应该关注当前迭代,将递归函数的调用视为原子调用(您无法深入探讨),假设它可以执行它应该执行的操作,并查看如何使用其结果来解决当前迭代

您已经知道您的
树根插入(x,z)
的契约:

将z插入以x为根的二叉搜索树,变换树,使z成为新根

让我们看一下这个片段:

   if z.key < x.key
      x.left = TREE-ROOT-INSERT(x.left, z)
      return RIGHT-ROTATE(x)
同样,您不知道调用
TREE-ROOT-INSERT(x.left,z)
将如何获得z根子树。现在你不在乎了,因为真正重要的部分是:如何让整棵树扎根于z?答案是
右旋转(x)

但在我分析代码时,我认为它将节点插入到它必须去的地方,然后只旋转树一次

树怎么可能每次都旋转

如果我理解正确,您仍然在思考如何以非递归的方式解决问题。确实,您可以使用标准BST插入过程将z插入以x为根的BST。这将使z处于正确的位置。但是,要从该位置将z带到根部,需要进行不止一次旋转


在递归版本中,在获得z根子树后,需要旋转以将z带到根。但是要从原始的x.left-rooted子树得到z根子树,还需要进行旋转。旋转被多次调用,但在不同的子树上。

这可能是一个更好的示例。这里的示例插入15表示可能需要多个旋转 x / \ z ... / \ ... ...