hash_table

Posted pengtangtang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hash_table相关的知识,希望对你有一定的参考价值。


1
//哈希表查询与插入删除速率非常快速 2 #include<unordered_map> 3 #include<map> 4 #include<iostream> 5 6 using namespace std; 7 template<typename Key,typename Value> 8 class HashTable 9 { 10 private: 11 const static int upperTol = 3; 12 const static int lowerTol = 1; 13 const static int initCapacity = 1; 14 map<Key,Value> **hashtable;//整个表 15 int M;//哈希表数组的大小 16 int size;//表中已有元素个数 17 18 public: 19 //传参构造 20 HashTable(int m) : M((m),size(0) 21 { 22 //this->hashtable = new map<Key,Value>* [M](); 23 this->hashtable = new map<Key,Value>* [M]; 24 for (inti= 0;i < M;i++) 25 { 26 this->hashtable[i] = new map<Key,Value>; 27 } 28 } 29 //默认构造 30 HashTable() { 31 HashTable(initCapacity); 32 } 33 34 //析构函数 35 ~HashTable() { 36 free(M); 37 } 38 39 public: 40 int getSize() { 41 return size; 42 } 43 44 //添加新元素 45 void add(Key key,Value value) 46 {// 拉链法出来的map如果为空,就动态分配一个map,然后进行插入 47 // 如果key不存在就看内存是否存在,不存在,就分配,存在就插入 48 if (hashtable[hashFunc(key)] == NULL || hashtable[hasFunc(key)]->count(key) == 0)//count() 49 { if (hashtable[hashFunc(key)] == NULL) 50 hashtable[hashFunc(key)] = new map<Key, Value>; 51 hashtable[hashFunc(key)]->insert(make_pair(key, value)); 52 size++; 53 if (size >= maxCapacity()) 54 resize(2 * M); 55 } else { 56 // 否则,修改value. 57 hashtable[hashFunc(key)]->erase(key); 58 hashtable[hashFunc(key)]->insert(make_pair(key, value)); 59 } 60 } 61 /** 62 * 移除Key 63 * @param key 64 * @return 0 success -1 fail 65 */ 66 Value remove(Key key) { 67 Value ret = -1; 68 // 是否包含key,若包含key,则直接删除 69 if (contains(key)) { 70 hashtable[hashFunc(key)]->erase(key); 71 size--; 72 // if (size == 0) delete hashtable[hashFunc(key)]; // 可以添加这行来动态减少内存 73 ret = 0; 74 // initCapacity 保证不会越界 75 if (size < minCapacity() && M / 2 >= initCapacity) resize(M / 2); 76 } 77 return ret; 78 } 79 80 /** 81 * 重设value 82 * @param key 83 * @param value 84 */ 85 void set(Key key, Value value) { 86 // key不存在 87 if (!contains(key)) 88 throw "key not exists!"; 89 // 修改value 90 hashtable[hashFunc(key)]->erase(key); 91 hashtable[hashFunc(key)]->insert(make_pair(key, value)); 92 } 93 /** 94 * 是否包含key 95 * @param key 96 * @return 97 */ 98 bool contains(Key key) { 99 return hashtable[hashFunc(key)] == NULL || this->hashtable[hashFunc(key)]->count(key) == 0 ? false : true; 100 } 101 102 /** 103 * 获取key对应的value 104 * @param key 105 * @return 106 */ 107 108 Value get(Key key) { 109 if (contains(key)) 110 return hashtable[hashFunc(key)]->at(key); 111 return 0; 112 } 113 114 /** 115 * 最大容量 116 * @return 117 */ 118 Value maxCapacity() { 119 return M * upperTol; 120 } 121 122 /** 123 * 最小容量 124 * @return 125 */ 126 Value minCapacity() { 127 return M * lowerTol; 128 } 129 130 private: 131 /** 132 * 哈希函数 133 * @param key 134 * @return 135 */ 136 int hashFunc(Key key) { 137 std::hash<Key> h; 138 return (h(key) & 0x7fffffff) % M; 139 } 140 141 template<typename K, typename V> 142 // 重载<<操作符 143 friend ostream &operator<<(ostream &out, HashTable<K, V> &hashTable); 144 145 /** 146 * 打印hash表中所有数据 147 */ 148 void print() { 149 string res = "{"; 150 for (int i = 0; i < this->M; i++) 151 if (this->hashtable[i]) 152 for (auto m:*(this->hashtable[i])) 153 res += m.first + ":" + to_string(m.second) + ","; 154 res.replace(res.size() - 1, string::npos, "}");//将最后一个字符串替换
//npos是一个静态成员常量值,对于size_t类型的元素,其最大值可能

