Advertisement
Guest User

Untitled

a guest
Nov 27th, 2014
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.07 KB | None | 0 0
  1. /**
  2. @file aisdihashmap.h
  3.  
  4. AISDIHashMap and related functions interface.
  5.  
  6. @author
  7. Pawel Cichocki
  8.  
  9. @date
  10. last revision
  11. - 2006.03.24 Pawel Cichocki: wrote it
  12.  
  13. COPYRIGHT:
  14. Copyright (c) 2006 Instytut Informatyki, Politechnika Warszawska
  15. ALL RIGHTS RESERVED
  16. *******************************************************************************/
  17.  
  18. #include <utility>
  19. #include <string>
  20. #include <iterator>
  21.  
  22. #define SIZE 65536
  23. /// Default keys' comparing function for AISDIHashMap - it uses
  24. /// operator== by default.
  25. /// @returns true if keys are equal, false otherwise.
  26. /// @param key1 First key to compare.
  27. /// @param key2 Second key to compare.
  28. template <class Key>
  29. inline bool _compFunc(const Key& key1, const Key& key2)
  30. {
  31.     return (key1 == key2);
  32. };
  33.  
  34. inline unsigned hashF(const std::string& m)
  35. {
  36.     unsigned h = 0;
  37.     int i;
  38.  
  39.     for (i = 0; i < m.length(); i++)
  40.         h ^= (h << 5) + (h >> 2) + m[i];
  41.     return h & 0xFFFF;
  42. };
  43. /// A map with a similar interface to std::map.
  44. template<class K, class V,
  45.     unsigned hashFunc(const K&),
  46.     bool compFunc(const K&, const K&) = &_compFunc<K> >
  47. class AISDIHashMap
  48. {
  49. public:
  50.     typedef K key_type;
  51.     typedef V value_type;
  52.     typedef unsigned size_type;
  53.  
  54.     /* klasa reprezentujaca element pierscienia*/
  55.     class Node
  56.     {
  57.     public:
  58.         std::pair<K, V> data;
  59.         Node* next;
  60.         Node* prev;
  61.         unsigned hashIndex; /* indeks w tablicy z hashowaniem */
  62.         Node(const std::pair<K, V>& d, unsigned hashnr) : data(d), next(NULL), prev(NULL), hashIndex(hashnr) { }
  63.     };
  64.  
  65. private:
  66.     Node* sentinel; /* wskaznik na straznika */
  67.     Node* hashTable[SIZE];  /* tablica 65536 wskaznikow na elementy pierscienia*/
  68.  
  69. public:
  70.     AISDIHashMap()
  71.     {
  72.         sentinel = new Node(std::make_pair(K(), V()));  /* tworzymy straznika */
  73.         sentinel->next = sentinel;  /* "uszy" straznika - pokazuje na siebie */
  74.         sentinel->prev = sentinel;
  75.         for (int i = 0; i < SIZE; i++)  /* inicjalizacja tablicy wskaznikow NULLem*/
  76.             hashTable[i] = NULL;
  77.     }
  78.     ~AISDIHashMap()
  79.     {
  80.         clear();    /* usuwamy wszystkie elementy */
  81.         delete sentinel; /* i jeszcze straznik */
  82.     }
  83.  
  84.     /// Coping constructor.
  85.     explicit AISDIHashMap(const AISDIHashMap<K, V, hashFunc, compFunc>& a)
  86.     {
  87.         const_iterator i;                       /* kopiujemy pozostale elementy */
  88.         Node* ptr = NULL;   /* wskaznik na ostatnio wstawiany element, na poczatku rowny NULL*/
  89.         Node* first;
  90.         int flag = 0;
  91.         for (i = a.begin(); i != a.end(); ++i)
  92.         {
  93.             Node* new_ptr = new Node(a.node->data, a.node->hashIndex);
  94.             if (ptr == NULL)    /* kopiujemy pierwszy element */
  95.             {
  96.                 first = new_ptr;
  97.                 flag = 1;
  98.             }
  99.             else /* kopiujemy kolejne elementy juz oprocz pierwszego */
  100.             {
  101.                 new_ptr->prev = ptr;
  102.                 ptr->next = new_ptr;
  103.             }
  104.             if (a.node->hashIndex != a.node->prev->hashIndex)   /* przypisanie wskazania jesli pierwszy hash */
  105.             {
  106.                 hashTable[hashIndex] = new_ptr;
  107.             }
  108.             ptr = new_ptr;
  109.         }
  110.         sentinel = new Node(std::make_pair(K(), V()));  /* tworzymy straznika nowej listy*/
  111.         if (flag == 1)
  112.         {   /* laczymy straznika z ostatnim i tworzymy pierscien */
  113.             sentinel->prev = ptr;
  114.             sentinel->next = first;
  115.             first->prev = sentinel;
  116.             ptr->next = sentinel;
  117.         }
  118.         else
  119.         {
  120.             /* jesli tylko straznik */
  121.             sentinel->next = sentinel;
  122.             sentinel->prev = sentinel;
  123.         }
  124.     }
  125.     /// const_iterator.
  126.     class const_iterator : public std::iterator < std::forward_iterator_tag,
  127.         std::pair<K, V> >
  128.     {
  129.     protected:
  130.         Node* node;     /* iterator przechowujacy wskaznik na element */
  131.         friend class AISDIHashMap;
  132.         const_iterator(Node* x) : node(x) {}
  133.     public:
  134.         typedef std::pair<K, V> T;
  135.         const_iterator() {}
  136.         const_iterator(const const_iterator& a) : node(a.node) {}
  137.         // operatory
  138.         inline const T& operator*() const
  139.         {
  140.             return node->data;
  141.         }
  142.  
  143.         inline const T* operator->() const
  144.         {
  145.             return &(node->data);
  146.         }
  147.         /* preincrementacja */
  148.         const_iterator& operator++()
  149.         {
  150.             node = node->next;
  151.             return *this;
  152.         }
  153.         /* postincrementacja */
  154.         const_iterator operator++(int)
  155.         {
  156.             const_iterator temp = *this;
  157.             ++*this;
  158.             return temp;
  159.         }
  160.         /* predekrementacja */
  161.         const_iterator& operator--()
  162.         {
  163.             node = node->prev;
  164.             return *this;
  165.         }
  166.         /* postdekrementacja */
  167.         const_iterator operator--(int)
  168.         {
  169.             const_iterator temp = *this;
  170.             --*this;
  171.             return temp;
  172.         }
  173.         inline bool operator==(const const_iterator& a) const
  174.         {
  175.             return node == a.node;
  176.         }
  177.         inline bool operator!=(const const_iterator& a) const
  178.         {
  179.             return node != a.node;
  180.         }
  181.     };
  182.  
  183.     /// iterator.
  184.     class iterator : public const_iterator
  185.     {
  186.         iterator(Node* x) : const_iterator(x) {}
  187.         friend class AISDIHashMap;
  188.     public:
  189.         iterator() {}
  190.         iterator(const iterator& a) { node = a.node; }
  191.  
  192.         inline T& operator*() const
  193.         {
  194.             return node->data;
  195.         }
  196.         inline T* operator->() const
  197.         {
  198.             return &(node->data);
  199.         }
  200.         /* preinkrementacja */
  201.         iterator& operator++()
  202.         {
  203.             ++(*(const_iterator*)this);
  204.             return (*this);
  205.         }
  206.         /* postinkrementacja */
  207.         iterator operator++(int)
  208.         {
  209.             iterator temp = *this;
  210.             ++*this;
  211.             return temp;
  212.         }
  213.         /* predekrementacja */
  214.         iterator& operator--()
  215.         {
  216.             --(*(const_iterator*)this);
  217.             return (*this);
  218.         }
  219.         /* postdekrementacja */
  220.         iterator operator--(int)
  221.         {
  222.             iterator temp = *this;
  223.             --*this;
  224.             return temp;
  225.         }
  226.     };
  227.  
  228.     /// Returns an iterator addressing the first element in the map.
  229.     inline iterator begin()
  230.     {
  231.         return iterator(sentinel->next);
  232.     }
  233.     inline const_iterator begin() const
  234.     {
  235.         return const_iterator(sentinel->next);
  236.     }
  237.  
  238.     /// Returns an iterator that addresses the location succeeding the last element in a map.
  239.     inline iterator end()
  240.     {
  241.         return iterator(sentinel);
  242.     }
  243.     inline const_iterator end() const
  244.     {
  245.         return const_iterator(sentinel);
  246.     }
  247.  
  248.     /// Inserts an element into the map.
  249.     /// @returns A pair whose bool component is true if an insertion was
  250.     ///          made and false if the map already contained an element
  251.     ///          associated with that key, and whose iterator component coresponds to
  252.     ///          the address where a new element was inserted or where the element
  253.     ///          was already located.
  254.     std::pair<iterator, bool> insert(const std::pair<K, V>& entry)
  255.     {
  256.         iterator i = find(entry.first);
  257.         if (i != end())
  258.             return std::make_pair(i, false);            /* jesli juz istnieje element o danym kluczu, to wstawianie nie powiodlo sie */
  259.         /* element nie istnieje, dlatego musimy go wstawic */
  260.         unsigned hash = hashFunc(entry.first);  /* liczymy hash elementu */
  261.         i.node = hashTable[hash];
  262.  
  263.         if (hashTable[hash] != NULL)    /* jesli jest element o danym hashu, to nowy wstawiamy na poczatku */
  264.         {
  265.             Node* newElement = new Node(entry, hash);
  266.             newElement->next = i.node;
  267.             newElement->prev = i.node->prev;
  268.             i.node->prev->next = newElement;
  269.             i.node->prev = newElement;
  270.             hashTable[hash] = newElement;
  271.             return std::make_pair(i, true); /* wstawianie powiodlo sie */
  272.         }
  273.         else    /* jesli nie ma elementow o takim hashu, to wstawiamy element za straznikiem */
  274.         {
  275.             Node* newElement = new Node(entry, hash);
  276.             newElement->next = sentinel->next;
  277.             newElement->prev = sentinel;
  278.             sentinel->next->prev = newElement;
  279.             sentinel->next = newElement;
  280.             hashTable[hash] = newElement;
  281.             return std::make_pair(i, true); /* wstawianie powiodlo sie */
  282.         }
  283.     }
  284.  
  285.     /// Returns an iterator addressing the location of the entry in the map
  286.     /// that has a key equivalent to the specified one or the location succeeding the
  287.     /// last element in the map if there is no match for the key.
  288.     iterator find(const K& k)
  289.     {
  290.         unsigned hash = hashFunc(k);    /* liczymy hash elementu */
  291.  
  292.         if (hashTable[hash] == NULL)    /* jesli nie ma elementow o takim hashu, to zwracamy straznika */
  293.             return end();
  294.  
  295.         iterator i;
  296.         i.node = hashTable[hash];   /* ustawiamy iterator na wyliczonym hashu */
  297.  
  298.         while (i.node->hashIndex == hash)   /* przegladamy elementy o takim samym hashu */
  299.         {
  300.             if (i.node->data.first == k)            /* jesli znajdziemy element o takim samym kluczu, to zwracamy iterator ustawiony na tym elemencie */
  301.                 return i;
  302.             i++;
  303.         }
  304.         return end();                       /* nie ma elementu o kluczu k; zwracamy straznika */
  305.     }
  306.  
  307.     /// Returns an const iterator
  308.     const_iterator find(const K& k) const
  309.     {
  310.         unsigned hash = hashFunc(k);    /* liczymy hash elementu */
  311.  
  312.         if (hashTable[hash] == NULL)    /* jesli nie ma elementow o takim hashu, to zwracamy straznika */
  313.             return end();
  314.  
  315.         iterator i;
  316.         i.node = hashTable[hash];   /* ustawiamy iterator na wyliczonym hashu */
  317.         while (i.node->hashIndex == hash)   /* przegladamy elementy o takim samym hashu */
  318.         {
  319.             if (i.node->data.first == k)            /* jesli znajdziemy element o takim samym kluczu, to zwracamy iterator ustawiony na tym elemencie */
  320.                 return i;
  321.             i++;
  322.         }
  323.         return end();                       /* nie ma elementu o kluczu k; zwracamy straznika */
  324.     }
  325.  
  326.     /// Inserts an element into a map with a specified key value
  327.     /// if one with such a key value does not exist.
  328.     /// @returns Reference to the value component of the element defined by the key.
  329.     V& operator[](const K& k)
  330.     {
  331.         return insert(std::make_pair(k, V())).first->second;
  332.     }
  333.  
  334.     /// Tests if a map is empty.
  335.     bool empty() const
  336.     {
  337.         return sentinel->next == sentinel;
  338.     }
  339.  
  340.     /// Returns the number of elements in the map.
  341.     size_type size() const
  342.     {
  343.         iterator i;
  344.         size_type mapSize = 0;
  345.         for (i = begin(); i != end(); i++)
  346.             mapSize++;
  347.         return mapSize;
  348.     }
  349.  
  350.     /// Returns the number of elements in a map whose key matches a parameter-specified key.
  351.     size_type count(const K& _Key) const
  352.     {
  353.         return find(_Key) != end();
  354.     }
  355.  
  356.     /// Removes an element from the map.
  357.     /// @returns The iterator that designates the first element remaining beyond any elements removed.
  358.     iterator erase(iterator i)
  359.     {
  360.         if (i == end())     /* jest tylko straznik - pusta mapa */
  361.             return end();
  362.         if (i.node == hashTable[i.node->hashIndex])
  363.         {
  364.             if (i.node->hashIndex == i.node->next->hashIndex && i.node->next != sentinel)   /* jesli pierwszy element o danym hashu */
  365.                 hashTable[i.node->hashIndex] = i.node->next;
  366.             else
  367.                 hashTable[i.node->hashIndex] = NULL;
  368.         }
  369.         Node* temp = i.node->next;              /* usuwanie elementu */
  370.         i.node->next->prev = i.node->prev;
  371.         i.node->prev->next = i.node->next;
  372.         delete i.node;
  373.         return iterator(temp);
  374.     }
  375.     /// Removes a range of elements from the map.
  376.     /// The range is defined by the key values of the first and last iterators
  377.     /// first is the first element removed and last is the element just beyond the last element removed.
  378.     /// @returns The iterator that designates the first element remaining beyond any elements removed.
  379.     iterator erase(iterator first, iterator last)
  380.     {
  381.         iterator i = first;
  382.         while (i != last)
  383.         {
  384.             Node* temp = i.node->next;
  385.             erase(i);
  386.             i.node = temp;
  387.         }
  388.         return last;
  389.     }
  390.  
  391.     /// Removes an element from the map.
  392.     /// @returns The number of elements that have been removed from the map.
  393.     ///          Since this is not a multimap it should be 1 or 0.
  394.     size_type erase(const K& key)
  395.     {
  396.         iterator i = find(key);
  397.         if (i != end())
  398.         {
  399.             erase(i);
  400.             return 1;
  401.         }
  402.         else
  403.             return 0;
  404.     }
  405.     /// Erases all the elements of a map.
  406.     void clear()
  407.     {
  408.         erase(begin(), end());
  409.     }
  410. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement