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
От: ArtDenis Россия  
Дата: 22.04.04 03:24
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К> ...

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

Ну, ну...

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

Оператор == в хеш-контейнере нужен лишь для того, чтобы диагностировать коллизию.
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...
Пока на собственное сообщение не было ответов, его можно удалить.