Advertisement
Guest User

hashmap.h

a guest
Jan 21st, 2013
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.11 KB | None | 0 0
  1. #ifndef HASHMAP_H
  2. #define HASHMAP_H
  3.  
  4. #include <ctype.h>  //isalnum()
  5. #include <fstream>  //obsluga plikow
  6. #include <string>
  7. #include <iterator>
  8. #include <utility>
  9. #define HASH_SIZE 64000         //wielkosc tablicy hashujacej
  10. #include <iostream>
  11. using namespace std;
  12. void otwieranie_pliku(string nazwa);
  13. template <class Key>
  14. inline int  _compFunc(const Key& key1,const Key& key2) //funkcja sprawdza, czy klucze sa rowne
  15. {
  16.    return (key2!=key1);
  17. };
  18.  
  19. template <class K>
  20. inline unsigned int hashF(const K &hash)
  21. {   unsigned int baza = 5381; //liczba pierwsza, dobra do hashowania, metoda DJB
  22.     const char *klucz = hash.c_str();
  23.     int znak;
  24.     while(znak=*klucz++) baza= ((baza <<5)+baza)+znak;
  25.     return baza % HASH_SIZE; //zeby nie wyskoczyc poza obszar tablicy hashujacej
  26. };
  27. ///Mapa podobna do STLowej
  28. template<class K, class V,
  29.          unsigned int hashFunc(const K&),
  30.          int compFunc(const K&,const K&)=&_compFunc<K> >
  31. class HashMap
  32. {
  33.  
  34.     struct Cell
  35.     {
  36.       pair<K,V> data;       //zawiera klucz i wartosc (Key, Value)
  37.       Cell *next;
  38.       Cell *prev;
  39.       unsigned int hash;
  40.  
  41.       Cell(){};             //konstruktor
  42.       Cell(const struct Cell &n) : data(n.data), next(n.next), prev(n.prev) {}; //kopiujacy
  43.       Cell(const pair<K, V> d, Cell *n = NULL, Cell *p = NULL) :
  44.            data(d), next(n), prev(p) {};
  45.     };
  46.  
  47.  
  48.       unsigned int map_size;
  49.       Cell *sentinel;          //wskaznik na sentinela
  50.  
  51. public:
  52.    typedef pair<K, V> T;
  53.  Cell *tablica_hash[HASH_SIZE];  //tworzymy tablice hashujaca////////////////////////////////////wrzuc do priva
  54.    HashMap(): map_size(0)
  55.     { sentinel=new Cell (make_pair(K(), V()));    //ustawienie sentinela
  56.       sentinel->next = sentinel;
  57.       sentinel->prev = sentinel;
  58.       sentinel->hash = 0;
  59.  
  60.       Cell **ptr = tablica_hash;                     //tworzymy wskaznik na pierwszy element tablicy hashujacej
  61.       for(int i=0; i<HASH_SIZE; ++i) *(ptr++)=NULL;  //i ustawiamy wszystkie elementy na NULL
  62.     }
  63.  
  64.    ~HashMap()
  65.     { Cell *tmp = sentinel->next;
  66.       while(tmp !=sentinel){tmp = tmp->next; delete(tmp->prev);} // usuwamy kazdy element hashtabla
  67.  
  68.       delete(sentinel); //na koniec sprzatamy po sobie kasujac sentinela
  69.     };
  70.  
  71.    /// Coping constructor.
  72.    explicit HashMap(const HashMap<K, V, hashFunc, compFunc>& a)
  73.     { sentinel = new Cell(make_pair(K(), V()));
  74.       sentinel->hash=0; //ustawiamy sentinela
  75.  
  76.        map_size = a.map_size;  //ustawiamy ilosc elementow
  77.       Cell **ptr = tablica_hash;
  78.       for(int i=0; i<HASH_SIZE; ++i) *(ptr++)= NULL;
  79.  
  80.       Cell *tmp = sentinel;
  81.       Cell *tmp2 = a.sentinel->next;
  82.      unsigned int prev_hash = tmp2->hash;
  83.  
  84.     for(;tmp2!=a.sentinel; tmp = tmp->next, tmp2=tmp2->next)
  85.         {tmp->nast = new Cell(tmp2->data, NULL, tmp);
  86.          tmp->nast->hash = tmp2->hash;
  87.  
  88.         if(prev_hash != tmp->nast->hash) //czy nie trzeba wstawic elementu do tab
  89.             {prev_hash = tmp->nast->hash;
  90.              tablica_hash[prev_hash] = tmp->nast;
  91.             }
  92.         }//zamyka fora
  93.  
  94.     tmp->nast = sentinel;
  95.     sentinel->prev = tmp;  //wskazujemy straznikowi koniec hashmapy
  96.     };
  97.  
  98.  
  99.  
  100. void otwieraniePliku()
  101. {
  102.     string nazwa;
  103.     cout<<"Podaj nazwe pliku: ";
  104.     cin>>nazwa;
  105.     fstream plik;
  106.     plik.open( nazwa.c_str(), ios::in );
  107.      if( plik.good() )
  108.      {
  109.          parsujTekst(plik);
  110.      }
  111.      else cout<< "Nie udalo sie otworzyc pliku!"<<endl;
  112. // Mozliwy blad -> podano zla nazwe ;d
  113.  
  114. };
  115.  
  116. void parsujTekst(fstream &plik)
  117. {
  118.     string linia;
  119.     while(!plik.eof())
  120.         {
  121.             unsigned int i=0;
  122.             string wyraz;
  123.             getline(plik, linia);
  124.             if(linia[0]=='#')
  125.             {
  126.                 cout<< "HASH!"<<endl;
  127.                 liniaHash(linia);
  128.             }
  129.             while(linia.size()!=0)
  130.             {
  131.                 wyraz = pobierzWyraz(linia);
  132.                 if(!wyraz.empty())cout <<"wyraz: "<<wyraz<<endl;
  133.             }
  134.         }
  135. };
  136. string do_zamiany;
  137. void liniaHash(string &linia)
  138. {
  139.     string zamiennik;// do_zamiany;
  140.     pobierzWyraz(linia);
  141.     if(pobierzWyraz(linia)=="define")
  142.     {
  143.         do_zamiany = pobierzWyraz(linia);
  144.         zamiennik = pobierzWyrazenie(linia);
  145.         cout<< "wtf : "<<do_zamiany<<endl;
  146.         insert(make_pair(do_zamiany, zamiennik));
  147.         cout<< "wtf2 : "<<do_zamiany<<endl;
  148.     }
  149. };
  150.  
  151. string pobierzWyrazenie(string &linia)
  152. {
  153.     string wyraz;
  154.     for (unsigned int i=0; i<= linia.size();++i)
  155.     {
  156.         if (linia[i]>= ' ' && !(linia[i]=='/'&&linia[i+1]=='/') ) //dopoki nalezy do znakow drukowalnych i nie jest komentarzem
  157.         {
  158.             wyraz+=linia[i];
  159.         }
  160.         else
  161.         {
  162.             linia.erase(0,i+1);
  163.         }
  164.     }
  165. };
  166. string pobierzWyraz(string &linia)
  167. {
  168.     string wyraz;
  169.     for (unsigned int i=0; i<= linia.size();++i)
  170.     {
  171.         if (isalnum(linia[i])||linia[i]=='_')
  172.         {
  173.             wyraz+=linia[i];
  174.         }
  175.         else
  176.         {
  177.             linia.erase(0,i+1);
  178.             return wyraz;
  179.         }
  180.     }
  181.  
  182. };
  183.  
  184.  
  185.  
  186.  
  187.    /// const_iterator.
  188.    class const_iterator: public iterator<forward_iterator_tag,
  189.                                                  pair<K, V> >
  190.     {
  191.        protected:
  192.         Cell *sentinel;     //wskazanie na sentinela
  193.         Cell *cell;         //          na element
  194.         friend class HashMap;
  195.        public:
  196.         const_iterator(){};
  197.         const_iterator(Cell *n, Cell *s) : cell(n), sentinel(s) {}
  198.         const_iterator(const const_iterator &n) : cell(n.cell), sentinel(n.sentinel) {}
  199.  
  200.         inline const T* operator*() const
  201.          {return cell->data;}
  202.  
  203.            inline const T* operator->() const
  204.             {return &(cell->data);}
  205.  
  206.               inline const_iterator& operator++() {
  207.               if(cell != sentinel) cell = cell->next;
  208.               return *this;
  209.             }
  210.  
  211.             inline const_iterator operator++(int) {
  212.               if(cell == sentinel) return *this;
  213.               const_iterator tmp = *this;
  214.              cell = cell->next;
  215.               return tmp;
  216.            }
  217.      inline const_iterator& operator--() {
  218.               if(cell->prev != sentinel) cell = cell->prev;
  219.               return *this;
  220.             }
  221.  
  222.             inline const_iterator operator--(int) {
  223.               if(cell->prev == sentinel) return *this;
  224.               const_iterator tmp = *this;
  225.               cell = cell->prev;
  226.               return tmp;
  227.             }
  228.  
  229.             inline bool operator==(const const_iterator &inny) const
  230.             {return (cell == inny.cell);}
  231.  
  232.             inline bool operator!=(const const_iterator &inny) const
  233.             {return (cell != inny.cell);}
  234.     };
  235.    /// iterator.
  236.    class iterator: public const_iterator
  237.     {
  238.       private:
  239.         friend class HashMap;
  240.       public:
  241.          iterator() {}
  242.             iterator(Cell *x, Cell *s) : const_iterator(x, s) {}
  243.             iterator(const iterator &a) {
  244.               this->cell = a.cell;
  245.               this->sentinel = a.sentinel;
  246.             }
  247.  
  248.             inline T& operator*() const
  249.             {return this->cell->data;}
  250.  
  251.             inline T* operator->() const
  252.             {return &(this->cell->data);}
  253.  
  254.             inline iterator& operator++()
  255.             {++(*(const_iterator*)this);
  256.               return (*this);
  257.             }
  258.  
  259.          inline iterator operator++(int)
  260.             {
  261.               iterator tmp = *this;
  262.               ++*this;
  263.               return tmp;
  264.             }
  265.  
  266.             inline iterator& operator--()
  267.             {
  268.               --(*(const_iterator*)this);
  269.               return (*this);
  270.             }
  271.  
  272.             inline iterator operator--(int)
  273.             {
  274.               iterator tmp = *this;
  275.               --*this;
  276.               return tmp;
  277.             }
  278.         };
  279.  
  280.    /// Returns an iterator addressing the first element in the map.
  281.  
  282.     inline iterator begin(){return iterator(sentinel->next, sentinel);}
  283.     inline const_iterator begin() const {return const_iterator(sentinel->next, sentinel);};
  284.  
  285.    /// Returns an iterator that addresses the location succeeding the last element in a map.
  286.  
  287.     inline iterator end(){return iterator(sentinel, sentinel);};
  288.     inline const_iterator end() const {return const_iterator(sentinel, sentinel);};
  289.  
  290.    /// Inserts an element into the map.
  291.    /// @returns A pair whose bool component is true if an insertion was
  292.    ///          made and false if the map already contained an element
  293.    ///          associated with that key, and whose iterator component coresponds to
  294.    ///          the address where a new element was inserted or where the element
  295.    ///          was already located.
  296.    pair<iterator, bool> insert(const pair<K, V>& entry)
  297.     {
  298.       unsigned hash=hashFunc(entry.first); // hash wstawianego elementu
  299.       Cell *tmp = tablica_hash[hash];
  300.         if(tmp!=NULL) //jest juz element o podanym hashu
  301.         {
  302.            while(tmp->hash == hash && tmp != sentinel)
  303.             {  if(!compFunc(tmp->data.first, entry.first))
  304.                 return make_pair(iterator(tmp, sentinel), false);
  305.                tmp = tmp->next;
  306.             }//zamyka while
  307.  
  308.            Cell *n = new Cell(entry, tmp, tmp->prev);
  309.            tmp->prev->next = n;
  310.            tmp->prev = n;
  311.               n->hash = hash;
  312.               map_size++;
  313.               return make_pair(iterator(n, sentinel), true);
  314.         }//zamyka ifa
  315.  
  316.         Cell *n= new Cell(entry, sentinel, sentinel->prev);
  317.         sentinel->prev->next = n;
  318.         sentinel->prev = n;
  319.         n->hash = hash;
  320.         tablica_hash[hash] = n;
  321.         map_size++;
  322.         return make_pair(iterator(n, sentinel), true);
  323.  
  324.     };
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.    /// Returns an iterator addressing the location of the entry in the map
  332.    /// that has a key equivalent to the specified one or the location succeeding the
  333.    /// last element in the map if there is no match for the key.
  334.    iterator find(const K& k)
  335.     { unsigned hash = hashFunc(k); //hash elementu
  336.  
  337.         if(tablica_hash[hash]==NULL) return end(); //jesli nie znalazles elementu zwroc iterator po ostatnim
  338.  
  339.         Cell *tmp = tablica_hash[hash];
  340.         do{
  341.             if(!compFunc(tmp->data.first, k)) return iterator(tmp, sentinel); //znaleziono element
  342.             tmp = tmp->next;
  343.           }while(tmp->hash == hash && tmp != sentinel);
  344.     return end();       //gdy nie ma takiego elementu
  345.     };
  346.  
  347.  
  348.  
  349.  
  350.    const_iterator find(const K&k) const
  351.     {unsigned hash = hashFunc(k);     //hash szuk. elementu
  352.  
  353.       //sprawdzamy miejsce w tablicy hashujacej
  354.        if(tablica_hash[hash] == NULL) return end();
  355.  
  356.      Cell* tmp = tablica_hash[hash];
  357.  
  358.     do {
  359.         if(!compFunc(tmp->data.first, k))return const_iterator(tmp, sentinel);
  360.         tmp = tmp->next;
  361.           } while(tmp->hash == hash && tmp != sentinel);
  362.  
  363.       return end();
  364.     };
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.    /// Inserts an element into a map with a specified key value
  372.    /// if one with such a key value does not exist.
  373.    /// @returns Reference to the value component of the element defined by the key.
  374.    V& operator[](const K& k)
  375.     {return insert(make_pair(K(k), V())).first->second;
  376.     };
  377.  
  378.    /// Tests if a map is empty.
  379.    bool empty( ) const{return sentinel == sentinel->next;};
  380.  
  381.    /// Returns the number of elements in the map.
  382.    unsigned size() const{return map_size;};
  383.  
  384.    /// Returns the number of elements in a map whose key matches a parameter-specified key.
  385.    unsigned count(const K& _Key) const
  386.     { unsigned hash=hashFunc(_Key);
  387.         if(tablica_hash[hash] == NULL) return 0; //znalazlo 0 elementow;
  388.         Cell *tmp = tablica_hash[hash];
  389.       do {
  390.         if(!compFunc(tmp->data.first, _Key))
  391.           return 1;                                //znaleziono
  392.         tmp = tmp->next;
  393.       } while(tmp->hash == hash && tmp != sentinel);
  394.  
  395.       return 0;
  396.     };
  397.  
  398.    /// Removes an element from the map.
  399.    /// @returns The iterator that designates the first element remaining beyond any elements removed.
  400.    iterator erase(iterator i)
  401.     {
  402.      //sprawdzamy czy i nie wskazuje na straznika i czy jest z tej mapy
  403.           if(i.cell == sentinel || i.sentinel!= sentinel) return i;
  404.  
  405.           Cell *tmp = i.cell;
  406.           unsigned int hash = tmp->hash;
  407.  
  408.  
  409.           if(tmp == tablica_hash[hash]) {
  410.             if(tmp->next->hash != hash || tmp->next == sentinel) {
  411.               tablica_hash[hash] = NULL;
  412.             } else {
  413.               tablica_hash[hash] = tmp->next;
  414.             }
  415.           }
  416.  
  417.           tmp->prev->next = tmp->next;
  418.           tmp->next->prev = tmp->prev;
  419.           i = iterator(tmp->next, sentinel);
  420.           delete tmp;
  421.           map_size--;
  422.           return i;
  423.     };
  424.  
  425.    /// Removes a range of elements from the map.
  426.    /// The range is defined by the key values of the first and last iterators
  427.    /// first is the first element removed and last is the element just beyond the last elemnt removed.
  428.    /// @returns The iterator that designates the first element remaining beyond any elements removed.
  429.    iterator erase(iterator first, iterator last)
  430.     {  if(first == end()) return end();
  431.        //sprawdzamy czy last>=first
  432.           Cell *tmp = last.cell;
  433.           for(; tmp != sentinel; tmp = tmp->next)
  434.         if(tmp == first.cell) return end();
  435.     //kasujemy elementy
  436.           while(first != last) erase(first++);
  437.  
  438.           return last;
  439.     };
  440.    /// Removes an element from the map.
  441.    /// @returns The number of elements that have been removed from the map.
  442.    ///          Since this is not a multimap itshould be 1 or 0.
  443.    unsigned erase(const K& key)
  444.     {unsigned hash = hashFunc(key);
  445.     if(tablica_hash[hash] == NULL) return 0; //jesli nie ma co usunac -> zwroc 0
  446.     Cell *tmp = tablica_hash[hash];
  447.  
  448.     if(!compFunc(tmp->data.first, key)) {
  449.             if(tmp->next->hash != hash || tmp->next == sentinel) {
  450.               tablica_hash[hash] = NULL;
  451.             } else {//else1
  452.               tablica_hash[hash] = tmp->next;
  453.              }//do else1
  454.           } else {//else2
  455.             do {
  456.               if(tmp == sentinel) return 0;               //doszlismy do konca
  457.               if(tmp->next->hash != hash) return 0;
  458.               tmp = tmp->next;
  459.             } while(compFunc(tmp->data.first, key) != 0);
  460.               }//do elsa2
  461.       tmp->prev->next = tmp->next;
  462.       tmp->next->prev = tmp->prev;
  463.       delete tmp;
  464.       map_size--;
  465.     //  cout << map_size<<endl;
  466.       return 1;
  467.     };
  468.  
  469.    /// Erases all the elements of a map.
  470.    void clear()
  471.     {Cell *tmp = sentinel;
  472.  
  473.       while(tmp != sentinel) {
  474.         tmp = tmp->next;                //usuwamy elementy
  475.         delete(tmp->prev);
  476.       }
  477.  
  478.       sentinel->next =  sentinel;
  479.     sentinel->prev = sentinel;
  480.       Cell **wsk = tablica_hash;
  481.       for(int i=0; i<HASH_SIZE; ++i)    //zerujemy tablice hash
  482.         *(wsk++)= NULL;
  483.  
  484.       map_size = 0;
  485.     };
  486.  
  487.  
  488.  
  489. };
  490. #include "hashmap.cpp"
  491. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement