当前位置:   article > 正文

《STL源码剖析》---stl_hashtable.h阅读笔记_sgi stl hashtable可以更改键值吗

sgi stl hashtable可以更改键值吗

在前面介绍的RB-tree红黑树中,可以看出红黑树的插入、查找、删除的平均时间复杂度为O(nlogn)。但这是基于一个假设:输入数据具有随机性。而哈希表/散列表hash table在插入、删除、查找上具有“平均常数时间复杂度”O(1);且不依赖输入数据的随机性。

hash table的实现有线性探测、二次探测、二次散列等实现,SGI的STL是采用开链法(separate chaining)来实现的。大概原理就是在hash table的每一项都是个指针(指向一个链表),叫做bucket。这样的话如果多个key值散列到同一位置,那么就存储到这个位置对应的链表中。如下图所示:

hash table使用了vector来做buckets的容器,容器大小是质数(因为散列函数好多情况下是取余数),实现代码如下:

  1. G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_hashtable.h 完整列表
  2. /*
  3. * Copyright (c) 1996,1997
  4. * Silicon Graphics Computer Systems, Inc.
  5. *
  6. * Permission to use, copy, modify, distribute and sell this software
  7. * and its documentation for any purpose is hereby granted without fee,
  8. * provided that the above copyright notice appear in all copies and
  9. * that both that copyright notice and this permission notice appear
  10. * in supporting documentation. Silicon Graphics makes no
  11. * representations about the suitability of this software for any
  12. * purpose. It is provided "as is" without express or implied warranty.
  13. *
  14. *
  15. * Copyright (c) 1994
  16. * Hewlett-Packard Company
  17. *
  18. * Permission to use, copy, modify, distribute and sell this software
  19. * and its documentation for any purpose is hereby granted without fee,
  20. * provided that the above copyright notice appear in all copies and
  21. * that both that copyright notice and this permission notice appear
  22. * in supporting documentation. Hewlett-Packard Company makes no
  23. * representations about the suitability of this software for any
  24. * purpose. It is provided "as is" without express or implied warranty.
  25. *
  26. */
  27. /* NOTE: This is an internal header file, included by other STL headers.
  28. * You should not attempt to use it directly.
  29. */
  30. #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
  31. #define __SGI_STL_INTERNAL_HASHTABLE_H
  32. // Hashtable class 用來實作 hashed associative containers
  33. // hash_set, hash_map, hash_multiset, 和 hash_multimap.
  34. #include <stl_algobase.h>
  35. #include <stl_alloc.h>
  36. #include <stl_construct.h>
  37. #include <stl_tempbuf.h>
  38. #include <stl_algo.h>
  39. #include <stl_uninitialized.h>
  40. #include <stl_function.h>
  41. #include <stl_vector.h>
  42. #include <stl_hash_fun.h>
  43. __STL_BEGIN_NAMESPACE
  44. //hash table中节点的定义,都是public
  45. template <class Value>
  46. struct __hashtable_node
  47. {
  48. /*
  49. 用vector来做hash table,为什么还需要next指针?
  50. 因为SGI 实现的hash table使用了开链法/链接法。
  51. hash table中的节点可能代表一系列节点。它们以链形式连接。
  52. 这是所谓的 separate chaining 技巧。
  53. */
  54. __hashtable_node* next;
  55. Value val;
  56. };
  57. //先声明 hash table,在 iterator中有用到。
  58. template <class Value, class Key, class HashFcn,
  59. class ExtractKey, class EqualKey, class Alloc = alloc>
  60. class hashtable;
  61. // 由与 __hashtable_iterator 和 __hashtable_const_iterator 两者会
  62. // 互相使用,因此必须在下面先做声明,否则编译出错。
  63. template <class Value, class Key, class HashFcn,
  64. class ExtractKey, class EqualKey, class Alloc>
  65. struct __hashtable_iterator;
  66. template <class Value, class Key, class HashFcn,
  67. class ExtractKey, class EqualKey, class Alloc>
  68. struct __hashtable_const_iterator;
  69. //hash table中的迭代器
  70. template <class Value, class Key, class HashFcn,
  71. class ExtractKey, class EqualKey, class Alloc>
  72. struct __hashtable_iterator {
  73. typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
  74. hashtable;
  75. typedef __hashtable_iterator<Value, Key, HashFcn,
  76. ExtractKey, EqualKey, Alloc>
  77. iterator;
  78. typedef __hashtable_const_iterator<Value, Key, HashFcn,
  79. ExtractKey, EqualKey, Alloc>
  80. const_iterator;
  81. typedef __hashtable_node<Value> node;
  82. //迭代器类型,只能向前
  83. typedef forward_iterator_tag iterator_category;
  84. typedef Value value_type;
  85. typedef ptrdiff_t difference_type;
  86. typedef size_t size_type;
  87. typedef Value& reference;
  88. typedef Value* pointer;
  89. node* cur; // 迭代器目前所指之节点
  90. hashtable* ht; // 保持对容器的连接关系,因为可能需要从bucket跳到bucket
  91. __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {}
  92. //默认构造函数什么也没做
  93. __hashtable_iterator() {}
  94. reference operator*() const { return cur->val; }
  95. #ifndef __SGI_STL_NO_ARROW_OPERATOR
  96. pointer operator->() const { return &(operator*()); }
  97. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
  98. iterator& operator++();
  99. iterator operator++(int);
  100. bool operator==(const iterator& it) const { return cur == it.cur; }
  101. bool operator!=(const iterator& it) const { return cur != it.cur; }
  102. };
  103. template <class Value, class Key, class HashFcn,
  104. class ExtractKey, class EqualKey, class Alloc>
  105. struct __hashtable_const_iterator {
  106. typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
  107. hashtable;
  108. typedef __hashtable_iterator<Value, Key, HashFcn,
  109. ExtractKey, EqualKey, Alloc>
  110. iterator;
  111. typedef __hashtable_const_iterator<Value, Key, HashFcn,
  112. ExtractKey, EqualKey, Alloc>
  113. const_iterator;
  114. typedef __hashtable_node<Value> node;
  115. typedef forward_iterator_tag iterator_category; // 注意
  116. typedef Value value_type;
  117. typedef ptrdiff_t difference_type;
  118. typedef size_t size_type;
  119. typedef const Value& reference;
  120. typedef const Value* pointer;
  121. const node* cur;
  122. const hashtable* ht;
  123. __hashtable_const_iterator(const node* n, const hashtable* tab)
  124. : cur(n), ht(tab) {}
  125. __hashtable_const_iterator() {}
  126. __hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}
  127. reference operator*() const { return cur->val; }
  128. #ifndef __SGI_STL_NO_ARROW_OPERATOR
  129. pointer operator->() const { return &(operator*()); }
  130. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
  131. const_iterator& operator++();
  132. const_iterator operator++(int);
  133. bool operator==(const const_iterator& it) const { return cur == it.cur; }
  134. bool operator!=(const const_iterator& it) const { return cur != it.cur; }
  135. };
  136. // 注意:假设 long 至少有 32 bits。
  137. //定义28个素数(大概是2倍关系增长),用来做hash table的大小
  138. static const int __stl_num_primes = 28;
  139. static const unsigned long __stl_prime_list[__stl_num_primes] =
  140. {
  141. 53, 97, 193, 389, 769,
  142. 1543, 3079, 6151, 12289, 24593,
  143. 49157, 98317, 196613, 393241, 786433,
  144. 1572869, 3145739, 6291469, 12582917, 25165843,
  145. 50331653, 100663319, 201326611, 402653189, 805306457,
  146. 1610612741, 3221225473ul, 4294967291ul
  147. };
  148. //找出28个素数中,最接近n且大于n的那个数
  149. inline unsigned long __stl_next_prime(unsigned long n)
  150. {
  151. const unsigned long* first = __stl_prime_list;
  152. const unsigned long* last = __stl_prime_list + __stl_num_primes;
  153. const unsigned long* pos = lower_bound(first, last, n);
  154. // 以上,lower_bound() 是泛型算法
  155. // 使用 lower_bound(),序列需先排序。上述数组以排序
  156. return pos == last ? *(last - 1) : *pos;
  157. }
  158. /*
  159. Value 节点的实值类型
  160. Key 节点的键值类型
  161. HashFcn hash function的类型
  162. EqualKey从节点中取出键值的方法(函数或仿函数)
  163. EqualKey判断键值是否相同的方法(函数或仿函数)
  164. */
  165. template <class Value, class Key, class HashFcn,
  166. class ExtractKey, class EqualKey,
  167. class Alloc> // 最上面已经说明:默认使用 alloc 空间配置器。
  168. class hashtable {
  169. public:
  170. //为 template 类型参数重新定义一个名称(貌似没必要)
  171. typedef Key key_type;
  172. typedef Value value_type;
  173. typedef HashFcn hasher;//hash函数
  174. typedef EqualKey key_equal;
  175. typedef size_t size_type;
  176. typedef ptrdiff_t difference_type;
  177. typedef value_type* pointer;
  178. typedef const value_type* const_pointer;
  179. typedef value_type& reference;
  180. typedef const value_type& const_reference;
  181. hasher hash_funct() const { return hash; }
  182. key_equal key_eq() const { return equals; }
  183. private:
  184. //以下三个都是 function objects。。、<stl_hash_fun.h>中定义了几个
  185. //标准类型(如int,c-style string等)的 hasher。
  186. hasher hash;
  187. key_equal equals;
  188. ExtractKey get_key;
  189. typedef __hashtable_node<Value> node;
  190. typedef simple_alloc<node, Alloc> node_allocator;
  191. vector<node*,Alloc> buckets; // 以 vector 完成
  192. size_type num_elements;//hash table中节点的个数
  193. public:
  194. typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
  195. Alloc>
  196. iterator;
  197. typedef __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
  198. Alloc>
  199. const_iterator;
  200. friend struct
  201. __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
  202. friend struct
  203. __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
  204. public:
  205. //没有默认的构造函数
  206. hashtable(size_type n,
  207. const HashFcn& hf,
  208. const EqualKey& eql,
  209. const ExtractKey& ext)
  210. : hash(hf), equals(eql), get_key(ext), num_elements(0)
  211. {
  212. initialize_buckets(n);
  213. }
  214. hashtable(size_type n,
  215. const HashFcn& hf,
  216. const EqualKey& eql)
  217. : hash(hf), equals(eql), get_key(ExtractKey()), num_elements(0)
  218. {
  219. initialize_buckets(n);
  220. }
  221. hashtable(const hashtable& ht)
  222. : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements(0)
  223. {
  224. copy_from(ht);
  225. }
  226. hashtable& operator= (const hashtable& ht)
  227. {
  228. if (&ht != this) { //防止自身赋值
  229. clear(); // 先清除自己
  230. hash = ht.hash; // 以下三个动作,将三份data members 复制过来。
  231. equals = ht.equals;
  232. get_key = ht.get_key;
  233. copy_from(ht); // 完整赋值整个 hash table的内容。
  234. }
  235. return *this;
  236. }
  237. ~hashtable() { clear(); }
  238. size_type size() const { return num_elements; }
  239. size_type max_size() const { return size_type(-1); }
  240. bool empty() const { return size() == 0; }
  241. void swap(hashtable& ht)
  242. {
  243. __STD::swap(hash, ht.hash);
  244. __STD::swap(equals, ht.equals);
  245. __STD::swap(get_key, ht.get_key);
  246. buckets.swap(ht.buckets);
  247. __STD::swap(num_elements, ht.num_elements);
  248. }
  249. iterator begin()
  250. {
  251. for (size_type n = 0; n < buckets.size(); ++n)
  252. //找出第一个被使用的节点,此即 begin iterator。
  253. if (buckets[n])
  254. return iterator(buckets[n], this);
  255. return end();
  256. }
  257. //最后被使用节点的下个位置,所以使用0来初始化迭代器
  258. iterator end() { return iterator(0, this); }
  259. const_iterator begin() const
  260. {
  261. for (size_type n = 0; n < buckets.size(); ++n)
  262. if (buckets[n])
  263. return const_iterator(buckets[n], this);
  264. return end();
  265. }
  266. const_iterator end() const { return const_iterator(0, this); }
  267. friend bool
  268. operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
  269. public:
  270. // bucket 个数即 buckets vector 的大小
  271. size_type bucket_count() const { return buckets.size(); }
  272. //以目前情况(不重建表格),总共可以有多少个 buckets
  273. size_type max_bucket_count() const
  274. { return __stl_prime_list[__stl_num_primes - 1]; }
  275. // 某一个 bucket (内含一个list) 容纳多少个元素
  276. size_type elems_in_bucket(size_type bucket) const
  277. {
  278. size_type result = 0;
  279. for (node* cur = buckets[bucket]; cur; cur = cur->next)
  280. result += 1;
  281. return result;
  282. }
  283. //安插元素,不允许重复
  284. pair<iterator, bool> insert_unique(const value_type& obj)
  285. {
  286. resize(num_elements + 1); // 判断是否需要重建表格,如果需要就填充
  287. return insert_unique_noresize(obj);
  288. }
  289. // 安插元素,允许重复
  290. iterator insert_equal(const value_type& obj)
  291. {
  292. resize(num_elements + 1);
  293. return insert_equal_noresize(obj);
  294. }
  295. pair<iterator, bool> insert_unique_noresize(const value_type& obj);
  296. iterator insert_equal_noresize(const value_type& obj);
  297. #ifdef __STL_MEMBER_TEMPLATES
  298. //插入两个迭代器之间的元素[f l)
  299. template <class InputIterator>
  300. void insert_unique(InputIterator f, InputIterator l)
  301. {
  302. insert_unique(f, l, iterator_category(f));
  303. }
  304. template <class InputIterator>
  305. void insert_equal(InputIterator f, InputIterator l)
  306. {
  307. insert_equal(f, l, iterator_category(f));
  308. }
  309. template <class InputIterator>
  310. void insert_unique(InputIterator f, InputIterator l,
  311. input_iterator_tag)
  312. {
  313. for ( ; f != l; ++f)
  314. insert_unique(*f);
  315. }
  316. template <class InputIterator>
  317. void insert_equal(InputIterator f, InputIterator l,
  318. input_iterator_tag)
  319. {
  320. for ( ; f != l; ++f)
  321. insert_equal(*f);
  322. }
  323. template <class ForwardIterator>
  324. void insert_unique(ForwardIterator f, ForwardIterator l,
  325. forward_iterator_tag)
  326. {
  327. size_type n = 0;
  328. distance(f, l, n);//判断两个迭代器的距离,n是引用传递
  329. resize(num_elements + n); // 判断(并实施)表格的重建
  330. for ( ; n > 0; --n, ++f)
  331. insert_unique_noresize(*f); // 一一安插新元素
  332. }
  333. template <class ForwardIterator>
  334. void insert_equal(ForwardIterator f, ForwardIterator l,
  335. forward_iterator_tag)
  336. {
  337. size_type n = 0;
  338. distance(f, l, n);
  339. resize(num_elements + n);
  340. for ( ; n > 0; --n, ++f)
  341. insert_equal_noresize(*f); // 一一安插新元素
  342. }
  343. #else /* __STL_MEMBER_TEMPLATES */
  344. void insert_unique(const value_type* f, const value_type* l)
  345. {
  346. //可以直接计算迭代器之间的距离,应该是rando access iterator
  347. size_type n = l - f;
  348. resize(num_elements + n);
  349. for ( ; n > 0; --n, ++f)
  350. insert_unique_noresize(*f);
  351. }
  352. void insert_equal(const value_type* f, const value_type* l)
  353. {
  354. size_type n = l - f;
  355. resize(num_elements + n);
  356. for ( ; n > 0; --n, ++f)
  357. insert_equal_noresize(*f);
  358. }
  359. void insert_unique(const_iterator f, const_iterator l)
  360. {
  361. size_type n = 0;
  362. distance(f, l, n);
  363. resize(num_elements + n);
  364. for ( ; n > 0; --n, ++f)
  365. insert_unique_noresize(*f);
  366. }
  367. void insert_equal(const_iterator f, const_iterator l)
  368. {
  369. size_type n = 0;
  370. distance(f, l, n);
  371. resize(num_elements + n);
  372. for ( ; n > 0; --n, ++f)
  373. insert_equal_noresize(*f);
  374. }
  375. #endif /*__STL_MEMBER_TEMPLATES */
  376. reference find_or_insert(const value_type& obj);
  377. iterator find(const key_type& key)
  378. {
  379. size_type n = bkt_num_key(key); // 首先找到落在哪个bucket内
  380. node* first;
  381. //从bucket list的头开始,一一对比每个元素的键值。
  382. for ( first = buckets[n];
  383. first && !equals(get_key(first->val), key);
  384. first = first->next)
  385. {}
  386. return iterator(first, this);
  387. }
  388. const_iterator find(const key_type& key) const
  389. {
  390. size_type n = bkt_num_key(key);
  391. const node* first;
  392. for ( first = buckets[n];
  393. first && !equals(get_key(first->val), key);
  394. first = first->next)
  395. {}
  396. return const_iterator(first, this);
  397. }
  398. //查看hash table中含有多少个值为key的元素
  399. size_type count(const key_type& key) const
  400. {
  401. const size_type n = bkt_num_key(key);
  402. size_type result = 0;
  403. // 以下,从bucket list 的头开始,一一比对每个素的键值。比对成功就累加1。
  404. for (const node* cur = buckets[n]; cur; cur = cur->next)
  405. if (equals(get_key(cur->val), key))
  406. ++result;
  407. return result;
  408. }
  409. pair<iterator, iterator> equal_range(const key_type& key);
  410. pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
  411. size_type erase(const key_type& key);
  412. void erase(const iterator& it);
  413. void erase(iterator first, iterator last);
  414. void erase(const const_iterator& it);
  415. void erase(const_iterator first, const_iterator last);
  416. void resize(size_type num_elements_hint);
  417. void clear();
  418. private:
  419. // 寻找STL中提供的下一个质数
  420. size_type next_size(size_type n) const { return __stl_next_prime(n); }
  421. // 注意,hash_vec 和 hash_map 都將其底層的 hash table 的初始大小預設為 100
  422. // hash_vec 和 hash_map 都将底层的 hash table初始化大小预设为100
  423. void initialize_buckets(size_type n)
  424. {
  425. //例如:传入100,返回193。以下首先保留193个元素空间,然后将其全部填0。
  426. //例如:传入50,返回53。以下首先保留53个元素空间,然后将其全部填0。
  427. const size_type n_buckets = next_size(n);
  428. buckets.reserve(n_buckets);
  429. buckets.insert(buckets.end(), n_buckets, (node*) 0);
  430. num_elements = 0;
  431. }
  432. size_type bkt_num_key(const key_type& key) const
  433. {
  434. return bkt_num_key(key, buckets.size());
  435. }
  436. size_type bkt_num(const value_type& obj) const
  437. {
  438. return bkt_num_key(get_key(obj));
  439. }
  440. size_type bkt_num_key(const key_type& key, size_t n) const
  441. {
  442. return hash(key) % n;
  443. }
  444. size_type bkt_num(const value_type& obj, size_t n) const
  445. {
  446. return bkt_num_key(get_key(obj), n);
  447. }
  448. node* new_node(const value_type& obj)
  449. {
  450. node* n = node_allocator::allocate();//配置空间
  451. n->next = 0;//指针next设置为NULL
  452. __STL_TRY {
  453. construct(&n->val, obj);//构建元素
  454. return n;
  455. }
  456. //commit or rollback
  457. __STL_UNWIND(node_allocator::deallocate(n));
  458. }
  459. void delete_node(node* n)
  460. {
  461. destroy(&n->val);//析构
  462. node_allocator::deallocate(n);//释放空间
  463. }
  464. void erase_bucket(const size_type n, node* first, node* last);
  465. void erase_bucket(const size_type n, node* last);
  466. void copy_from(const hashtable& ht);
  467. };
  468. template <class V, class K, class HF, class ExK, class EqK, class A>
  469. __hashtable_iterator<V, K, HF, ExK, EqK, A>&
  470. __hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++()
  471. {
  472. const node* old = cur;
  473. cur = cur->next; // 如果存在,就是它。否则进入以下 if 流程
  474. if (!cur) {
  475. // 根据原值,重新定位。从该位置(bucket)的下一个位置找起。
  476. size_type bucket = ht->bkt_num(old->val);
  477. while (!cur && ++bucket < ht->buckets.size()) // 注意,prefix operator++
  478. cur = ht->buckets[bucket];
  479. }
  480. return *this;
  481. }
  482. template <class V, class K, class HF, class ExK, class EqK, class A>
  483. inline __hashtable_iterator<V, K, HF, ExK, EqK, A>
  484. __hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
  485. {
  486. iterator tmp = *this;
  487. ++*this; // 调用 operator++()
  488. return tmp;
  489. }
  490. template <class V, class K, class HF, class ExK, class EqK, class A>
  491. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>&
  492. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++()
  493. {
  494. const node* old = cur;
  495. cur = cur->next;
  496. if (!cur) {
  497. size_type bucket = ht->bkt_num(old->val);
  498. while (!cur && ++bucket < ht->buckets.size())
  499. cur = ht->buckets[bucket];
  500. }
  501. return *this;
  502. }
  503. template <class V, class K, class HF, class ExK, class EqK, class A>
  504. inline __hashtable_const_iterator<V, K, HF, ExK, EqK, A>
  505. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
  506. {
  507. const_iterator tmp = *this;
  508. ++*this;
  509. return tmp;
  510. }
  511. #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
  512. template <class V, class K, class HF, class ExK, class EqK, class All>
  513. inline forward_iterator_tag
  514. iterator_category(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
  515. {
  516. return forward_iterator_tag();
  517. }
  518. template <class V, class K, class HF, class ExK, class EqK, class All>
  519. inline V* value_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
  520. {
  521. return (V*) 0;
  522. }
  523. template <class V, class K, class HF, class ExK, class EqK, class All>
  524. inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
  525. distance_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
  526. {
  527. return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;
  528. }
  529. template <class V, class K, class HF, class ExK, class EqK, class All>
  530. inline forward_iterator_tag
  531. iterator_category(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
  532. {
  533. return forward_iterator_tag();
  534. }
  535. template <class V, class K, class HF, class ExK, class EqK, class All>
  536. inline V*
  537. value_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
  538. {
  539. return (V*) 0;
  540. }
  541. template <class V, class K, class HF, class ExK, class EqK, class All>
  542. inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
  543. distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
  544. {
  545. return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;
  546. }
  547. #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
  548. //判断两个hash table是否相等(两个hasn table的 buckets相同,且
  549. //bucket对应的list相同)
  550. template <class V, class K, class HF, class Ex, class Eq, class A>
  551. bool operator==(const hashtable<V, K, HF, Ex, Eq, A>& ht1,
  552. const hashtable<V, K, HF, Ex, Eq, A>& ht2)
  553. {
  554. typedef typename hashtable<V, K, HF, Ex, Eq, A>::node node;
  555. if (ht1.buckets.size() != ht2.buckets.size())
  556. return false;
  557. for (int n = 0; n < ht1.buckets.size(); ++n) {
  558. node* cur1 = ht1.buckets[n];
  559. node* cur2 = ht2.buckets[n];
  560. for ( ; cur1 && cur2 && cur1->val == cur2->val;
  561. cur1 = cur1->next, cur2 = cur2->next)
  562. {}
  563. if (cur1 || cur2)//如果cur1或cur2有一个不等于0(没有指向最后位置的下一个位置)
  564. return false;
  565. }
  566. return true;
  567. }
  568. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  569. template <class Val, class Key, class HF, class Extract, class EqKey, class A>
  570. inline void swap(hashtable<Val, Key, HF, Extract, EqKey, A>& ht1,
  571. hashtable<Val, Key, HF, Extract, EqKey, A>& ht2) {
  572. ht1.swap(ht2);
  573. }
  574. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  575. //在不重建表格的情况下安插新节点。键值不允许重复。返回pair。第二个参数指出
  576. //插入是否成功
  577. template <class V, class K, class HF, class Ex, class Eq, class A>
  578. pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool>
  579. hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)
  580. {
  581. const size_type n = bkt_num(obj); // 決定obj位于哪个buckets中
  582. node* first = buckets[n]; // 令 first 指向 bucket 对应串列头部
  583. // 如果 buckets[n] 已被占用,此时first 将不为0,于是进入以下循环,
  584. // 遍历bucket对应的整个链表
  585. for (node* cur = first; cur; cur = cur->next)
  586. if (equals(get_key(cur->val), get_key(obj)))
  587. // 如果发现链表中的某键值相同,就不安插,立刻回返。
  588. return pair<iterator, bool>(iterator(cur, this), false);
  589. //离开以上循环(或没进入循环),first指向指向bucket所指链表的头部节点
  590. node* tmp = new_node(obj); // 生成新节点并赋值
  591. tmp->next = first; //更改新节点指针
  592. buckets[n] = tmp; // 新节点称为bucket链表第一个节点
  593. ++num_elements; // 节点个诉累加1
  594. return pair<iterator, bool>(iterator(tmp, this), true);
  595. }
  596. //在不重建表格的情况下安插新节点。键值不允许重复。
  597. template <class V, class K, class HF, class Ex, class Eq, class A>
  598. typename hashtable<V, K, HF, Ex, Eq, A>::iterator
  599. hashtable<V, K, HF, Ex, Eq, A>::insert_equal_noresize(const value_type& obj)
  600. {
  601. const size_type n = bkt_num(obj);
  602. node* first = buckets[n];
  603. // 如果 buckets[n] 已被佔用,此時first 將不為0,於是進入以下迴圈,
  604. // 走過 bucket 所對應的整個串列。
  605. for (node* cur = first; cur; cur = cur->next)
  606. if (equals(get_key(cur->val), get_key(obj))) {
  607. // 如果发现链表中键值相同,马上插入,然后返回
  608. //插到键值相同节点的后面
  609. node* tmp = new_node(obj);
  610. tmp->next = cur->next;
  611. cur->next = tmp;
  612. ++num_elements;
  613. return iterator(tmp, this); // 返回迭代器,指向新插入的节点
  614. }
  615. // 运行到此处,没有键值重复。
  616. node* tmp = new_node(obj);
  617. tmp->next = first;
  618. buckets[n] = tmp;
  619. ++num_elements;
  620. return iterator(tmp, this);
  621. }
  622. //如果存在obj节点则返回指向其节点的迭代器,否则插入
  623. template <class V, class K, class HF, class Ex, class Eq, class A>
  624. typename hashtable<V, K, HF, Ex, Eq, A>::reference
  625. hashtable<V, K, HF, Ex, Eq, A>::find_or_insert(const value_type& obj)
  626. {
  627. resize(num_elements + 1);
  628. size_type n = bkt_num(obj);
  629. node* first = buckets[n];
  630. for (node* cur = first; cur; cur = cur->next)
  631. if (equals(get_key(cur->val), get_key(obj)))
  632. return cur->val;
  633. node* tmp = new_node(obj);
  634. tmp->next = first;
  635. buckets[n] = tmp;
  636. ++num_elements;
  637. return tmp->val;
  638. }
  639. template <class V, class K, class HF, class Ex, class Eq, class A>
  640. pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator,
  641. typename hashtable<V, K, HF, Ex, Eq, A>::iterator>
  642. hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key)
  643. {
  644. typedef pair<iterator, iterator> pii;
  645. const size_type n = bkt_num_key(key);
  646. for (node* first = buckets[n]; first; first = first->next) {
  647. if (equals(get_key(first->val), key)) {
  648. for (node* cur = first->next; cur; cur = cur->next)
  649. if (!equals(get_key(cur->val), key))
  650. return pii(iterator(first, this), iterator(cur, this));
  651. for (size_type m = n + 1; m < buckets.size(); ++m)
  652. if (buckets[m])
  653. return pii(iterator(first, this),
  654. iterator(buckets[m], this));
  655. return pii(iterator(first, this), end());
  656. }
  657. }
  658. return pii(end(), end());
  659. }
  660. //查找键值等于key的区间。pair两个元素类型都是迭代器类型
  661. //一个指向区间起始位置,一个指向区间结束的下一个位置。
  662. template <class V, class K, class HF, class Ex, class Eq, class A>
  663. pair<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator,
  664. typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator>
  665. hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const
  666. {
  667. typedef pair<const_iterator, const_iterator> pii;
  668. const size_type n = bkt_num_key(key);//先找到在哪个 buckets
  669. //bucket对应的链表中查找
  670. for (const node* first = buckets[n] ; first; first = first->next) {
  671. if (equals(get_key(first->val), key)) {//找到键值为key的起始位置
  672. for (const node* cur = first->next; cur; cur = cur->next)
  673. if (!equals(get_key(cur->val), key))
  674. return pii(const_iterator(first, this),
  675. const_iterator(cur, this));
  676. //运行到此处,说明bucket对应的链表中尾节点也是键值为key节点
  677. //那么下一个位置就是 buckets中可用的bucket链表头节点
  678. for (size_type m = n + 1; m < buckets.size(); ++m)
  679. if (buckets[m])
  680. return pii(const_iterator(first, this),
  681. const_iterator(buckets[m], this));
  682. //后面的 buckets都没用
  683. return pii(const_iterator(first, this), end());
  684. }
  685. }
  686. // hash table没有key值节点
  687. return pii(end(), end());
  688. }
  689. //擦除键值为key的节点
  690. template <class V, class K, class HF, class Ex, class Eq, class A>
  691. typename hashtable<V, K, HF, Ex, Eq, A>::size_type
  692. hashtable<V, K, HF, Ex, Eq, A>::erase(const key_type& key)
  693. {
  694. const size_type n = bkt_num_key(key);
  695. node* first = buckets[n];//找到对应bucket链表头节点
  696. size_type erased = 0;
  697. if (first) {
  698. node* cur = first;//这里要保存前一个节点,因为是单向链表
  699. node* next = cur->next;
  700. //如果链表中多于一个节点
  701. while (next) {
  702. if (equals(get_key(next->val), key)) {
  703. cur->next = next->next;
  704. delete_node(next);
  705. next = cur->next;
  706. ++erased;
  707. --num_elements;
  708. }
  709. else {
  710. cur = next;
  711. next = cur->next;
  712. }
  713. }
  714. //链表中只有一个节点
  715. if (equals(get_key(first->val), key)) {
  716. buckets[n] = first->next;
  717. delete_node(first);
  718. ++erased;
  719. --num_elements;
  720. }
  721. }
  722. return erased;
  723. }
  724. template <class V, class K, class HF, class Ex, class Eq, class A>
  725. void hashtable<V, K, HF, Ex, Eq, A>::erase(const iterator& it)
  726. {
  727. if (node* const p = it.cur) {
  728. const size_type n = bkt_num(p->val);
  729. node* cur = buckets[n];
  730. if (cur == p) {
  731. buckets[n] = cur->next;
  732. delete_node(cur);
  733. --num_elements;
  734. }
  735. else {
  736. node* next = cur->next;
  737. while (next) {
  738. if (next == p) {
  739. cur->next = next->next;
  740. delete_node(next);
  741. --num_elements;
  742. break;
  743. }
  744. else {
  745. cur = next;
  746. next = cur->next;
  747. }
  748. }
  749. }
  750. }
  751. }
  752. //擦除两个迭代器之间的元素
  753. template <class V, class K, class HF, class Ex, class Eq, class A>
  754. void hashtable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last)
  755. {
  756. size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();
  757. size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();
  758. if (first.cur == last.cur)
  759. return;
  760. else if (f_bucket == l_bucket)
  761. erase_bucket(f_bucket, first.cur, last.cur);
  762. else {
  763. erase_bucket(f_bucket, first.cur, 0);
  764. for (size_type n = f_bucket + 1; n < l_bucket; ++n)
  765. erase_bucket(n, 0);
  766. if (l_bucket != buckets.size())
  767. erase_bucket(l_bucket, last.cur);
  768. }
  769. }
  770. template <class V, class K, class HF, class Ex, class Eq, class A>
  771. inline void
  772. hashtable<V, K, HF, Ex, Eq, A>::erase(const_iterator first,
  773. const_iterator last)
  774. {
  775. erase(iterator(const_cast<node*>(first.cur),
  776. const_cast<hashtable*>(first.ht)),
  777. iterator(const_cast<node*>(last.cur),
  778. const_cast<hashtable*>(last.ht)));
  779. }
  780. template <class V, class K, class HF, class Ex, class Eq, class A>
  781. inline void
  782. hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it)
  783. {
  784. erase(iterator(const_cast<node*>(it.cur),
  785. const_cast<hashtable*>(it.ht)));
  786. }
  787. //重新配置 hash table的大小
  788. template <class V, class K, class HF, class Ex, class Eq, class A>
  789. void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_elements_hint)
  790. {
  791. const size_type old_n = buckets.size();//原来hash table大小
  792. if (num_elements_hint > old_n) { // 确定真的需要重新配置
  793. const size_type n = next_size(num_elements_hint); // 找出下一个质数
  794. //下个这个判断没必要了吧?因为n>=num_elements_hint,而num_elements_hint>=old_n
  795. if (n > old_n) {
  796. vector<node*, A> tmp(n, (node*) 0); // 设立新的 buckets
  797. __STL_TRY {
  798. // 下面处理每一个旧的bucket
  799. for (size_type bucket = 0; bucket < old_n; ++bucket) {
  800. node* first = buckets[bucket]; // 指向节点所对应链表的起始节点
  801. // 以下處理每一個舊bucket 所含(串列)的每一個節點
  802. // 一下处理bucketliability的每一个节点
  803. while (first) { // 链表没结束
  804. // 以下找出节点落在哪一个新bucket 內
  805. size_type new_bucket = bkt_num(first->val, n);
  806. // 以下四个动作颇为巧妙
  807. // (1) 令旧 bucket 指向其所对应之链表的下一个节点(以便迭代处理)
  808. buckets[bucket] = first->next;
  809. // (2)(3) 将当前节点安插到新的bucket内,成为其对应链表的第一个节点。
  810. first->next = tmp[new_bucket];
  811. tmp[new_bucket] = first;
  812. // (4) 回到旧bucket 所指的待处理链表,准备处理下一个节点
  813. first = buckets[bucket];
  814. }
  815. }
  816. buckets.swap(tmp); // vector::swap。新旧 buckets 对调。
  817. // 注意,对调两方如果大小不同,大的会变小,小的会变大。
  818. // tmp为局部作用域,离开其作用域自动释放
  819. }
  820. # ifdef __STL_USE_EXCEPTIONS
  821. //commit or rollback
  822. catch(...) {
  823. for (size_type bucket = 0; bucket < tmp.size(); ++bucket) {
  824. while (tmp[bucket]) {
  825. node* next = tmp[bucket]->next;
  826. delete_node(tmp[bucket]);
  827. tmp[bucket] = next;
  828. }
  829. }
  830. throw;
  831. }
  832. # endif /* __STL_USE_EXCEPTIONS */
  833. }
  834. }
  835. }
  836. //擦除hash table对应第n个bucket中的一段元素[first last)
  837. template <class V, class K, class HF, class Ex, class Eq, class A>
  838. void hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n,
  839. node* first, node* last)
  840. {
  841. node* cur = buckets[n];
  842. if (cur == first)
  843. erase_bucket(n, last);
  844. else {
  845. node* next;
  846. for (next = cur->next; next != first; cur = next, next = cur->next)
  847. ;
  848. //下面应该是 while(next!=last)吧?否则last在这没用
  849. while (next) {
  850. cur->next = next->next;
  851. delete_node(next);
  852. next = cur->next;
  853. --num_elements;
  854. }
  855. }
  856. }
  857. 擦除hash table对应第n个bucket中的一段元素[buckets[n] last)
  858. template <class V, class K, class HF, class Ex, class Eq, class A>
  859. void
  860. hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last)
  861. {
  862. node* cur = buckets[n];
  863. while (cur != last) {
  864. node* next = cur->next;
  865. delete_node(cur);
  866. cur = next;
  867. buckets[n] = cur;
  868. --num_elements;
  869. }
  870. }
  871. template <class V, class K, class HF, class Ex, class Eq, class A>
  872. void hashtable<V, K, HF, Ex, Eq, A>::clear()
  873. {
  874. // 针对每一个 bucket.
  875. for (size_type i = 0; i < buckets.size(); ++i) {
  876. node* cur = buckets[i];
  877. // 将 bucket list 中的每一个节点刪除掉
  878. while (cur != 0) {
  879. node* next = cur->next;
  880. delete_node(cur);
  881. cur = next;
  882. }
  883. buckets[i] = 0; // 令bucket 內容为 null 指针
  884. }
  885. num_elements = 0; // 令总节点个数0
  886. // 注意,buckets vector 并未释放掉,仍保有原来大小。
  887. }
  888. template <class V, class K, class HF, class Ex, class Eq, class A>
  889. void hashtable<V, K, HF, Ex, Eq, A>::copy_from(const hashtable& ht)
  890. {
  891. // 先清除己方的buckets vector. 调用vector::clear.
  892. buckets.clear();
  893. //如果己方空间大于对方,就不懂,否则增大己方空间等于对方
  894. buckets.reserve(ht.buckets.size());
  895. //从己方的buckets vector尾端开始,安插n个元素,其值为NULL指针。
  896. //注意,此时buckets vector为空,所以所谓尾端就是起始处
  897. buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);
  898. __STL_TRY {
  899. // 针对 buckets vector
  900. for (size_type i = 0; i < ht.buckets.size(); ++i) {
  901. //复制 vector 的每一个元素(是个指针,指向hash table节点)
  902. //注意下面if语句,是先赋值再判断,它等价于
  903. //const node* cur = ht.buckets[i]; if(cur)
  904. if (const node* cur = ht.buckets[i]) {
  905. node* copy = new_node(cur->val);
  906. buckets[i] = copy;
  907. // 针对每一个 bucket list,复制每一个节点
  908. for (node* next = cur->next; next; cur = next, next = cur->next) {
  909. copy->next = new_node(next->val);
  910. copy = copy->next;
  911. }
  912. }
  913. }
  914. num_elements = ht.num_elements; // 重新设置节点个数(hashtable 的大小)
  915. }
  916. __STL_UNWIND(clear());
  917. }
  918. __STL_END_NAMESPACE
  919. #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */
  920. // Local Variables:
  921. // mode:C++
  922. // End:


 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/996187
推荐阅读
相关标签
  

闽ICP备14008679号