优先搜索树混淆

时间:2016-05-14 03:33:40

标签: algorithm search binary-search-tree computational-geometry range-tree

我找到的唯一合理的幻灯片集是this,在第15页中说,用于构建:

  
      
  • 按x坐标值对所有点进行排序并将其存储在   平衡二叉树的叶节点(即范围树)
  •   
  • 从根开始,每个节点包含其子树中的点,其y坐标的最大值尚未存储
      在树的较浅的深度;如果不存在这样的节点,那么节点
      是空的
  •   

我实现了一个范围树just before,因此根据我在那里使用的示例,我现在(对于优先搜索树):

                             7
                      ------ 0 ---------------------
                      |                            |
                      6                            6
                ---- -3 ----                  ---- 4 ------ 
                |          |                  |           |
                4          2                  1           3
          ---- -4 -       -2              --- 3 ---       5
          |       |       / \             |       |      / \
          0    (-3,4) (-2,2)(0,7)        NIL   (4,-4) (5,3)(6,-1)
         -5                               2    
         / \                             / \
    (-5,6) (-4,0)                    (2,1) (3,6)

此处,每个内部节点的格式为:

mid_x
max y

我正在构建的范围查询是(-inf,1)x(-0.5,5),即(x_low,x_high)x(y_low,y_high)。

  1. 所以,让我们从根开始,检查x(= 0)是否在(-inf,1)中 如果7> (-0.5,5)。因此,我继续两个孩子,但是 简单,让我按照左边的那个(在所有情况下从现在开始)。
  2. 我检查-3是否是x范围,如果6大于或等于 查询的y范围的上限(即5)。是的,所以我 继续。
  3. 相同的下一个级别,因此我们进入下一个级别,现在请 专注于这个内部节点。它的最大值为0,表示该值 子树的最大y是0,这是不正确的(左子是 (-5,6)) *
  4. 在构建/搜索过程中我缺少什么?

    换句话说:

    检查树的最左边的分支;它有max_y个值(引用中的第2个子弹),7,6,4,0。

    但该值是否指示存储在内部节点下的子树中的最大y值的值?如果是,则不适用于0和点(-5, 6)(6未使用,因为它在第2级使用)。

    * 我提出的特定查询可能不会被此损坏,但另一个可以。

1 个答案:

答案 0 :(得分:2)

你最后的逻辑实际上仍然是正确的。当您点击标记为(6,-3)的节点时,应该已经拾取了(-5,6)值。 现在,我没有数学专业。但总体思路是这样的。在您实施的优先搜索树中,您实际上是在两个不同的标准上进行搜索。 对于x,它是对范围的简单二进制搜索。 对于y,您实际上正在搜索它作为优先级树(适合搜索y:inf或-inf:y,具体取决于您使用的是max还是min。)

请注意,在第15页的底部,它指出树适用于半无限范围(一个是无限的)。继续阅读,您将看到树如何针对y的半无限范围进行优化。

简而言之,由于您的树构造为x作为二分搜索,y作为优先级(使用最大剩余值),最佳搜索是[x1:x2],[y1:inf]。

树中的每个节点实际上存储了两件事。 1. x的中点(或左树中的max-x,以及向左或向右移动的决定基于> x检查)。 2.子树中y值最高且未添加到前一个的POINT。

搜索算法基本上是这样的。使用[x1:x2],[y1:inf]标准从根开始 1.检查分配给节点的POINT的y值。如果y> y1,转到2,否则STOP遍历(因为分配给节点的POINT具有最高y值,如果检查失败,则其下面没有其他节点可以满足[y1:inf]。 2.检查点的x值是否在[x1:x2]的范围内。如果是这样,请在输出中包含该点。无论您是否包括该点,都继续执行步骤3。 3.检查节点"中点"价值(让我们称之为mx)。如果mx在[x1:x2]的范围内,则向下遍历两个路径。如果mx是< [x1:x2],向左移动。否则就行了。对于您遍历的每条路径,请返回步骤1。

编辑非常非常长的文字: 让我们来看看你的例子吧。我已经使用字母(点" s"名称")标记了每个点的附加注释。每个节点现在都具有点名称的格式,在父母的情况下具有y值,并且"中间范围"它下面的x。对于叶节点,那些带有' *'意味着它们已经被分配到树的某个地方,如果你到达它们,应该被视为NIL。

                              7(E)
                       ------ 0 ---------------------
                       |                            |
                      A(6)                         G(6)
                 ----- -3 -----                  ---- 4 -------- 
                 |            |                  |             |
                 C(4)        D(2)               F(1)          I(3)
           ---- -4 -         -2              --- 3 ---         5
           |       |         / \             |       |        / \
           B(0)  C*(-3,4)D*(-2,2)E*(0,7)     NIL   H(4,-4) I*(5,3)J(6,-1)
          -5                                 2   
          / \                               / \
    A*(-5,6)B*(-4,0)                   F*(2,1) G*(3,6)

让我们运行[-2:4] [1:inf](或任何y> = 1)的示例查询

  • 从root开始,我们看到E点。
  • 点E(7)的y是> = 1?是。
  • [ - 2:4]中的点E(0)的x是多少?是
  • 将E添加到输出。
  • 中点(也是0)是否在范围内?是
  • 从带有E的节点开始,需要遍历两侧。
  • 首先,让我们离开,我们看到A点。
  • 点A(6)的y是> = 1?是。
  • [ - 2:4]中A点(-5)的x是多少?否。
  • 跳过A,但继续遍历(只有y检查停止转换)。
  • A的中点是否在[-2:4]的范围内?不,它在左边。
  • 从-3< [-2:4],我们只需要向右移动。现在我们看到D点。
  • 点D(2)的y是否= 1?没有!跳过点并停止向下移动,因为在D下没有其他点我们没有输出(注意,即使E低于D,当我们在开始访问root时已经输出了E。)
  • 我走到A,因为我们不需要穿越左路,继续上升。
  • 现在我回到了根,这需要遍历。自从我们离开后,我们就走了。在那里,我们看到了点G
  • 点G(6)的y是> = 1?是
  • [ - 2:4]中点G(3)的x是?是
  • 将G添加到输出中,现在我们有(E,G)。
  • G的中点是否在范围内?是的,我们必须穿越双方。
  • 让我们先走吧。我们看到F。
  • 点F(1)的y是> = 1?是
  • 点[F:2]的x在[-2:4]中?是
  • 将F添加到输出,现在我们有(E,F,G)
  • F中的中点是[-2:4]吗?是的,我们必须穿越双方。
  • 让我们再次离开,我们看到...... NIL。下面不再添加点数(因为我们之前已经检查/添加了F,G)。
  • 让我们回到F并沿着右侧行进,我们看到H.
  • 点H(-4)的y是否= 1?不。不要添加点并停止遍历。
  • 我们回到F,已经遍历了两条路径。
  • 我们回到G,仍然需要正确的路径遍历。
  • 我们沿着严谨的路径走,看见我。
  • 点I(3)的y是> = 1?是
  • [-2:4]中的点I(5)的x是多少?否。
  • Skip F。
  • I的中点是否在[-2,4]的范围内?不,它更大。
  • 由于它更大,我们只需要遍历左侧,所以让我们这样做。
  • 我们看到......我再次走向左侧。既然我们已经看过I,而且它是一个叶子节点,我们就会停止遍历并返回到我。
  • 我已经完成了(不需要向右移动)。回到G。
  • G完成(双方遍历)。回到E。
  • E完成(双方遍历)。由于E是根节点,我们现在已经完成了。

结果是" E,F,G"在范围内。