map::insert

Тема в разделе "LANGS.C", создана пользователем cupuyc, 5 авг 2011.

  1. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Dmitry_Milk
    Не дольше чем в дерево. Добавлять в хеш-таблицу можно без выделения памяти из кучи. А куча она умеет потормозить.
     
  2. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    r90
    У Вас проблемы с теорией алгоритмов. Вставка в табличку будет занимать время ~n, вставка в дерево ~ln(n). Так что ничуть не меньше.

    Atlantic
    Покажите алгоритм.

    Всё это похоже на какой-то гон: вот, если взять хороший аллокатор, если предположить, что преимущественно будет происходить не вставка, а поиск и т.п. Дайте, наконец, кусок кода мапы size_t -> size_t. r90, Вы ведь били себя в грудь: Ну дык его писать -- двадцать минут вместе с отладкой и тестами. Прошла уже почти неделя, код так и не представлен. А Вы заявляли о 20 минутах.
     
  3. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Добавлять в дерево тоже можно без выделения памяти:

    Код (Text):
    1. template <
    2.    class Key,
    3.    class Type,
    4.    class Traits = less<Key>,
    5.    class Allocator=allocator<pair <const Key, Type> >
    6. >
    7. class map
    Создайте свой аллокатор в котором преалоцируйте память.
     
  4. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Да легко. Это стандартная техника для выделения памяти фиксированными кусками. 8 байт на два size_t, которые нужно хранить, еще 4 байта на указатель next для хэш-таблицы. Нужная память выделяется одним блоком размером 12*N байт, указатели next выставляются так, что образуют список свободных блоков. Когда надо выделить 12 байт - берется блок из начала списка, когда надо вернуть 12 байт - добавляется блок в начало списка. Список использует те же (физически) указатели, что и хэш-таблица, перерасхода памяти нет. Выделение и освобождение памяти гарантированно выполняются за константное время, что гораздо лучше стандартной кучи, которая может фрагментироваться.

    Собственно сам блок:
    Код (Text):
    1. struct SBlock
    2. {
    3.   size_t first;
    4.   size_t second;
    5.   SBlock *next;
    6. };
    Инициализация (для примера - N блоков):
    Код (Text):
    1. SBlock *blocks = new SBlock[N];
    2. SBlock *list_begin = blocks;
    3. for (int i = 0; i < N - 1; ++i)
    4.   blocks[i].next = &blocks[i + 1];
    5. blocks[N - 1].next = 0;
    Выделение памяти:
    Код (Text):
    1. SBlock* get_block()
    2. {
    3.   SBlock *result = list_begin;
    4.   if (!result)
    5.   {
    6.     // по хорошему тут должно быть выделение нового массива блоков
    7.     return 0;
    8.   }
    9.   list_begin = list_begin->next;
    10.   return result;
    11. }
    Освобождение памяти:
    Код (Text):
    1. void free_block(SBlock *block)
    2. {
    3.   block->next = list_begin;
    4.   list_begin = block;
    5. }
    P.S. Аллокатор написал не в stl-совместимом виде, чтобы было понятней.
     
  5. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Atlantic это обычный односвязный список. Вставка/поиск в таком списке будет производиться за время ~n. Дерево даёт возможность вставлять за время ~ln(n). Где же тут бОльшая эффективность?
     
  6. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    srm
    Ну хоть прочитать надо, что я написал. Это список для быстрого и эффективного выделения памяти. Или может еще и хэш-таблицу написать?
     
  7. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Конечно же нужен алгоритм вставки/удаления/поиска в мапе. Меня интересует именно мапа, зачем мне работа с памятью?

    Вам нужно было прочитать название темы.
     
  8. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    srm
    Мне перепечатать код из учебника по алгоритмам, чтобы доказать, что я знаю как пишется хэш-таблица что-ли? Как то не хочется тратить время. Тем более что в реальном проекте я напишу stdext::hash_map<size_t, size_t> и не буду заморачиваться.
     
  9. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    У меня есть сомнения, что мапу size_t -> size_t можно реализовать через хеш таблицу (в смысле, эффективно реализовать - эффективней, чем красно-чёрное дерево).

    Там же 20 минут вместе с отладкой и примерами! Вы больше времени тратите на дискуссию.
     
  10. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    У меня нет сомнений.

    Хэш-таблицы как бы по умолчанию умеют справляться с коллизиями. Либо списки элементов с одинаковым хэшем, либо двойное хэширование.
     
  11. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Кто-то меня только что убеждал, что stl - ацтой, лучше писать свой велосипед. Зачем же Вы его собираетесь юзать?
     
  12. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Это был не я, ахахаа :) На первой странице мои посты посмотри.
     
  13. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Молодец, возьми конфетку с полки.

    Значит Вы плохо знаете теорию алгоритмов.

    Да, справляются. Но как это влияет на время работы с мапой? Отсюда и мои сомнения. Подбирать хеш функцию для случайного size_t - гиблое дело. Заранее могу сказать лишь то, что диапазон изменения параметра - от 0x00000000 до 0x7FFFFFFF.
     
  14. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Знаю хорошо. Хэш-таблицы асимптотически быстрее красно-черных деревьев, плюс у красно-черных деревьев медленная вставка и удаление (с большими константами перед logN).

    Зависит от процента заполненности хэш-таблицы и ее типа. Если хэш-таблица разрешает коллизии списками и заполнена примерно на 100%, то средняя длина списка равна 1 и про коллизии можно не вспоминать вообще.

    Ах, вот оно что. Не так уж и сложно подобрать.

    F(X) = (X * 0x8088405 + 1) % N, где N (простое число) - размер таблицы
     
  15. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    size_t вообще-то беззнаковый. 0x00000000-0xFFFFFFFF
     
  16. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Плохо знаете. Это только в случае идеальной хеш-функции.

    А почему Вы так уверены, что будет именно так?

    Давайте посчитаем скорость поиска при разумном N и оверхед по памяти.
     
  17. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    и что?
     
  18. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Память я уже написал - 12*N байт + K*4 байт для собственно хэш-таблицы (указатели на начало списков), если K - размер таблицы, N - число хранимых элементов. Скорость поиска - сферический конь в вакууме. Зависит от компилятора, его настроек, реализации хэш-таблицы и дерева. Про асимптотику я уже сказал. Хэш-таблицы быстрее любых деревьев. Про вырожденные случаи типа корявой хэш-функции или специально подобранных данных под хэш-функцию я вообще не посчитал нужным упоминать раньше, это должно быть и так очевидным.
     
  19. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Подставьте конкретные числа и убедитесь, что никакого выигрыша ни в производительности, ни по памяти нет. Да и при чём здесь компилятор, посчитайте сложность алгоритма! Какое количество операций необходимо?

    Вот именно - это очевидно. Если я говорю про мапу size_t -> size_t, то очевиден диапазон изменения ключа. Вы же навязываете хеш таблицу, прекрасно понимая, что практической пользы от хеш таблицы при изменении аргумента в пределах от 0 до 0x7FFFFFFF нет никакой. Тут подбери какую угодно хеш функцию - будет дофига коллизий, а значит и сложность алгоритма будет приближаться к ~n.
     
  20. srm

    srm New Member

    Публикаций:
    0
    Регистрация:
    14 июн 2011
    Сообщения:
    189
    Нужно понимать ситуации когда они действительно быстрее. У меня явно не такая ситуация.