zhangsongcui

HashMap

Sep 21st, 2014
319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.55 KB | None | 0 0
  1. #include <string>
  2. #include <iostream>
  3. #include <array>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <limits>
  7. #include <stdexcept>
  8.  
  9. #include <chrono>
  10. #include <unordered_map>
  11.  
  12. template <typename T>
  13. class HashMap {
  14.     using value_type = std::pair<std::string, T>;
  15.     using cont_type = std::array<std::vector<value_type>, std::numeric_limits<unsigned char>::max() + 1>;
  16.    
  17. public:
  18.     T& operator [](const std::string& key) {
  19.         if (auto ptr = try_get(key)) {
  20.             return *ptr;
  21.         } else {
  22.             try_add(key, T(), &ptr);
  23.             return *ptr;
  24.         }
  25.     }
  26.    
  27.     T* try_get(const std::string& key) noexcept {
  28.         auto& vec = container[hashString(key)];
  29.         auto iter = std::find_if(std::begin(vec), std::end(vec), [&](value_type& value) {
  30.             return value.first == key;
  31.         });
  32.         if (iter == std::end(vec)) {
  33.             return nullptr;
  34.         }
  35.        
  36.         return &iter->second;
  37.     }
  38.    
  39.     T& get(const std::string& key) {
  40.         if (auto ptr = try_get(key)) {
  41.             return *ptr;
  42.         } else {
  43.             throw std::invalid_argument("key not found");
  44.         }
  45.     }
  46.    
  47.     bool try_add(std::string key, T value, T **inserted = nullptr) {
  48.         auto& vec = container[hashString(key)];
  49.         auto iter = std::find_if(std::begin(vec), std::end(vec), [&](value_type& value) {
  50.             return value.first == key;
  51.         });
  52.         if (iter == std::end(vec)) {
  53.             vec.push_back(std::make_pair(std::move(key), std::move(value)));
  54.             if (inserted) {
  55.                 *inserted = &vec.back().second;
  56.             }
  57.             return true;
  58.         } else {
  59.             if (inserted) {
  60.                 *inserted = &iter->second;
  61.             }
  62.         }
  63.        
  64.         return false;
  65.     }
  66.    
  67.     T& add(std::string key, T value) {
  68.         T *ptr;
  69.         if (try_add(std::move(key), std::move(value), &ptr)) {
  70.             return *ptr;
  71.         } else {
  72.             throw std::invalid_argument("duplicated key found");
  73.         }
  74.     }
  75.    
  76. private:
  77.     static inline unsigned char hashString(const std::string& str) {
  78.         const unsigned char x = std::numeric_limits<unsigned char>::max() >> 1;
  79.         switch (str.length()) {
  80.             case 0:
  81.                 return 0;
  82.                
  83.             case 1:
  84.                 return str[0];
  85.                
  86.             default:
  87.                 return ((unsigned char)str[0] & x) + ((unsigned char)str[1] & x);
  88.         }
  89.     }
  90.    
  91. private:
  92.     cont_type container;
  93. };
Advertisement
Add Comment
Please, Sign In to add comment