该值字符串成员函数中用作len(或sublen)参数的值时,表示“直到字符串结尾” 作为返回值,通常用于表示没有匹配项。 该常量定义为值-1,这是因为size_t是无符号整数类型,因此它是此类型可能的最大可表示值。
155 cout << res << endl; 156 } 157 158 /** 159 * 动态调整内存,保证时间复杂度O(1)查找 160 * 把扩容后的操作,平摊到前面每次操作,时间复杂度O(2),那就是O(1)了 161 * @param newM 162 */ 163 void resize(int newM) {
        //首先获取新的空间,再将旧的数据复制到新的空间,最后释放旧空间
164 cout << "resize " << newM << endl; 165 map<Key, Value> **newHashTable = new map<Key, Value> *[newM]; 166 for (int i = 0; i < newM; i++) { 167 newHashTable[i] = new map<Key, Value>; 168 } 169 int oldM = M; 170 this->M = newM; 171 for (int i = 0; i < oldM; i++) { 172 map<Key, Value> m = *(hashtable[i]); 173 for (auto p:m) 174 newHashTable[hashFunc(p.first)]->insert(make_pair(p.first, p.second)); 175 } 176 177 178 free(oldM); 179 this->hashtable = newHashTable; 180 } 181 182 private: 183 /** 184 * 释放内存 185 * @param M 186 */ 187 void free(int M) { 188 for (int i = 0; i < M; i++) { 189 if (hashtable[i]) 190 delete hashtable[i]; 191 } 192 delete[]hashtable; 193 } 194 }; 195 196 template<typename K, typename V> 197 ostream &operator<<(ostream &out, HashTable<K, V> &hashTable) { 198 hashTable.print(); 199 return out; 200 } 201 202 /** 203 * 哈希函数的设计原则: 204 * 1.一致性:如果a==b,则hashFunc(a)=o=hashFunc(b) 205 * 2.高效性:计算高效简便 206 * 3.均匀性:哈希值均匀分布 207 */ 208 209 // (hashcode(k1) & 0x7fffffff)%M 210 // f为7个一个f有4个1那么就是28个1,,7有3个1,,总共31个1 211 // 而最高位第32位表示正负,故上述取&后,变为正数。 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 };

哈希表:以map作为底部容器,由装多个map地址的数组和多个map构成。
map:所有元素都唯一,且所有元素自动从小到大排序

1)map::count()----根据键值查看map中是否由此节点
 1 #include<iostream>
 2 #include<map>
 3 int main()
 4 {
 5   std::map<char,int> mymap;
 6   char c;
 7 
 8   mymap[a] = 101;
 9   mymap[b] = 202;
10   mymap[c] = 303;
11 
12   for (c = a;c < e;c++)
13   {
14     std::cout << c << endl;
15     if (mymap.count(c) > 0)
16       std::cout <<"is an element
";
17     else
18       std::cout << "is not an element
";
19   }
20   
21 }
2)map::insert()---插入节点
 1 #include <iostreram>
 2 #include <map>
 3 
 4 int main()
 5 {
 6   sta::map<char,int> mymap;
 7   //first version----single parameter
 8   mymap.insert(std::pair<char,int>(a,100));
 9   mymap.insert(std::pair<char,int>(z,200));
10   mymap.insert(std::make_pair(d,321));
11 
12   std::pair<std::map<char,int>::iterator,bool> ret;
13   ret = mymap.insert(std::pair<char,int>(z,500));
14   if (ret.second == false){
15     std::cout << "element ‘z‘ already existed";
16     std::cout << "with a value of " << ret.first->second << estd::endl
17   }
18 //second version---with hint position
19   std::map<char,int>::iterator it = mymap.begin();
20   mymap.insert(it,std::pair<char,int>(b,300));
21   mymap.insert(it,std::pair<char,int>)c,400));
22 
23 //third version----range insertion
24 std::map<char,int> anothermap;
25 anothermap.insert(mymap.begin(),mymap.find(c));
26 //show contents
27 std::cout << "mymap contains:
";
28 for (it = mymap.begin();it != mymap.end();it++)
29 {
30   std::cout << it->first << "-->" << it->second << 
;
31 }
32 
33 std::cout << "anothermap contains:
";
34 for (it = anothermap.begin();it != aonthermap.end();it++)
35   std::cout << it->first << "-->" << it->second << 
 ;
36 }

3)string成员函数

(1)replace

 1 #include <iostream>
 2 
 3 #include <string>
 4 
 5 int main()
 6 
 7 {
 8 
 9   std::string base = "this is a test string";
10 
11   std::string str2 = "n example";
12 
13   std::string str3 = "sample phrase";
14 
15   std::string str4 = "useful";
16 
17   //versionj1-----use position
18 
19   std::string str = base;
20 
21   str.replace(9,5,str2);
22 
23   str.replace(19,6,str3,7,6);
24 
25   str.replace(8,10,"just a");
26 
27   str.replace(8,6,"a shorty",7);
28 
29   str.replace(22,1,3,!);
30 
31 
32 
33   //using iterator
34 
35   str.replace(str.begin(),str.end()-3,str3);
36 
37   str.replace(str.begin(),str.begin()+6,"replace");
38 
39   str.replace(str.begin(),str.begin+14,"is");
40 
41 }

(2)string::npos

静态const size_t npos = -1;
size_t的最大值

npos是一个静态成员常量值,对于size_t类型的元素,其最大值可能

该值字符串成员函数中用作len(或sublen)参数的值时,表示“直到字符串结尾” 作为返回值,通常用于表示没有匹配项。 该常量定义为值-1,这是因为size_t是无符号整数类型,因此它是此类型可能的最大可表示值。

 

  

以上是关于hash_table的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode哈希表 hash_table(共88题)

LeetCode哈希表 hash_table(共88题)

hash_table

hash_table

STL简单hashtable的实现

在 setdefault 之后附加到字典中的列表 [重复]