Fusion tree — различия между версиями
Zernov (обсуждение | вклад) |
Zernov (обсуждение | вклад) м (→Вычисление sketch(x)) |
||
Строка 54: | Строка 54: | ||
# Уберем все несущественные биты <tex>x' = x \& \displaystyle \sum_{i=0}^{r-1}2^{b_i}</tex>. | # Уберем все несущественные биты <tex>x' = x \& \displaystyle \sum_{i=0}^{r-1}2^{b_i}</tex>. | ||
− | # Умножением на некоторое заранее вычисленное число <tex>M = \displaystyle\sum_{i=0}^{r-1}2^{m_i}</tex> сместим все существенные биты в блок меньшего размера: <tex>x'\times M = \displaystyle(\sum_{i=0}^{r-1}x_{b_i}2^{b_i})(\sum_{i=0}^{r-1}2^{m_i}) = \sum_{i=0}^{r-1}\sum_{j=0}^{r-1}x_{b_i}2^{b_i+m_j}</tex>. | + | # Умножением на некоторое заранее вычисленное число <tex>M = \displaystyle\sum_{i=0}^{r-1}2^{m_i}</tex> сместим все существенные биты в блок меньшего размера: <tex>x'\times M = \displaystyle \left( \sum_{i=0}^{r-1}x_{b_i}2^{b_i} \right) \left(\sum_{i=0}^{r-1}2^{m_i}\right) = \sum_{i=0}^{r-1}\sum_{j=0}^{r-1}x_{b_i}2^{b_i+m_j}</tex>. |
# Применив побитовое <tex>\&</tex>, уберем лишние биты, появившиеся в результате умножения: <tex>\displaystyle\sum_{i=0}^{r-1}\sum_{j=0}^{r-1}x_{b_i}2^{b_i+m_j} \& \displaystyle\sum_{i=0}^{r-1}2^{b_i+m_i} = \sum_{i=0}^{r-1}x_{b_i}2^{b_i+m_i}</tex>. | # Применив побитовое <tex>\&</tex>, уберем лишние биты, появившиеся в результате умножения: <tex>\displaystyle\sum_{i=0}^{r-1}\sum_{j=0}^{r-1}x_{b_i}2^{b_i+m_j} \& \displaystyle\sum_{i=0}^{r-1}2^{b_i+m_i} = \sum_{i=0}^{r-1}x_{b_i}2^{b_i+m_i}</tex>. | ||
# Сделаем сдвиг вправо на <tex>m_0 + b_0</tex> бит. | # Сделаем сдвиг вправо на <tex>m_0 + b_0</tex> бит. |
Версия 20:21, 5 июня 2015
Fusion tree — дерево поиска, позволяющее хранить
-битных чисел, используя памяти, и выполнять операции поиска за время . Эта структура данных была впервые предложена в 1990 году М. Фредманом (M. Fredman) и Д. Уиллардом (D. Willard).Содержание
Структура
Fusion tree — это B-дерево, такое что:
- у всех вершин, кроме листьев, детей,
- время, за которое определяется, в каком поддереве находится вершина, равно .
Такое время работы достигается за счет хранения дополнительной информации в вершинах. Построим цифровой бор из ключей узла дерева. Всего ветвящихся вершин. Биты, соответствующие уровням дерева, в которых происходит ветвление, назовем существенными и обозначим их номера . Количество существенных битов равно (все ребра на уровне детей ветвящейся вершины являются существенными битами).
В Fusion tree вместе с ключом
хранится — последовательность битов .Утверждение: |
сохраняет порядок, то есть , если . |
Рассмотрим наибольший общий префикс | и . Тогда следующий бит определяет их порядок и одновременно является существенным битом. Поэтому, если , то и .
Поиск вершины
Пусть
— множество ключей узла, отсортированных по возрастанию, — ключ искомой вершины, — количество бит в . Сначала найдем такой ключ , что . Но положение среди не всегда эквивалентно положению среди , поэтому, зная соседние элементы , найдем и .Понятия succ(q) и pred(q)
Пусть
.Утверждение: |
Среди всех ключей наибольший общий префикс с будет иметь или или . |
Предположим, что | имеет наибольший общий префикс с . Тогда будет иметь больше общих битов со . Значит, ближе по значению к , чем или , что приводит к противоречию.
Сравнивая
и , найдем какой из ключей имеет наибольший общий префикс с (наименьшее значение соответствует наибольшей длине).Предположим, что
— наибольший общий префикс, а его длина, — ключ, имеющий наибольший общий префикс с ( или ).- если , то бит равен единице, а бит равен нулю. Так как общий префикс и является наибольшим, то не существует ключа с префиксом . Значит, больше всех ключей с префиксом меньшим либо равным . Найдем , , который одновременно будет ,
- если — найдем , . Это будет .
Длина наибольшего общего префикса двух w-битных чисел
и может быть вычислена с помощью нахождения индекса наиболее значащего бита в побитовом и .Параллельное сравнение
Найдем
и . Определим как число, составленное из единиц и , то есть . Вычтем из число . В начале каждого блока, где , сохранятся единицы. Применим к получившемуся побитовое c , чтобы убрать лишние биты.
Если
, то , в противном случае . Теперь надо найти количество единиц в . Умножим на , тогда все единицы сложатся в первом блоке результата, и, чтобы получить количество единиц, сдвинем его вправо.Вычисление sketch(x)
Чтобы найти sketch за константное время, будем вычислять
, имеющий все существенные биты в нужном порядке, но содержащий лишние нули.- Уберем все несущественные биты .
- Умножением на некоторое заранее вычисленное число сместим все существенные биты в блок меньшего размера: .
- Применив побитовое , уберем лишние биты, появившиеся в результате умножения: .
- Сделаем сдвиг вправо на бит.
Утверждение: |
Дана последовательность из чисел . Тогда существует последовательность , такая что:
|
Выберем некоторые Чтобы получить , таким образом, чтобы . Предположим, что мы выбрали . Тогда . Всего недопустимых значений для , поэтому всегда можно найти хотя бы одно значение. , выбираем каждый раз наименьшее и прибавляем подходящее число кратное , такое что . |
Первые два условия необходимы для того, чтобы сохранить все существенные биты в нужном порядке. Третье условие позволит поместить sketch узла в w-битный тип. Так как
, то будет занимать бит.Индекс наиболее значащего бита
Чтобы найти в
-битном числе индекс самого старшего бита, содержащего единицу, разделим на блоков по бит. . Далее найдем первый непустой блок и индекс первого единичного бита в нем.1) Поиск непустых блоков.
a. Определим, какие блоки имеют единицу в первом бите. Применим побитовое
к и константе .
b. Определим, содержат ли остальные биты единицы.
Вычислим
.
Вычтем из . Если какой-нибудь бит обнулится, значит, соответствующий блок содержит единицы.
Чтобы найти блоки, содержащие единицы, вычислим .
c. Первый бит в каждом блоке содержит единицу, если соответствующий блок ненулевой.
2) Найдем , чтобы сместить все нужные биты в один блок. Существенными битами в данном случае будут первые биты каждого блока, поэтому .
Будем использовать
. Тогда . Все суммы различны при . Все возрастают, и .Чтобы найти
, умножим на и сдвинем вправо на бит.3) Найдем первый ненулевой блок. Для этого надо найти первую единицу в
. Как и при поиске и используем параллельное сравнение с . В результате сравнения получим номер первого ненулевого блока .4) Найдем номер
первого единичного бита в найденном блоке так же как и в предыдущем пункте.5) Индекс наиболее значащего бита будет равен
.Каждый шаг выполняется за
, поэтому всего потребуется времени, чтобы найти индекс.См. Также