Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Гибрид массива и списка


Автор: T42 1.12.2010, 21:00
Вопрос по структурам данных. Кто нибудь знает или может быть видел где нибудь структуру, позволяющую реализовать массив элементов, с возможностью быстрой вставки (добавления) и удаления элемента в любом месте массива и с возможностью быстрого доступа по индексу за время О(log2(n)), или быстрее? Естественно, структура должна быть самобалансирующейся за такое же время или быстрее.

Автор: Akina 1.12.2010, 22:13
Связные списки. Индексированные списки. Деревья.

Автор: Predator_2004 1.12.2010, 22:17
В большинстве книжек в конце главы посвяшенной вашему вопросу есть что-то типа: "Реализация очереди/списка на базе массива". Да и в интернете полно примеров. В общем случае принципиальное отличие только выделении/отдаче памяти - в при добавлении элемента память не выделяется а элемент записывается по определенному индексу в массиве. Вся память выделяется на этапе инициализации.

Автор: T42 1.12.2010, 22:40
Доступ к элементам списка - за О(n) операций, деревья не поддерживают вставку по произвольному индексу, только по элементу. При чем тут "Реализация очереди/списка на базе массива", вообще не пойму...

Автор: Predator_2004 1.12.2010, 22:43
А-а-а деревья!! Деревья - частный случай графов, а альтернативное представление графов - матрица смежности (двумерный массив).

Автор: T42 1.12.2010, 22:57
Деревья не подходят, я же написал...

Автор: Predator_2004 1.12.2010, 23:02
Видимо я совсем вымотался и плохо соображаю. Переформулируйте пожалуйста вопрос, так чтобы он содержал собственно какие структуры вы имеете ввиду, и все требования.

Автор: T42 1.12.2010, 23:11
Однако... Хорошо. Нам нужна совершенно новая, нетипичная структура данных, которая бы обладала преимуществами как списка, так и обыкновенного массива. А именно, быстрый доступ по индексу (как у обычного массива), и быстрая вставка/удаление (как у списка). Список не подходит, т.к. имеет медленный доступ по индексу, а обыкновенный массив не подходит, т.к. при удалении элемента, скажем, из середины массива, требует сдвиг всех остальных элементов, что очень долго...

Автор: Akina 1.12.2010, 23:18
Ну так линейный массив плюс кластеризованный индекс. Это же ещё в DBF/NDX было реализовано... только на диске - а ты организуй в памяти.
Недостатки: увеличенный расход памяти (возможно наличие неиспользуемых блоков в массиве данных), необходимость периодического сжатия массива данных и перестроения массива индексов. Но зато вставка в произвольное место и поиск O(log2(N)) - как просили. Плюс можно, как в NTFS, вести битовую карту использования элементов в массиве - чтобы избегать быстрого распухания массива данных и частой необходимости сжимать его.
А если размер элементов массива невелик - то просто кластерное хранение. Правда, тогда и вставка будет как поиск - О(log2(N)), но зато не нужен массив-индекс.

Автор: pathfinder 2.12.2010, 09:42
T42, 

Как раз таки массив можно реализовать поверх дерева

Код

Неявные декартовы деревья

Неявное декартово дерево - это простая модификация обычного декартового дерева, которая, тем не менее, оказывается очень
мощной структурой данных. Фактически, неявное декартово дерево можно воспринимать как массив, над которым можно 
реализовать следующие операции (все за O (log N) в режиме онлайн):

    * Вставка элемента в массив в любую позицию
    * Удаление произвольного элемента
    * Сумма, минимум/максимум на произвольном отрезке, и т.д.
    * Прибавление, покраска на отрезке
    * Переворот (перестановка элементов в обратном порядке) на отрезке

Ключевая идея заключается в том, что в качестве ключей key следует использовать индексы элементов в массиве. Однако явно 
хранить эти значения key мы не будем (иначе, например, при вставке элемента пришлось бы изменять key в O (N) вершинах дерева).

Заметим, что фактически в данном случае ключ для какой-то вершины - это количество вершин, меньших неё. Следует заметить, 
что вершины, меньшие данной, находятся не только в её левом поддереве, но и, возможно, в левых поддеревьях её предков. Более 
строго, неявный ключ для некоторой вершины t равен количеству вершин cnt(t->l) в левом поддереве этой вершины плюс 
аналогичные величины cnt(p->l)+1 для каждого предка p этой вершины, при условии, что t находится в правом поддереве для p.

