Хранение разреженного массива
От: DSblizzard Россия  
Дата: 30.10.07 01:07
Оценка:
Дан массив в 10^9 элементов, но известно, что одновременно в нем может храниться не более 10^6 (скажем, ненулевые, остальные нули). Элементы могут как добавляться, так и удаляться. Способ хранения с возможностью только добавления я придумал — время доступа O( (log(n))^3 ). А вот с удалением проблемы. Кто-нибудь знает, где можно найти алгоритм и структуру данных? Должны быть относительно быстрыми операции вставки, удаления, присваивания, взятия значения и поиск.
Программировать сложно. Но не программировать еще сложнее.
Re: Хранение разреженного массива
От: McSeem2 США http://www.antigrain.com
Дата: 30.10.07 03:46
Оценка: 1 (1) +2
Здравствуйте, DSblizzard, Вы писали:

DS> А вот с удалением проблемы. Кто-нибудь знает, где можно найти алгоритм и структуру данных? Должны быть относительно быстрыми операции вставки, удаления, присваивания, взятия значения и поиск.


Хэш-таблица — классическое решение. Пр хорошей хеш-функции все операции получаются достаточно хорошо сбалансированными по времени выполнения. Поиск элемента — в среднем констатное время O(1). Недостаток — значительная дисперсия по времени операций. То есть, скажем, в 99% случаев время доступа — O(1), но для некоторых элементов может сваливаться до O(N). В среднем же гораздо быстрее Binary Search
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: Хранение разреженного массива
От: Mab Россия http://shade.msu.ru/~mab
Дата: 30.10.07 07:44
Оценка: 2 (1)
Здравствуйте, DSblizzard, Вы писали:

Любой ассоциативный контейнер подойдёт. Про хеш-таблицу уже написали. Можно сделать map на сбалансированном дереве (хотя бы std::map), будет O(log n) на любую операцию.
Re[2]: Хранение разреженного массива
От: a18 Россия  
Дата: 31.10.07 05:51
Оценка:
MS> но для некоторых элементов может сваливаться до O(N).
Хм, а как это может произойти?
ИМХО, если у хеша разумный уровень коллизий и размер хеша примерно соответствует числу хранимых элементов, то доступ к элементу всегда должен быть в районе O(1).
Re[3]: Хранение разреженного массива
От: Mab Россия http://shade.msu.ru/~mab
Дата: 31.10.07 06:01
Оценка: +1
Здравствуйте, a18, Вы писали:

a18>ИМХО, если у хеша разумный уровень коллизий и размер хеша примерно соответствует числу хранимых элементов, то доступ к элементу всегда должен быть в районе O(1).

Ну так это при условии, что хеш-значения независимы и равномерно распределены. Но никто не гарантирует, что количество коллизий не станет порядка N.
Re[4]: Хранение разреженного массива
От: a18 Россия  
Дата: 31.10.07 07:11
Оценка: -1
a18>>ИМХО, если у хеша разумный уровень коллизий и размер хеша примерно соответствует числу хранимых элементов, то доступ к элементу всегда должен быть в районе O(1).
Mab>Ну так это при условии, что хеш-значения независимы и равномерно распределены. Но никто не гарантирует, что количество коллизий не станет порядка N.

Мысль ясна. Только, наверное, не N, а, в нашем примере, 10^9/10^6=1000 коллизий на ячейку хеш-таблицы для наихудшего набора данных (если, конечно, хеш хоть сколько-нибудь годный). Но, согласен, даже это немало.
Re: Хранение разреженного массива
От: a18 Россия  
Дата: 31.10.07 12:55
Оценка:
DS>Дан массив в 10^9 элементов, но известно, что одновременно в нем может храниться не более 10^6 (скажем, ненулевые, остальные нули). Элементы могут как добавляться, так и удаляться. Способ хранения с возможностью только добавления я придумал — время доступа O( (log(n))^3 ). А вот с удалением проблемы. Кто-нибудь знает, где можно найти алгоритм и структуру данных? Должны быть относительно быстрыми операции вставки, удаления, присваивания, взятия значения и поиск.

О, как раз пара статей на эту тему подвернулись (про хеш-таблицы):
http://rsdn.ru/article/alg/bintree/hash.xml
Автор(ы):

http://thespoke.net/ViewContent.aspx?PostID=477174
Re[5]: Хранение разреженного массива
От: Mab Россия http://shade.msu.ru/~mab
Дата: 31.10.07 20:50
Оценка:
Здравствуйте, a18, Вы писали:

a18>Мысль ясна. Только, наверное, не N, а, в нашем примере, 10^9/10^6=1000 коллизий на ячейку хеш-таблицы для наихудшего набора данных (если, конечно, хеш хоть сколько-нибудь годный). Но, согласен, даже это немало.

Не понял, честно говоря, откуда такая дробь взялась. Коллизия -- это когда совпадают хеши у разных ключей. Вот в худшем случае они все и совпадут.
Re[6]: Хранение разреженного массива
От: a18 Россия  
Дата: 01.11.07 07:04
Оценка:
a18>>Мысль ясна. Только, наверное, не N, а, в нашем примере, 10^9/10^6=1000 коллизий на ячейку хеш-таблицы для наихудшего набора данных (если, конечно, хеш хоть сколько-нибудь годный). Но, согласен, даже это немало.
Mab>Не понял, честно говоря, откуда такая дробь взялась. Коллизия -- это когда совпадают хеши у разных ключей. Вот в худшем случае они все и совпадут.

ОК, попробую привести пример:
Задача — представить массив с ключами в виде целых чисел от 0 до 10^9 (ключи влезают в 30 бит), у которого только некоторые (10^6) элементы заполнены единицами, а всё остальные — нули.
В качестве хеш функции возьмём очень упрощённый вариант — 20 бит от ключа (для удобства — пусть это будут старшие биты — с 10-го по 29-й, нумерация с 0).
Соответственно, строим хеш-таблицу в виде массива от 0 до 2^20-1 (чуть больше 1 млн. ячеек).
Теперь пытаемся заполнить эту хеш-таблицу максимально плохими (с точки зрения коллизий) данными. Очевидно, для этого надо брать ключи подряд от 0 и дальше. Ключи 0-1023 дадут одинаковый хеш (0) и попадут в первую ячейку хеш-таблицы, следующая пачка ключей (1024-2047) уже пойдёт во вторую ячейку и т.п.
Т.е. даже для самого худшего набора данных получаем всего примерно 10^3 коллизий в ячейке. Вот это я и имел ввиду.

Конечно, если взять совсем дурацкий хеш (например, который для любого ключа тупо выдаёт 0), то можно догнать число коллизий и до 10^6, но это уже совсем маразм!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.