Шаг обновления в Fenwick Trees
Мой вопрос касается полного обоснования шага обновления в Binary Indexed Trees (деревья Фенвика). Таким образом, при обновлении нашего массива с определенным приращением в определенной позиции обновление происходит следующим образом:
void updateBIT(int BITree[], int n, int index, int val)
{
// index in BITree[] is 1 more than the index in arr[]
index = index + 1;
// Traverse all ancestors and add 'val'
while (index <= n)
{
// Add 'val' to current node of BI Tree
BITree[index] += val;
// Update index to that of parent in update View
index += index & (-index);
}
Моя проблема с index += index & (-index);
часть. Обратите внимание, что я понимаю index & (-index)
немного, особенно в контексте запроса дерева.
Я попробовал несколько примеров вручную, используя это правило обновления индекса, но мне не удалось найти логику добавления index & (-index)
для того, чтобы перейти к следующему узлу, который должен быть обновлен.
От того, что я получил до этого момента, узел i
в BIT "отвечает" за исходные значения в массиве, начиная от [i - i & (-i) + 1, i]
, так что это подразумевает, что любой узел попадет в диапазон этой формы. Конкретно, насколько я понимаю, при желании обновить позицию k
в исходном массиве мы выполняем следующие шаги (концептуально, а не в реальном коде):
- итерация
0
: ОбновитьBIT[k + 1]
(индексы сдвинуты на1
в массиве BIT). Пока еще на итерации0
мы обновляем индекс, на который мы смотрим, поэтому я предполагаю, что мы ищем следующий наименьший интервал, который отвечает за узелk
следовательно, нам нужно найти следующий индексi
гдеi - i & (-i) < k < i
, Найти этот индексi
увеличивая текущий индекс наk & (-k)
,
Остальные итерации происходят таким же образом, пока мы не выйдем за пределы. Я пробовал множество примеров вручную, и до сих пор не понимаю, зачем добавлять i & (-i)
ведет нас к следующему правильному узлу. Каждый и каждый учебник, который я нашел в Интернете, включая видео, абсолютно неуместен в этом вопросе.
Здесь есть несколько связанных вопросов о битах, пожалуйста, не объединяйте их с моими, прежде чем читать их внимательно. Насколько мне известно, этот конкретный вопрос не получил ответа.
1 ответ
Итак, позвольте мне попытаться объяснить вышеприведенный сценарий на простом примере.
Давайте принимать i = 12
, Теперь мы обновляем BIT[12]
, Теперь следующий шаг в соответствии с алгоритмом обновления i += i&(-i)
,
Что такое 12 в двоичном = 01100
, Последний установленный бит 2
, значение 2^2
= 4 (как вы знаете
0th bit value is 2^0 = 1
1st bit value is 2^1 = 2
2nd bit value is 2^2 = 4.
Аналогичным образом для других битов.
Так что теперь следующий индекс, который мы будем обновлять, 12 + 4 = 16
, т.е. BIT[16]
,
Теперь речь шла о том, как работает система. Позвольте мне объяснить простыми словами, почему эта техника работает.
Скажем, мне нужно обновить index = 1
и скажем, значение массива MAX равно 8. Так что весь индекс я буду обновлять 1,2,4,8
,
Теперь, скажем, мне нужно обновить index = 3
, Таким образом, индексы массива я буду обновлять 3,4,8
,
Итак, вы видите, как до сих пор BIT[4]
получил сумму всех значений из индекса массива 1 to 4
,
Теперь предположим, что вам нужно получить общую сумму за первые 4 числа, просто BIT[4]
и вы пройдете через индексы 4,0
, Короче говоря, вы не проходите через 1,2,3
, Как мы видели, как эти индексы были покрыты из-за битовых манипуляций.
Надеюсь это поможет!