优先搜索树混乱

Priority Search Tree confusion

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

  • Sort all points by their x coordinate value and store them in the leaf nodes of a balanced binary tree (i.e., a range tree)
  • Starting at the root, each node contains the point in its subtree with the maximum value for its y coordinate that has not been stored
    at a shallower depth in the tree; if no such node exists, then node
    is empty

我实现了范围树 ,所以根据我在那里使用的示例,我现在有(对于 优先搜索树):

                             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)。是的,所以我在两个 children 中进行,但是对于 简单,让我跟着左边的(从现在开始所有情况下)。
  2. 我检查 -3 是否是 x 范围以及 6 是否大于或等于 查询的 y 范围的上限(即 5)。是的,所以我 继续。
  3. 下一关也一样,所以我们进入下一关,现在请 专注于这个内部节点。它的最大 y 为 0,这表明 子树的max y为0,这是不正确的(left child是 (-5, 6))*.

我在 building/searching 过程中遗漏了什么?


换句话说:

检查树最左边的分支;它具有 max_y 值(引号中的第二个项目符号),7、6、4、0。

但是那个值不是表示存储在内部节点下的子树中的最大y值的值吗?如果是这样,这不适用于0 和点 (-5, 6) (没有使用 6,因为它在第 2 级使用)。


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

你上次的逻辑其实还是对的。当您点击标记为 (6,-3) 的节点时,(-5,6) 值应该已经被拾取。 现在,我不是数学专业的。但总体思路是这样的。在您实施的优先搜索树中,您实际上是在根据两个不同的条件进行搜索。 对于 x,它是范围的简单二进制搜索。 对于 y,您实际上是在将其作为优先级树进行搜索(适合搜索 y:inf 或 -inf:y,具体取决于您使用的是最大值还是最小值。)

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

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

树中的每个节点基本上都存储了 2 个东西。 1. x的中点(或者说左树中的max-x,判断向左遍历还是向右遍历是根据>x校验)。 2. 未添加到上一个子树中y值最高的POINT。

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

编辑非常非常长的文本: 让我们 运行 通过您的示例。我已经使用字母(点的 "name")标记了每个点。每个节点现在都有点名称的格式,括号中是 y 值,下面是 "mid-range" 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)

  • 从根开始,我们看到E点。
  • E点的y(7)是否>=1?是的
  • E(0)点的x在[-2:4]内吗?是
  • 将 E 添加到输出。
  • 中点(也是0)在范围内吗?是
  • 从有E的节点开始,需要遍历两边
  • 首先,我们向左走,我们看到A点。
  • A(6)点的y是否>=1?是的
  • A(-5)点的x在[-2:4]内吗?号
  • 跳过A,但继续遍历(只有y检查停止遍历)。
  • A点的中点在[-2:4]范围内吗?不,在左边。
  • 由于-3 < [-2:4],我们只需要向右遍历即可。现在我们看到D点了。
  • 点D(2)的y是否>=1?不!跳过该点停止向下遍历,因为D下面没有其他点我们没有输出(注意,即使E在D下面,我们一开始访问root的时候E已经输出了)
  • 我遍历到A,左边的路不需要遍历,继续往上走。
  • 现在我回到了根目录,这两个目录都需要遍历。因为我们只是向左走,所以我们向右走。在那里,我们看到点 G
  • G点的y(6)是否>=1?是
  • G(3)点的x在[-2:4]内吗?是
  • 将 G 添加到输出,现在我们有 (E,G)。
  • G处的中点在范围内吗?是的,我们得从两边走过去。
  • 我们先往左走。我们看到F.
  • F(1)点的y是否>=1?是
  • F(2)点的x在[-2:4]内吗?是
  • 将 F 添加到输出,现在我们有 (E,F,G)
  • 中点是在[-2:4]中的F处吗?是的,我们得从两边走过去。
  • 让我们再次先向左走,我们看到... NIL。下面没有更多要添加的点(因为我们之前已经 checked/added F,G)。
  • 我们回到F,往右走,我们看到H。
  • H点的y(-4)是否>=1?不行,不加点就停止遍历
  • 我们回到 F,它已经遍历了两条路径。
  • 我们回到G,它还需要正确的路径遍历。
  • 我们沿着正确的路径往下走,看到我。
  • I(3)点的y是否>=1?是
  • I(5)点的x在[-2:4]内吗?号
  • 跳过 F.
  • I 的中点是否在 [-2,4] 范围内?不,更大。
  • 因为比较大,我们只需要遍历左边,就这样吧。
  • 从左侧向下我们看到...我,又一次。因为我们已经看到了I,而且它是一个叶子节点,所以我们停止遍历并返回到I。
  • 我搞定了(不需要向右遍历)。回到G.
  • G完成(两边遍历)。回到 E.
  • E完成(两边遍历)。由于 E 是根节点,我们现在完成了。

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