Ясно, как теперь быстро вычислять для текущей вершины её неявный ключ. Поскольку во всех операциях мы приходим в 
какую-либо вершину, спускаясь по дереву, мы можем просто накапливать эту сумму, передавая её функции. Если мы идём в левое 
поддерево - накапливаемая сумма не меняется, а если идём в правое - увеличивается на cnt(t->l)+1.


Полностью статья http://e-maxx.ru/algo/treap

Автор: _Y_ 2.12.2010, 09:58
Мне почему-то кажется, что задача должна решаться с привязкой к языку (языки ведь по-разному работают с паматью). Да и к задаче.

В общем же виде, у меня был такой вариант:

Нужен был "быстрый" массив с небольшим максимальным количеством членов, которые только могли быть добавлены за время работы программы. Я сделал два массива: один со значениями и еще один Boolean того же размера. При удалении члена, соответствуюшее Boolean значение менялось на False, а размер массива оставался прежним. Работало быстро.

Автор: Akina 2.12.2010, 11:49
Цитата(_Y_ @  2.12.2010,  10:58 Найти цитируемый пост)
Я сделал два массива: один со значениями и еще один Boolean того же размера. При удалении члена, соответствуюшее Boolean значение менялось на False, а размер массива оставался прежним. Работало быстро.

Я об этом говорил:
Цитата(Akina @  2.12.2010,  00:18 Найти цитируемый пост)
можно, как в NTFS, вести битовую карту использования элементов в массиве 


Автор: T42 2.12.2010, 13:12
Всем большое спасибо за предложенные варианты. Решение вопроса находится в области деревьев с неявными индексами (ключами). Ближе всех оказался pathfinder, статья про декартовое дерево содержит один из вариантов решения задачи.

Автор: _Y_ 2.12.2010, 16:53
Цитата(Akina @  2.12.2010,  11:49 Найти цитируемый пост)
Я об этом говорил: можно, как в NTFS, вести битовую карту использования элементов в массиве 

У меня было даже проще, чем ты описал. Т.к. количество элементов было небольшим, поиск "свободных" ячеек не производился. Новые элементы просто дописывались в хвост; при этом размер массива задавался заранее с запасом и имелся указатель на следующий элемент для записи. Ничего быстрее придумать не удалось.

Автор: Alexk553 13.12.2010, 19:30
А сколько дополнительной памяти автор готов пожертвовать для реализации этой структуры? Массив - самая экономная структура: только данные иду сплошным блоком в памяти. Списки, в зависимости от платформы ещё требуют один или два указателя (а это 4 или 8 байт) на каждый элемент. 

Могу предложить двоичное дерево поиска, полезной нагрузкой которого (элементами тобишь) которое содержит индексы элементов массива. 

для добавления элемента он дописывается в конец массива, память выделяется блоками. - запись моментальна, но нужно ещё модифицировать дерево. 
для поиска - поиск по двоичному дереву. 
удаление - то же самое. Но физически элемент будет находиться в памяти, поэтому нужен ещё один массив индексов удалённых элементов. 
 из недостатков - если память забивается, или идёт очень интенсивные и равные потоки удаление -> добавление, то будет требоваться регулярная чистка и реиндексация, во время которых работа невозможна. 
Это для однопоточной работы.

короче есть куча нюансов:

одно или многопоточная реализация?
масштабируемость алгоритма в случае многопоточности.
величина (добавленные - удалённые) делить на (добавленные + удалённые) в единицу времени
допустимые затраты памяти.
если объём данных выходит за пределы ОЗУ, какой процент сдампленных на жёсткий диск данных.
и.т.п.
потому что какая бы ни была реализация, есть сильные и слабые стороны.



Автор: T42 28.12.2010, 05:50
Alexk553,  вы зачем в топик не вникаете? Я же написал уже что решение найдено. Только что прочитал ваше сообщение, зачем огород нагородили? Поумничать? Все намного проще. Существует элегантное, достаточно экономное, быстрое решение задачи. Хотите знать какое? Читайте статью pathfinder.

Автор: pathfinder 28.12.2010, 12:41
T42, статья про декартово дерево НЕ моя, а http://forum.vingrad.ru/users/maxdiver-а. 

Автор: T42 29.12.2010, 08:17
pathfinder,  прошу прощения, я имел ввиду вашу статью в том смысле что вы дали на нее ссылку. А вот то, что автор, оказывается, тоже присутствует на форуме, я не знал.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)