Re[3]: нужно написать свой hash_map
От: ArtDenis Россия  
Дата: 22.04.04 03:24
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К> ...

К> А отношение равенства не позволяет однозначно сортировать. Это означает,
К> что поиск будет не двоичный, а линейный.

Ну, ну...

Вообще-то в хеш-таблице поиск должен осуществлятся почти за константное время (время вычисления хеш-функции). Исключения составляют коллизии, но их можно не учитывать.

Оператор == в хеш-контейнере нужен лишь для того, чтобы диагностировать коллизию.
Posted via RSDN NNTP Server 1.8 beta
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 10:33
Оценка:
Необходимо разработать ассоциативный контейнер hash_map<Key, Data, HashFcn, Equal, Alloc> который будет ассоциировать
объект типа Key с объектом типа Data. Интерфейс этого контейнера должен быть аналогичным к STL map,
только оператор < должен быть заменен оператором ==

я уже не знаю за что взятся.

а что если его реализовать класами.
Re: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 10:57
Оценка:
Здравствуйте, eBit, Вы писали:

B>Необходимо разработать ассоциативный контейнер hash_map<Key, Data, HashFcn, Equal, Alloc> который будет ассоциировать

B>объект типа Key с объектом типа Data. Интерфейс этого контейнера должен быть аналогичным к STL map,
B>только оператор < должен быть заменен оператором ==

B>я уже не знаю за что взятся.


Скопировать из какого-нибудь STL Только избавиться от ассоциативных контейнеров, заменив там логарифмический поиск линейным.

B>а что если его реализовать класами.


В смысле?
Перекуём баги на фичи!
Re: нужно написать свой hash_map
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 21.04.04 11:02
Оценка:
Здравствуйте, eBit, Вы писали:

B>Необходимо разработать ассоциативный контейнер hash_map<Key, Data, HashFcn, Equal, Alloc> который будет ассоциировать

B>объект типа Key с объектом типа Data. Интерфейс этого контейнера должен быть аналогичным к STL map,

B>только оператор < должен быть заменен оператором ==

Тогда он не будет аналогичен STL map.
STL map для сравнения использует отношение эквивалентности по отношению к порядку сортировки:
два элемента считаются эквивалентными по отношению к порядку сортировки, используемому ассоциативным контейнером, если ни один из них не предшествует другому в данном порядке сортировке. Если перевести на C++, то объекты x и y эквиваленты, если выражение !(x F y) && !(y F y) истоно, где F — функция сравнения. Обычно в качестве данной функции используется <. Но никогда нельзя использовать ==!!! Вот почему: !(x == x) && !(x == x) = !(true) && !(true) = false && false = false !!! .. То есть, если в качестве функции сравнения использовать ==, имеем что объект не эквивалентен сам себе .

B>я уже не знаю за что взятся.

Возьми готовую реализацию — их море
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re: нужно написать свой hash_map
От: ArtDenis Россия  
Дата: 21.04.04 11:21
Оценка:
Здравствуйте, eBit, Вы писали:

e> Необходимо разработать ассоциативный контейнер hash_map<Key, Data,

e> HashFcn, Equal, Alloc>

В STLPort есть такая вещь как std::hash_map, её и используй.
Posted via RSDN NNTP Server 1.8 beta
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 11:22
Оценка:
Здравствуйте, Mr. None, Вы писали:

MN>Возьми готовую реализацию — их море

у меня была идея видрать с STLPort, но посмотрев в код, а там ище всего много подключаетса.


а на счет реализовать класами:
так взять написать "список <ключ ,значение>", hash_table, и уже сам hash_map.
на даный момент работает такой вариант. есть некоторые глюки. но зато свое
Re[2]: нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 11:25
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, eBit, Вы писали:


e>> Необходимо разработать ассоциативный контейнер hash_map<Key, Data,

e>> HashFcn, Equal, Alloc>

AD>В STLPort есть такая вещь как std::hash_map, её и используй


тогда мне приедетса с кодом программы ище и STLPort передавать.
Re[3]: нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 11:27
Оценка:
кстати
я пишу на Visual C++ 6
Re[3]: нужно написать свой hash_map
От: Bell Россия  
Дата: 21.04.04 11:33
Оценка:
Здравствуйте, eBit, Вы писали:

B>Здравствуйте, ArtDenis, Вы писали:


AD>>Здравствуйте, eBit, Вы писали:


e>>> Необходимо разработать ассоциативный контейнер hash_map<Key, Data,

e>>> HashFcn, Equal, Alloc>

AD>>В STLPort есть такая вещь как std::hash_map, её и используй


B>тогда мне приедетса с кодом программы ище и STLPort передавать.


А что в этом плохого?
Или ты всерьез полагаешь, что твоя реализация будет лучше?
Любите книгу — источник знаний (с) М.Горький
Re[4]: нужно написать свой hash_map
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 21.04.04 11:42
Оценка:
Здравствуйте, eBit, Вы писали:

B>кстати

B>я пишу на Visual C++ 6

Вот-вот... поставь хотябы M$VC 7.0 — там уже есть готовый hash_map
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[5]: нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 11:47
Оценка:
Здравствуйте, Mr. None, Вы писали:
MN>Вот-вот... поставь хотябы M$VC 7.0 — там уже есть готовый hash_map

я уже знаю что в 7 есть, но прикол в том, что у меня задание написать на 6.



на счет STLPort, реально с него взять сам hash_map не используя весь STLPort?? (точнее что бы его не ставить всего)
Re[2]: нужно написать свой hash_map
От: ArtDenis Россия  
Дата: 21.04.04 11:56
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Скопировать из какого-нибудь STL Только избавиться от ассоциативных контейнеров, заменив там логарифмический поиск линейным.


Ага, написать эмулятор красно-чёрного дерева, который будет отображать "виртуальное" дерево на реальную хеш-таблицу
... << RSDN@Home 1.1.2 stable >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[6]: нужно написать свой hash_map
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 21.04.04 12:00
Оценка:
Здравствуйте, eBit, Вы писали:

B>я уже знаю что в 7 есть, но прикол в том, что у меня задание написать на 6.


B>на счет STLPort, реально с него взять сам hash_map не используя весь STLPort?? (точнее что бы его не ставить всего)

В принципе реально, если выкачаешь все потребные ему файлы, хотя я этим не занимался...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[2]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 12:25
Оценка:
Тупой эскиз
template<class K, class V, class HK, class HF>
class hashmap
{
public:
  typedef K key_type;
  typedef V value_type;
  typedef HK hash_type;
  typedef HF hash_function;

  typedef pair<const key_type, value_type> data_type;

  typedef list<data_type> datalist_type; // данные с одинаковым хешем сгруппированы подряд
private:
  typedef pair<hash_value, datalist_type::iterator> hash_entry;
  typedef list<hash_entry> hashlist_type;

  hash_function hf_;
  hashlist_type hl_;
  datalist_type dl_;

  struct hashfinder
  {
    hash_type h_; // хеш имеет смысл хранить по значению (он маленький)
    hashfinder(hash_type h) : h_(h) {}
    bool operator()(const hash_entry& e) const { return e.first == h_; } // <-- здесь компаратор хеша
  };
  struct keyfinder
  {
    const key_type& k_; // ... а ключ - по ссылке (скорее всего, он большой)
    findhash(const key_type& k) : k_(k) {}
    bool operator()(const data_type& d) const { return d.first == k_; } // <-- здесь компаратор ключа
  };

public:
  typedef datalist_type::iterator iterator;
  typedef datalist_type::const_iterator const_iterator

  iterator find(const key_type& k) // также - версия const
  {
    hash_type h = hf_(k);
    hashlist_type::iterator hli = find_if(hl_.begin(), hl_.end(), hashfinder(h));
    if(hli == hl_.end()) return dl_.end();
    datalist_type::iterator dli = find_if(hl_.second, dl_.end(), keyfinder(k));
  }

  pair<iterator,bool> insert(const key_type& k, const value_type& v)
  {
    hash_type h = hf_(k);
    hashlist_type::iterator hli = find_if(hl_.begin(), hl_.end(), findhash(h));
    if(hli == hl_.end()) // новый хэш
    {
      datalist_type::iterator dli = dl_.insert(dl_.end(), data_type(k,v)); // добавим запись
      hl_.push_back(make_pair<h,dli>); // и добавим хеш
      return make_pair<dli,true>;
    }
    datalist_type::iterator dli = hli.second;
    hashlist_type::iterator hle = hli; ++hle;
    datalist_type::iterator dle = (hle == hl_.end()) ? dl_.end() : hle.second);
    dli = find_if(dli, dle, keyfinder(k));
    if(dli != dle) // ключ найден
      return make_pair<dli,false>;
    dli = dl_.insert(dle, data_type(k,v)); // добавим запись в конец отрезка коллизий
    return make_pair<dli,true>;
  }

  value_type& operator[](const key_type& k) // const недоступен
  {
    static value_type defvalue; // чтобы не конструировать дефолты каждый раз
    return insert(k,defvalue).first.second;
  }
};
Перекуём баги на фичи!
Re[3]: нужно написать свой hash_map
От: A_l_e_x_e_y Россия  
Дата: 21.04.04 13:10
Оценка:
Здравствуйте, eBit, Вы писали:

AD>>В STLPort есть такая вещь как std::hash_map, её и используй

B>тогда мне приедетса с кодом программы ище и STLPort передавать.
А в STL'е для MSVC2003 уже есть свой hach_map и можно не заморачиваться
... << RSDN@Home 1.1.3 stable >>
Re[3]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 13:17
Оценка:
Здравствуйте, ArtDenis, Вы писали:

К>>Скопировать из какого-нибудь STL Только избавиться от ассоциативных контейнеров, заменив там логарифмический поиск линейным.


AD>Ага, написать эмулятор красно-чёрного дерева, который будет отображать "виртуальное" дерево на реальную хеш-таблицу


Нет. КЧД, будучи ДДП (двоичным деревом поиска), требует введения строгого порядка.
А по заданию — дано только отношение равенства.

Для линейного поиска необходим и достаточен любой линейный контейнер. В данном случае лучше всего — два списка.

Если над хэшами можно ввести строгий порядок — то получим список и мап, или мап списков.
Если пространство хэшей невелико и отображается на сплошной отрезок целых чисел — то вместо мапа можно использовать вектор.
Перекуём баги на фичи!
Re: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 13:27
Оценка:
Здравствуйте, eBit, Вы писали:

B>Необходимо разработать ассоциативный контейнер hash_map<Key, Data, HashFcn, Equal, Alloc>...


Тебе потребуется ещё тип хеш-значений. Может быть, его можно вывести из типа HashFcn — но не факт: в общем случае это наложит неоправданные ограничения на параметры шаблона.

Далее, существует ли строгий порядок над хеш-значениями — или тоже только равенство?
Заданы ли эти отношения операторами < и == соответственно?

STL-ные аллокаторы уже параметризованы; тебе потребуется как минимум два аллокатора, причём параметризованные внутренними типами.
Поэтому, наверное, можно потребовать, чтобы Alloc был моделью обобщённого аллокатора (с шаблонными членами), а не STL-аллокатора.
struct general_allocator
{                                                    // типовая реализация
  template<class T> T* allocate() const              { return new T(); }
  template<class T> T* duplicate(const T& src) const { return new T(src); }
  template<class T> void deallocate(T* obj) const    { delete obj; }
};
Перекуём баги на фичи!
Re[2]: нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 13:44
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Тебе потребуется ещё тип хеш-значений. Может быть, его можно вывести из типа HashFcn — но не факт: в общем случае это наложит неоправданные ограничения на параметры шаблона.


тип хеш-значения будет целое число, я имею опредиленый тип даних для сохранения, это будет string, ключ я тоже беру string.

К>Далее, существует ли строгий порядок над хеш-значениями — или тоже только равенство?

К>Заданы ли эти отношения операторами < и == соответственно?

я даже не знаю, что за оператор мне нужно заменить.


В шаблонах я не силен, только расбираюсь. И литературы мало по них я нахожу где на пальцах все расказано (на руском).
Уж немало всего разобрал, но как много ище осталось.
Re[3]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 14:18
Оценка:
Здравствуйте, eBit, Вы писали:

К>>Тебе потребуется ещё тип хеш-значений. Может быть, его можно вывести из типа HashFcn — но не факт: в общем случае это наложит неоправданные ограничения на параметры шаблона.


B>тип хеш-значения будет целое число, я имею опредиленый тип даних для сохранения, это будет string, ключ я тоже беру string.


К>>Далее, существует ли строгий порядок над хеш-значениями — или тоже только равенство?

К>>Заданы ли эти отношения операторами < и == соответственно?

B>я даже не знаю, что за оператор мне нужно заменить.


Для string определёны операторы < и ==, чем они тебе не понравились?

B>В шаблонах я не силен, только расбираюсь. И литературы мало по них я нахожу где на пальцах все расказано (на руском).

B>Уж немало всего разобрал, но как много ище осталось.

Кстати, о хеше.
Пространство целых чисел имеет мощность INT_MAX. Поэтому, при хорошей хеш-функции, ты будешь иметь коллизии с очень маленькой вероятностью. Поэтому делать двухступенчатый контейнер будет столь же накладно, как и одноступенчатый. Всё равно подребуется двоичный поиск, всё равно это будет КЧ дерево...
Максимальный выигрыш от хеша можно достичь, когда мощность пространства хешей — примерно квадратный корень от ожидаемой мощности множества ключей.

Заодно я придумал обходное решение: в качестве ключа использовать не строку, а строку+хеш.
struct hashstring
{
  string str;
  int hash;

  hashstring() : str(), hash(0) {}
  hashstring(const string& s) : str(s), hash(hashfunc(s)) {}
};

bool operator < (const hashstring& l, const hashstring& r)
{
  if(l.hash < r.hash) return true;
  if(r.hash < l.hash) return false;
  // хеши совпали - проверим строки
  if(l.str < r.str) return true;
  return false; // l >= r
}
// остальные операторы определяются через оператор <
// впрочем, для map достаточно только его

/////////
map<hashstring, my_value_type> my_table;

То есть мы ничего не меняем в структурах данных (как был мап на КЧД, так и остался), но существенно ускоряем поиск: все сравнения проходят в первую очередь по хешу (быстро), и только затем, в случае коллизии, — по строке (медленно).
Побочный эффект — кажущаяся неотсортированность такого мапа.
Точнее, он отсортирован по hashstring, чей порядок существенно отличается от алфавитного.

При желании — можешь обобщить этот приём, создав класс, который содержит внутри такой мап.
template<class K, class V, class HF>
class hashtable
{
private:
  struct hashkey
  {
    int h_;
    K k_;
    hashkey() : h_(0) {}
    hashkey(int h, K k) : h_(h), k_(k) {}

    bool operator< (const hashkey& r) const { ..... }
  };
  map<hashkey, V> cont_;
  HF hf_;

public:
  hashtable() {}
  hashtable(HF hf) : hf_(hf) {}

  bool empty() const { return cont_.empty(); }
  void clear() { cont_.clear(); }

  V& operator[](const K& k) const
  {
    return cont_[hashkey(hf_(k),k)];
  }
  bool exist(const K& k) const
  {
    return cont_.find(hashkey(hf_(k),k)) != cont_.end();
  }
  // а итераторы пусть погуляют.
};
Перекуём баги на фичи!
Re[4]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 14:34
Оценка:
К>Максимальный выигрыш от хеша можно достичь, когда мощность пространства хешей — примерно квадратный корень от ожидаемой мощности множества ключей.

Последнее, наверно, требует некоторых комментариев.

Немного математики:

Мощность пространства хешей h, мощность множества ключей k.
Среднее количество ключей с одинаковым хешем c = max(1, k/h).

Время поиска T = Th(h) * Tk(c), где Th — поиск хешей, Tk — поиск ключей в множестве коллизий данного хеша.

Если таблица хешей имеет произвольный доступ (что возможно при h гораздо меньшем чем 2^32),
O(T) = O(1) * O(Tk(c)) = O(Tk(k/h)).
Тут очевидно, что чем больше h, тем лучше. И всё упирается в цену памяти.

Если же поиск логарифмический (при большом h)
O(T) = O(log h) * O(Tk(k/h)) = O(log(h) * Tk(k/h)).

Допустим, поиск по коллизиям линейный, O(Tk(k/h)) == O(k/h)
O(T) = O(log(h)/h * k)
Снова понятно, что чем больше h, тем лучше: log(h)/h убывает.

Наконец, если поиск по коллизиям логарифмический,
O(T) = O(log(h) * log(k/h)) = O(log(h) * (log(k) — log(h)))
то минимум будет при

x = log(h)
y = log(k)

f = x*(y-x) = xy — x^2
f' = y — 2x
f'==0, x = y/2
log(h) = log(k)/2 = log(k^(1/2))
h = sqrt(k)

что и требовалось показать.
Перекуём баги на фичи!
Re: нужно написать свой hash_map
От: eBit Украина  
Дата: 21.04.04 14:54
Оценка:
... STL map, только оператор < должен быть заменен оператором ==

а как это понять, в чем суть, скажите ...
Re[2]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 15:28
Оценка:
Здравствуйте, eBit, Вы писали:

B>... STL map, только оператор < должен быть заменен оператором ==


B>а как это понять, в чем суть, скажите ...


Какой мексиканский негодяй тебе дал такое задание — вот у него и спроси, что он имел в виду.

STL-ные ассоциативные контейнеры (set, map, multiset, multimap) требуют, чтобы над элементами существовало отношение строгого порядка.
Как, впрочем, любые сортированные контейнеры. Потому что только на сортированном контейнере можно осуществлять двоичный поиск.

А отношение равенства не позволяет однозначно сортировать. Это означает, что поиск будет не двоичный, а линейный.

Как сделать хеш-контейнер с линейным поиском из STL-ных деталек — я уже выше показывал.
Перекуём баги на фичи!
Re[5]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 21.04.04 20:04
Оценка:
К>Мощность пространства хешей h, мощность множества ключей k.
К>Среднее количество ключей с одинаковым хешем c = max(1, k/h).

К>Время поиска T = Th(h) * Tk(c), где Th — поиск хешей, Tk — поиск ключей в множестве коллизий данного хеша.


Дурня свалял.

Конечно же, T = Th + Tk.
Поэтому все последующие формулы — прошу считать инсинуациями.
... << RSDN@Home 1.1.2 stable >>
Перекуём баги на фичи!
Re[3]: нужно написать свой hash_map
От: Dog  
Дата: 21.04.04 20:29
Оценка:
B>В шаблонах я не силен, только расбираюсь. И литературы мало по них я нахожу где на пальцах все
B>расказано (на руском).
B>Уж немало всего разобрал, но как много ище осталось.
Псмотри вот эту книгу
Автор(ы): Дэвид Вандевурд, Николаи М. Джосаттис

Шаблоны C++ представляют собой активно развивающуюся часть языка программирования, предоставляющую программисту новые возможности быстрой разработки эффективных и надежных программ и повторного использования кода. Данная книга, написанная в соавторстве теоретиком C++ и программистом-практиком с большим опытом, удачно сочетает строгость изложения и полноту освещения темы с вопросами практического использования шаблонов. В книге содержится масса разнообразного материала, относящегося к программированию с использованием шаблонов, в том числе материал, который даст опытным программистам возможность преодолеть современные ограничения в этой области. Книга предполагает наличие у читателя достаточно глубоких знаний языка C++; тем не менее стиль изложения обеспечивает доступность материала как для квалифицированных специалистов, так и для программистов среднего уровня.

Правда твоей задачи там нет
... << RSDN@Home 1.1.3 stable >>
Re[3]: нужно написать свой hash_map
От: Павел Кузнецов  
Дата: 22.04.04 03:13
Оценка:
> А отношение равенства не позволяет однозначно сортировать. Это означает, что поиск будет не двоичный, а линейный.

Ничего страшного: в том же STLport hash_[multi](map|set) используют именно равенство в качестве функции сравнения
Posted via RSDN NNTP Server 1.8 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: нужно написать свой hash_map
От: eBit Украина  
Дата: 06.05.04 07:36
Оценка:
Здравствуйте, Кодт, Вы писали:
некоторый код из вашего эскиза.


Как вам такой хеш мап
Скажите свок ФЕ, и что можна добавить, улучшить.

template <class _Key, class _Val , class _HashFcn>
class hash_map {
  private:
    datalist_type   _dl;   // список всех пар
    hash_table_type _hl; // хаш таблиця для пар
    hash_function   _hf;
    int data_capacity;   // количество сохраненых елементов
    
  public:
    typedef _Key     key_type;
    typedef _Val     value_type;
    typedef _HashFcn hash_function;
    typedef size_t   hash_type;


    typedef std::pair<key_type, value_type> data_type;       
    typedef std::list<data_type*>           datalist_type;   // пары с однаковым хешом
    typedef std::vector<datalist_type>      hash_table_type;

    typedef hash_table_type::iterator iterator;
    typedef hash_table_type::reverse_iterator reverse_iterator;

    typedef datalist_type::iterator   iterator_list;



//----------------------------------------
    hash_map() {
       _hl.resize(100);
       data_capacity = 0;
    }

//----------------------------------------
    std::pair<iterator, bool> insert(const key_type& k, const value_type& v) {
      hash_type h_ = _hf(k, _hl.capacity() );
      
      data_type *dt_;
      
      iterator hli_;

      hli_ = _hl.begin() + h_ - 1;

      
      if( !hli_ -> empty() ) { 
        // ключ в хаш таблице с таким хешом уже есть
        // сомотрим разные ли ключи
        iterator_list dli_ = find_if( hli_ -> begin(), hli_ -> end(), keyfinder( k )); 

        if( dli_ != (hli_ -> end()) )
        {
          iterator hli_end = _hl.end();
          return pair<iterator, bool>(hli_end, false);
        }
      }

      dt_ = new data_type;
      dt_ -> first = k;
      dt_ -> second = v;

      _dl.push_back(dt_);  
      hli_ -> push_back(dt_);

      data_capacity++;
      return pair<iterator, bool>(hli_,true);
    }

//----------------------------------------
    iterator find(const key_type& k) {
      iterator hli_;
      
      hash_type h_ = _hf(k, _hl.capacity() );

      hli_ = _hl.begin() + h_ - 1;

      bool tr =  hli_ -> empty();

      if( tr == 1 ) 
         return NULL;

      return hli_;
    }

//----------------------------------------
    iterator begin() {
      return _hl.begin();
    }

    iterator end() {
      return _hl.end();
    }

    reverse_iterator rbegin() {
      return _hl.rbegin()
    }

    reverse_iterator rend() {
      return _hl.rend();
    }

//----------------------------------------

    size_t size() {
      return data_capacity;
    }

    size_t capacity() {
      return _hl.capacity();
    }
//----------------------------------------
    void clear()
    {
    }

    
//----------------------------------------

    datalist_type* operator[](const key_type& k) {   
      hash_type h_ = _hf(k, _hl.capacity() );

      return &_hl[h_- 1];
    }


  private:
    void rehash() { 
    };


    struct keyfinder {
      const key_type& k_;
      keyfinder(const key_type& k) : k_(k) {}
      bool operator()(const data_type* d) const { 
       return d->first == k_; 
      }
    };


};
Re[6]: нужно написать свой hash_map
От: maq Россия http://www.maqdev.com
Дата: 06.05.04 11:00
Оценка:
B>на счет STLPort, реально с него взять сам hash_map не используя весь STLPort?? (точнее что бы его не ставить всего)

Мне кажется проще взять из Dinkumware, у него и исходник куда более читабельный имхо.
Re[7]: нужно написать свой hash_map
От: eBit Украина  
Дата: 06.05.04 11:26
Оценка:
Здравствуйте, maq, Вы писали:

maq>Мне кажется проще взять из Dinkumware, у него и исходник куда более читабельный имхо.


Ве эти исходники очень большие, читал я их, достали они меня, но зато много интересного нашел.
Самое интересное — мне нужно спмому написать hash_map, а не передрать.
... << RSDN@Home 1.1.3 stable >>
Re[4]: нужно написать свой hash_map
От: Кодт Россия  
Дата: 09.05.04 22:02
Оценка:
Здравствуйте, eBit, Вы писали:

B>Как вам такой хеш мап

B>Скажите свок ФЕ, и что можна добавить, улучшить.

