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

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

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

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

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

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


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

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

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


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


person gsamaras    schedule 14.05.2016    source источник
comment
У вас достаточно репутации, чтобы знать лучше... stackoverflow.com/help/mcve Люди делают предположения о том, что они делают которые неверны, а затем не публикуют детали, которые действительно важны, потому что они предполагают, что делают эту часть правильно.   -  person xaxxon    schedule 14.05.2016
comment
@xaxxon это связано с алгоритмом, а не с тем, как я преобразовываю псевдокод в код!   -  person gsamaras    schedule 14.05.2016
comment
тогда почему это помечено с++?   -  person xaxxon    schedule 14.05.2016
comment
Я использую C++, если это имеет значение, это в вопросе @xaxxon. Хорошая мысль, но я ее удалю!   -  person gsamaras    schedule 14.05.2016
comment
Внутренние узлы содержат среднее значение x (которое содержит бинарное дерево) и максимальное значение y, которые лежат (?) под его поддеревом. @xaxxon   -  person gsamaras    schedule 14.05.2016
comment
Я не понимаю, что каждый узел содержит точку в своем поддереве, что такое точка в поддереве и как вы ее содержите?   -  person xaxxon    schedule 14.05.2016
comment
Я проверяю, находится ли x (=0) в (-inf, 1) и если 7 ‹ (-0,5, 5). Это так, я продолжаю в обоих детей 0 не внутри -inf.. -0,5   -  person xaxxon    schedule 14.05.2016
comment
максимальное значение y, лежащее (?) под его поддеревом - тогда не должно ли узлу 4-4 быть 6-4? Извините, это все, что у меня есть на данный момент.   -  person xaxxon    schedule 14.05.2016
comment
@xaxxon спасибо за попытку помочь! 1) Если прочитать все предложение, там говорится, что узел содержит значение y, то есть максимальное значение, появившееся в поддереве. Например, корень имеет 7, так как все точки, которые хранятся в его поддереве (всем дереве, поскольку это корень), имеют максимум 7 в качестве координаты y. 2) Как я пояснил в своем вопросе, (-inf, 1) - это диапазон x, который нас интересует, больше -inf и меньше 1 в этом случае. 3) Цитата со слайдов говорит о том, что значение не должно было использоваться где-либо еще, а 6 используется на предыдущем уровне, вот что меня смущает!!   -  person gsamaras    schedule 14.05.2016


Ответы (1)


Ваша последняя логика на самом деле все еще верна. Значение (-5,6) уже должно было быть получено, когда вы нажмете на узел, который вы пометили (6,-3). Так вот, я не специалист по математике. Но общая идея такова. В дереве приоритетного поиска, как вы реализовали, вы фактически выполняете поиск по двум отдельным критериям. Для x это простой бинарный поиск диапазона. Для 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 равно ‹ [x1:x2], пройдите влево. В противном случае пройдите вправо. Вернитесь к шагу 1 для каждого пути, который вы траверс.

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

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

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

person ShuberFu    schedule 14.05.2016
comment
Почему вы используете такой запрос, как [x1:x2], [y1:inf]? Я понимаю, что это может быть быстрее, но эквивалентно тому, что я просил? - person gsamaras; 14.05.2016
comment
Принципиальное отличие состоит в том, что ваш полубесконечный диапазон находится на значении x. Построенное вами дерево оптимизировано для полубесконечного диапазона значения y. Другими словами, построенное вами дерево оптимизировано для поиска x в пределах диапазона и отклонения y ниже определенного значения. - person ShuberFu; 14.05.2016
comment
Итак, правильно ли я разместил древовидное здание в Стерлинге? На данный момент меня не интересуют какие-либо оптимизации. - person gsamaras; 14.05.2016
comment
Да, дерево, которое вы строите, правильное. Главное, как вы его пройдете. Правильное дерево не работает, если вы не проходите его правильно. Я добавил довольно длинный пример, подробно описывающий логику перемещения. Надеюсь, это поможет. - person ShuberFu; 14.05.2016
comment
Стерлинг, ты прекрасен! Я буду искать другие сообщения от вас, может быть, так же хорошо, как это! Однако позволю себе высказать некоторые мысли: 1) Is the y of point D(2) >= 1? No! Это да. D должен быть выведен. 2) Is the mid-point at F in [-2:4]? Yes, we'll have to traverse both sides. Я бы прошел только по левой ветви, так как левая ветвь содержит точки с x ‹= 4, что является верхней границей значения x нашего запроса диапазона. Я перестану читать здесь, но я понял идею, большое спасибо! - person gsamaras; 14.05.2016