Путаница в дереве поиска приоритетов

Единственный разумный набор слайдов, который я нашел, это то, что на странице 15 говорит, для построения:

  • Сортируйте все точки по их значениям координаты x и сохраните их в конечных узлах сбалансированного двоичного дерева (т. Е. Дерева диапазонов)
  • Начиная с корня, каждый узел содержит точку в своем поддереве с максимальным значением для его координаты y, которое не было сохранено
    на меньшей глубине в дереве; если такого узла не существует, то узел
    пустой

Я реализовал Range Range непосредственно перед этим, поэтому на основе примера, который я там использовал, теперь у меня есть (для дерева поиска приоритетов):

                             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. То же самое для следующего уровня, поэтому мы переходим на следующий уровень и теперь, пожалуйста, сосредоточимся на этом внутреннем узле. Он имеет значение max y a 0, что указывает на то, что max y поддерева равно 0, что неверно (левый дочерний элемент равен (-5, 6))*.

Чего мне не хватает в процессе сборки / поиска?


Другими словами:

Проверьте крайнюю левую ветвь дерева; это как max_y значения (2-й пункт в цитате), 7, 6, 4, 0.

Но не является ли это значение тем, которое указывало максимальное значение y, хранящееся в поддереве под внутренним узлом? Если это так, это не относится к 0 и указать (-5, 6) (6 не используется, так как используется на 2-м уровне).


*Определенный запрос, который я задаю, может быть не поврежден этим, но другой может.

1 ответ

Решение

Ваша последняя логика на самом деле все еще верна. Значение (-5,6) должно быть уже подобрано, когда вы нажмете на узел, который вы пометили (6,-3). Теперь я не математик. Но общая идея такова. В дереве Приоритетного поиска, который вы внедрили, вы выполняете поиск по двум отдельным критериям. Для х это простой двоичный поиск диапазона. Для y вы фактически ищете его как дерево приоритетов (хорошо для поиска y:inf или -inf:y, в зависимости от того, используете ли вы max или min.)

Обратите внимание, что в нижней части страницы 15 указано, что дерево подходит для полубесконечного диапазона (один из них бесконечный). Продолжайте читать, вы увидите, как дерево оптимизировано для полубесконечного диапазона для y.

Короче говоря, поскольку ваше дерево построено с x в качестве двоичного поиска и y в качестве приоритета (с использованием максимального оставшегося значения), оптимальный поиск - [x1:x2],[y1:inf].

Каждый узел в дереве по сути хранит 2 вещи. 1. Средняя точка x (или max-x в левом дереве, и решение пройти влево или вправо основано на проверке>x). 2. ТОЧКА с наибольшим значением y в поддереве, которое не было добавлено к предыдущему.

По сути, алгоритм поиска выглядит так. Начиная с корня, используя критерии [x1:x2], [y1:inf] 1. Проверьте значение y ТОЧКИ, присвоенной узлу. Если y > y1, переходите к 2, иначе ПРЕКРАТИТЕ прохождение вниз (поскольку ТОЧКА, назначенная узлу, имеет наибольшее значение y, если проверка не удалась, под ним нет другого узла, который мог бы выполнить [y1:inf]. 2. Проверьте если значение x точки находится в диапазоне [x1:x2]. Если это так, включите эту точку в выходные данные. Если вы включили эту точку, переходите к шагу 3. 3. Проверьте значение "средней точки" узла (давайте назовем это mx.) Если mx находится в диапазоне [x1: x2], пройдите по обоим путям. Если mx <

РЕДАКТИРОВАТЬ для очень, очень длинного текста: давайте разберем ваш пример. Я сделал дополнительную аннотацию, помечая каждую точку буквой ("имя" точки). Теперь у каждого узла есть формат имени точки, с его значением 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)

  • Начиная с корня, мы видим точку E.
  • Является ли у точки E (7) > ​​= 1? Да.
  • Является ли x точки E (0) в [-2:4]? да
  • Добавьте E к выводу.
  • Средняя точка (также 0) находится в диапазоне? да
  • От узла с E нужно пройти обе стороны.
  • Сначала пойдем налево, видим точку А.
  • Y точки A(6) >= 1? Да.
  • Является ли x точки A(-5) в [-2:4]? Нет.
  • Пропустите A, но продолжайте движение (только проверка y останавливает движение).
  • Находится ли средняя точка А в диапазоне [-2:4]? Нет, это слева.
  • Поскольку -3 <[-2: 4], нам нужно пройти только вправо. Теперь мы видим точку D.
  • Является ли у точки D(2) >= 1? Нет! Пропустите точку и прекратите движение вниз, так как под D нет другой точки, которую мы НЕ вывели (заметьте, даже если E ниже D, E уже выводится, когда мы посетили root в начале).
  • Я иду до A, так как нам не нужно пересекать левый путь, продолжайте идти вверх.
  • Теперь я вернулся к корню, который должен пройти оба. Так как мы просто пошли налево, мы идем направо. Там мы видим точку G
  • Является ли у точки G (6) >= 1? да
  • Является ли х точки G (3) в [-2:4]? да
  • Добавьте G к выводу, теперь мы имеем (E,G).
  • Средняя точка в G находится в диапазоне? Да, нам придется пройти через обе стороны.
  • Пойдемте налево первым. Мы видим Ф.
  • Является ли у точки F (1) >= 1? да
  • Является ли х точки F (2) в [-2:4]? да
  • Добавьте F к выводу, теперь мы имеем (E,F,G)
  • Средняя точка в F в [-2:4]? Да, нам придется пройти через обе стороны.
  • Давайте снова пойдем налево сначала, мы видим... NIL. Там нет больше точек, которые будут добавлены ниже (так как мы уже проверяли / добавляли F, G раньше).
  • Давайте вернемся к F и пройдем по правой стороне, мы увидим H.
  • Является ли у точки H (-4) >= 1? Нет. Не добавляй точку и не прекращай обходить.
  • Мы возвращаемся к F, который уже прошел оба пути.
  • Мы возвращаемся к G, который все еще нуждается в его правильном обходе пути.
  • Пройдем по правильному пути и увидим меня.
  • Является ли у точки I (3) >= 1? да
  • Является ли х точки I (5) в [-2:4]? Нет.
  • Пропустить Ф.
  • Находится ли средняя точка в I в диапазоне [-2,4]? Нет, это больше.
  • Поскольку он больше, нам нужно пройти только левую сторону, так что давайте сделаем это.
  • Пройдя вниз по левой стороне, мы видим... Я снова. Так как мы уже видели I, и это листовой узел, мы прекращаем обход и возвращаемся к I.
  • Я сделал (не нужно проходить вправо). Вернитесь к Г.
  • G сделано (обе стороны пройдены). Вернитесь к E.
  • E сделано (обе стороны пройдены). Поскольку E является корневым узлом, мы закончили.

Результат "E,F,G" находятся в диапазоне.

Другие вопросы по тегам