B>
B>template <class _Key, class _Val , class _HashFcn>
B>class hash_map {
B>  private:
B>    datalist_type   _dl;   // список всех пар
B>    hash_table_type _hl; // хаш таблиця для пар
B>    hash_function   _hf;
B>    int data_capacity;   // количество сохраненых елементов
    
B>  public:
B>    typedef _Key     key_type;
B>    typedef _Val     value_type;
B>    typedef _HashFcn hash_function;
B>    typedef size_t   hash_type;


B>    typedef std::pair<key_type, value_type> data_type;       
B>    typedef std::list<data_type*>           datalist_type;   // пары с однаковым хешом
B>    typedef std::vector<datalist_type>      hash_table_type;

Получается, у тебя есть один список всех элементов (_dl) и ещё отдельно списки коллизий (_hl) ?
Да ещё и совместное владение элементами (хранящимися по указателям).
А нафига, раскрой секрет.

На мой взгляд, удобнее иметь список элементов (отсортированный по хешу) и таблицу итераторов.
Для отдельного, искушённого пользователя можно сделать итерирование по хешам. Но вообще это не имеет смысла.

B>    typedef hash_table_type::iterator iterator;
B>    typedef hash_table_type::reverse_iterator reverse_iterator;

B>    typedef datalist_type::iterator   iterator_list;

Вот тебе уже пришлось ввести два разных типа итераторов — один на домене хештаблицы, а другой — на домене списка-помойки.
Кстати, если уж давать имя, то не iterator_list (список итераторов), а list_iterator (итератор списка).

B>//----------------------------------------
B>    hash_map() {
B>       _hl.resize(100);
B>       data_capacity = 0;
B>    }

По некоторым соображениям, лучше использовать хеш с размером, равным простому числу. Достигается лучшее перемешивание. (Подробности — у Кнута; я, к сожалению, не вчитывался, а сейчас книги нет).


B>//----------------------------------------
B>    std::pair<iterator, bool> insert(const key_type& k, const value_type& v) {
B>      hash_type h_ = _hf(k, _hl.capacity() );
      // только, наверное, не capacity(), а size() ?
B>      data_type *dt_;
      
B>      iterator hli_;

B>      hli_ = _hl.begin() + h_ - 1;

      
B>      if( !hli_ -> empty() ) { 
B>        // ключ в хаш таблице с таким хешом уже есть
B>        // сомотрим разные ли ключи
B>        iterator_list dli_ = find_if( hli_ -> begin(), hli_ -> end(), keyfinder( k )); 

B>        if( dli_ != (hli_ -> end()) )
B>        {
B>          iterator hli_end = _hl.end();
B>          return pair<iterator, bool>(hli_end, false);
B>        }
B>      }

B>      dt_ = new data_type;
B>      dt_ -> first = k;
B>      dt_ -> second = v;

B>      _dl.push_back(dt_);  
B>      hli_ -> push_back(dt_);

B>      data_capacity++;
B>      return pair<iterator, bool>(hli_,true);
B>    }

B>//----------------------------------------
B>    iterator find(const key_type& k) {
B>      iterator hli_;
      
B>      hash_type h_ = _hf(k, _hl.capacity() );

B>      hli_ = _hl.begin() + h_ - 1;

B>      bool tr =  hli_ -> empty();

B>      if( tr == 1 ) 
B>         return NULL;

B>      return hli_;
B>    }

B>//----------------------------------------
B>    iterator begin() {
B>      return _hl.begin();
B>    }

B>    iterator end() {
B>      return _hl.end();
B>    }

B>    reverse_iterator rbegin() {
B>      return _hl.rbegin()
B>    }

B>    reverse_iterator rend() {
B>      return _hl.rend();
B>    }

B>//----------------------------------------

B>    size_t size() {
B>      return data_capacity;
B>    }

B>    size_t capacity() {
B>      return _hl.capacity();
B>    }

Ты определись — соблюдаешь ли конвенции STL или нет. Потому что иначе — это бардак.
Заодно выясни, в чём разница между size() и capacity()


B>//----------------------------------------
B>    void clear()
B>    {
B>    }

    
B>//----------------------------------------

B>    datalist_type* operator[](const key_type& k) {   
B>      hash_type h_ = _hf(k, _hl.capacity() );

B>      return &_hl[h_- 1];
B>    }

Очень весело! Мне по ключу выдают список элементов, где я ещё и должен искать этот ключ. Ладно бы эти элементы были логически сгруппированы (и имел бы смысл такой "нечёткий запрос" — как, например, std::multiset/multimap). Так ведь нет — элементы перемешаны! То есть их объединение — исключительная прихоть судьбы в виде хеш-функции.


B>  private:
B>    void rehash() { 
            // а это что?
B>    };


B>    struct keyfinder {
B>      const key_type& k_;
B>      keyfinder(const key_type& k) : k_(k) {}
B>      bool operator()(const data_type* d) const { 
B>       return d->first == k_; 
B>      }
B>    };


B>};
B>


Итого,
... << RSDN@Home 1.1.2 stable >>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.