Итак, предположим, у вас есть коллекция предметов. Каждый элемент имеет идентификатор, который может быть представлен с использованием битового поля. В качестве простого примера, предположим, что ваша коллекция:
0110, 0111, 1001, 1011, 1110, 1111
Итак, вы хотите реализовать функцию, Remove(bool bitval, int position)
. Например, вызов Remove(0, 2)
удалит все элементы, где индекс 2 (то есть 3-й бит) равен 0. В этом случае это будет только 1001. Remove(1,1)
удалит 1110, 1111, 0111 и 0110. Тривиально создать коллекцию O (n) там, где это возможно (просто используйте связанный список), где n - это количество элементов в коллекции. Как правило, количество элементов, которые должны быть удалены, будет O (n) (при условии, что данный бит имеет вероятность ≥ c%, равную 1, и вероятность ≥ c%, равную 0, где c - некоторая постоянная> 0), так что «лучшие» алгоритмы, которые так или иначе представляют собой O (l), где l - это количество удаляемых элементов, являются неинтересными.
Можно ли определить структуру данных, в которой среднее (или еще лучше, в худшем случае) время удаления лучше, чем O (n)? Бинарное дерево может работать очень хорошо (просто удалите все левые / правые ветви на высоте m, где m тестируемый индекс), но мне интересно, есть ли способ добиться большего успеха (и, честно говоря, я не знаете, как эффективно удалить все левые или правые ветви на определенной высоте). В качестве альтернативы, есть ли доказательство того, что добиться лучшего невозможно?
Редактировать: Я не уверен точно, чего я ожидаю с точки зрения эффективности (извините, Арно), но основное объяснение его возможного применения таково: предположим, мы работаем с двоичным деревом решений. Такое дерево может быть использовано для игрового дерева или для решения головоломок или чего-то еще. Далее предположим, что дерево достаточно мало, чтобы мы могли поместить все листовые узлы в память. Каждый такой узел - это просто битовое поле, в котором перечислены все решения. Теперь, если мы хотим обрезать произвольные решения из этого дерева, одним из методов будет просто перепрыгнуть на высоту, на которой принимается конкретное решение, и обрезать левую или правую сторону каждого узла (слева означает одно решение, справа - другое) , Обычно в дереве решений вы хотите обрезать поддерево только за один раз (поскольку родитель этого поддерева отличается от родителя других поддеревьев, и, следовательно, решение, которое следует удалить в одном поддереве, не следует обрезать от других), но в В некоторых ситуациях это может быть не так. Кроме того, обычно вы хотите только удалить все под конкретным узлом, но в этом случае вы оставите некоторые элементы ниже узла, но также обрежете ниже других узлов в дереве.
Во всяком случае, это отчасти вопрос, основанный на любопытстве; Я не уверен, что практично использовать какие-либо результаты, но мне интересно, что люди скажут.
Edit:
Думая об этом дальше, я думаю, что метод дерева на самом деле O (n / logn), предполагая, что он достаточно плотный. Доказательство:
Предположим, у вас есть двоичное дерево с n элементами. Это высота log (n). Удаление половины дна потребует n / 2 удаления. Удаление половины строки выше потребует n / 4. Сумма операций для каждой строки равна n-1. Таким образом, среднее количество удалений составляет n-1 / log (n).