Logic 如何确定您需要右-右旋转还是左-右旋转

Logic 如何确定您需要右-右旋转还是左-右旋转,logic,avl-tree,Logic,Avl Tree,我正在尝试实现一个AVL树,我很难知道何时需要RR或RL旋转(LL和LR也是如此) 每种方法的先决条件是什么,它们有什么不同。我知道当我看到树的图片时(凭直觉),但实际情况如何 这是一个逻辑问题,不需要代码,谢谢 我所知道的是,它涉及到树的左重或右重。但是您如何确定呢?可能有不同的解决方案,但有一个如下所示: 递归添加项时,在每次递归调用时,您应该跟踪该调用是将节点添加到左子树还是右子树(例如,通过让add函数返回节点)。递归调用后,检查高度不变量。如果在插入后发现该节点上的it已被违反,则您将

我正在尝试实现一个AVL树,我很难知道何时需要RR或RL旋转(LL和LR也是如此)

每种方法的先决条件是什么,它们有什么不同。我知道当我看到树的图片时(凭直觉),但实际情况如何

这是一个逻辑问题,不需要代码,谢谢


我所知道的是,它涉及到树的左重或右重。但是您如何确定呢?

可能有不同的解决方案,但有一个如下所示:

递归添加项时,在每次递归调用时,您应该跟踪该调用是将节点添加到左子树还是右子树(例如,通过让add函数返回节点)。递归调用后,检查高度不变量。如果在插入后发现该节点上的it已被违反,则您将知道不平衡的路径

某些(不完整)伪代码:

add(item, node):
  if item < node.value //should add to left subtree
    if node.left is empty
      //add item here
    else
      addedLeft := add(item, node.left)
      if node.left.height - node.right.height > 1
        if addedLeft
          //you know the path to the subtree causing the imbalance is LL, do a RR (single-right) rotation
        else
          //path is LR, do a LR (double-right) rotation
  ...
添加(项目、节点):
如果项1
如果加德夫特
//您知道导致不平衡的子树路径是LL,请执行RR(单右)旋转
其他的
//路径为LR,进行LR(双右)旋转
...

递归调用将从添加的节点自下而上展开,一般的想法是检查在哪个节点违反了不变量(如果有)。当发现该节点时,您需要知道导致不平衡的子树的路径。人们必须以某种方式解决这个问题,这是一种解决办法。

可能有不同的解决办法,但有一种办法如下:

递归添加项时,在每次递归调用时,您应该跟踪该调用是将节点添加到左子树还是右子树(例如,通过让add函数返回节点)。递归调用后,检查高度不变量。如果在插入后发现该节点上的it已被违反,则您将知道不平衡的路径

某些(不完整)伪代码:

add(item, node):
  if item < node.value //should add to left subtree
    if node.left is empty
      //add item here
    else
      addedLeft := add(item, node.left)
      if node.left.height - node.right.height > 1
        if addedLeft
          //you know the path to the subtree causing the imbalance is LL, do a RR (single-right) rotation
        else
          //path is LR, do a LR (double-right) rotation
  ...
添加(项目、节点):
如果项1
如果加德夫特
//您知道导致不平衡的子树路径是LL,请执行RR(单右)旋转
其他的
//路径为LR,进行LR(双右)旋转
...

递归调用将从添加的节点自下而上展开,一般的想法是检查在哪个节点违反了不变量(如果有)。当发现该节点时,您需要知道导致不平衡的子树的路径。必须以某种方式解决该问题,这是一种解决方案。

您是否考虑过某个操作,例如,将节点添加到树中,然后维护balance属性?添加和删除都是如此,但如果我理解其中一个,我想另一个也同样容易。我希望树在任何时候都保持平衡,但由于它唯一的修改时间是通过添加或删除元素,因此我看不到任何其他必要的时刻。但我更愿意在您考虑某个操作时,集中精力添加元素,例如,在树中添加一个节点,然后在添加和删除中维护平衡属性,但如果我理解其中一个,我认为另一个也同样容易。我希望树在任何时候都保持平衡,但由于它唯一的修改时间是通过添加或删除元素,因此我看不到任何其他必要的时刻。但我更愿意集中精力在此时添加元素,因此我必须跟踪添加节点时的路径。这是否意味着我需要记住最后两条路径?(LL或LR等)?好的,是和否。是因为它是确定要执行的旋转所必需的,不是因为你不需要比上面的pseude代码更“记住”它-这里的逻辑是,如果我们决定将节点添加到左子树,并且要添加的递归调用也决定将项添加到其左子树,导致不平衡的子树必须离开当前节点。那有用吗?是的,我想我明白了。我需要首先实现这一点,但如果它起作用(意味着我确实理解了你的意思),我将选择你的答案,否则我将更新问题。不管怎样,谢谢。所以我必须跟踪添加节点时的路径。这是否意味着我需要记住最后两条路径?(LL或LR等)?好的,是和否。是因为它是确定要执行的旋转所必需的,不是因为你不需要比上面的pseude代码更“记住”它-这里的逻辑是,如果我们决定将节点添加到左子树,并且要添加的递归调用也决定将项添加到其左子树,导致不平衡的子树必须离开当前节点。那有用吗?是的,我想我明白了。我需要首先实现这一点,但如果它起作用(意味着我确实理解了你的意思),我将选择你的答案,否则我将更新问题。不管怎样,谢谢你。