Hash table (hash list) detailed and code implementation

Source: Internet
Author: User
1. Definition:

A hash table, also known as a hash table, is a data structure that is accessed directly based on key code values (keys, value). That is, it accesses the record by mapping the key value to a location in the table to speed up the lookup. This mapping function is called a hash function, and an array of records is called a hash table. 2. Principle:

The principle of a hash table is simple:

If the keyword is k, its value is stored in the position of F (k). Thus, no comparison is required to obtain the recorded records directly. The corresponding relation f is a hash function, and the table established by this idea is a hash list. 3. Common method: Direct addressing method. Except the remainder method. The method of horizontal method is taken. Digital Analysis method. Folding method. Random number method. We often use the first two methods:
Direct addressing: A linear function value that takes a keyword or keyword as a hash address. That is, H (key) =key or H (key) = a key + B, where A and B are constants.

Excluding remainder method: A hash address is the remainder of a key value that is removed by a number p that is not greater than the hash list length m. Hash (Key) = key%p
However, both the direct address method and the remainder method produce a hash conflict, that is, different Key values are processed to get the same value.
4. Methods for resolving the Greek conflict: 1) Closed hashing method (open addressing method): His core idea was, Place the conflicting elements in another location in the hash table. The closed hashing method is divided into: linear probes and two probes    a. Linear probing: thinking: Move the conflicting elements backward from the current position, Move to the first encountered empty position. Assuming that the hash table has a length of 10, we have 5 data 79,28,39,48,9 respectively. Insert the remainder method into a hash table, as follows: inserted coordinates =key value% table Length 9% = 8;% = 9;% = 8; 9 & 10 = 9; From the calculation of the results known, 79,39,9, the insertion of the position conflict. 28,48 the location of the insertion conflict.
   b. Two probes thought: Two probes and linear probes, only the size of the back shift after the collision is the square of the number of times. For example, suppose the number of moves is I. (or the use case above)

Note: the load factor for a hash list is defined as: A= fill in the number of elements in the table/hash list length. Because the table length is a fixed value, a is proportional to the number of elements in the table, so a larger size indicates that the more elements are filled in the table, the greater the likelihood of a conflict. Conversely, the smaller A is the less likely the conflict will occur. For the open addressing method, the load factor is a particularly important factor and should be strictly controlled in 0.7--0.8. 2) Open hashing method (open chain method or zipper hair): idea:
Define a hash table as an array of pointers, and each time a conflict occurs, the element is linked below the subscript.


linear probe code implementation:

#include <iostream> #include <vector> #include <string> #include <assert.h> using namespace std;

The linear probing method enum state {EMPTY, EXIST, DELETE,};
	Template<class k> struct __hashfunc {size_t operator () (const k& k) {return k;

}
}; Special template<> struct __hashfunc<string> {size_t operator () (const string& k) {return Bkdhash (K.c_st
	R ()); Static size_t Bkdhash (const char* str) {unsigned int seed = 131;//-131 1313 13131 131313 int hash = 0
		;
		while (*STR) {hash = Hash*seed + (*str++);
	Return (hash & 0x7fffffff);
}
};
	Template <class K, class v> struct Hashnode {pair<k, v> _kv;

	State _s;

Hashnode (): _s (EMPTY) {}}; Template<class K, Class V, class Hashfunc = __hashfunc<k>> class HashTable {typedef hashnode<k, v> Nod
E
	Public:hashtable (): _size (0) {} HashTable (size_t N): _size (0) {_tables.resize (n); pair<node*, bool> Insert (const pAir<k, v>& kv) {_checkcapacity ();
		size_t index = _getindex (Kv.first); while (_tables[index]._s = = EXIST) {//Check for presence if (_tables[index]._kv.first = Kv.first) return Make_pair (&
			_tables[index], false);
			++index;
		if (index = = _tables.size ()) index = 0;
		} _tables[index]._kv = kv;
		_tables[index]._s = EXIST;
		++_size;
	Return Make_pair (&_tables[index], true);
		} node* Find (const k& key) {size_t index = _getindex (key);
					while (_tables[index]._s!= EMPTY) {if (_tables[index]._kv.first = = key) {if (_tables[index]._s = = EXIST)
				Return &_tables[index]; 
			else return NULL;
			} ++index;
		if (index = = _tables.size ()) index = 0;
	return NULL;
		BOOL Remove (const k& key) {node* del = find (key);
			if (del!= NULL) {del->_s = DELETE;
			--_size;
		return true;

	return false;
		} void Print () {size_t size = _tables.size ();
for (size_t i = 0; i < size; ++i)		{if (_tables[i]._s = = EXIST) {cout << _tables[i]._kv.first << "--" <<_tables[i]._kv.second
			<< "";
	}} cout << Endl;
		} v& operator[] (const k& key) {pair<node*, bool> ret = Insert (Make_pair (Key, V ()));
	Return ((Ret.first)->_kv). Second;
		} protected:size_t _getindex (const k& key) {Hashfunc K;
	return K (key)% _tables.size ();
		} void Swap (hashtable<k, v> ht) {swap (_size, ht._size);
	_tables.swap (Ht._tables);
		} void _checkcapacity () {if (_tables.size () = = 0) {_tables.resize (53);
			else if (_size */_tables.size () = = 7) {size_t newsize = _getnextprime (_tables.size ());
			Hashtable<k, V, hashfunc> newht (newsize); for (size_t i = 0; i < _tables.size (); ++i) {if (_tables[i]._s = = EXIST) {Newht.insert (_tables[i]._kv
				);
		} this->swap (NEWHT); } size_t _getnextprime (size_t n) {const int _primesize = 28;//Below is a prime number table static const unsigned long _primelist[_primesize] = {53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 1228 9ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 251 
		65843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul
		}; for (size_t i = 0; i< _primesize. ++i) {if (n < _primelist[i]) return _primelist[i];//find the next prime number to find} AS
	SERT (FALSE);
	} protected:vector<node> _tables;
size_t _size;

};
		void Testhash () {int a[] = {89, 18, 49, 58, 9};
		Hashtable<int, int> ht; for (size_t i = 0; i < sizeof (a)/sizeof (a[0)); ++i) {ht.
		Insert (Make_pair (a[i], i)); } ht.
		Insert (Make_pair (10, 1)); Ht.
		Insert (Make_pair (11, 1)); Ht.
		Insert (Make_pair (12, 1)); Ht.
		Insert (Make_pair (13, 1)); Ht.
		Insert (Make_pair (14, 1)); Ht.
		Print (); Cout< 

Open Chain Method code implementation:
#include <iostream> #include <vector> using namespace std;
	Template <class k,class v> struct hashnode, pair<k v>;

	Hashnode<k, v>* _next;
Hashnode (const pair<k,v>& KV): _kv (KV), _next (NULL) {}};
	Template <class k> struct _hashfunc {size_t operator () (const k& key) {return key;

}
}; Special template<> struct _hashfunc<string> {size_t operator () (const string& key) {return Bkdrhash (key).
	C_str ()); Protected://String hash algorithm static size_t bkdrhash (const char* str) {unsigned int seed = 131;//31 131 1313 13131 13131
		3 unsigned int hash = 0;
		while (*STR) {hash = Hash*seed + (*str++);
	Return (hash & 0x7fffffff);

}
};

Declare Template<class K, Class V, Class Hashfunc> class Hashtablebucket; Template<class K, Class V, Class Hashfunc, Class Valuetypeptr, class valuetyperef> struct __hashtableiterator {typ
	Edef hashnode<k, v> Node; typedef __hashtableiterator< K, V, Hashfunc, valuetypeptr, valuetyperef> Self;
	Node* _node;

	Hashtablebucket<k, V, hashfunc>* _ht; __hashtableiterator (node* node, hashtablebucket<k, V, hashfunc>* ht): _node (node), _HT (HT) {} valuetyperef O
	Perator* () {return _node->_kv;
	} valuetypeptr operator-> () {return & (operator* ());
	BOOL operator = = (const self& s) Const {return _node = = S._node;
	BOOL operator!= (const self& s) Const {return _node!= s._node;
		} self& operator++ () {_node = _next (_node);
	return *this;
		} protected:node* _next (node* Node) {node* Next = node->_next;
		if (next) return to next;
			else {size_t index = _ht->_hashfunc (Node->_kv.first) + 1;
				for (; index < _ht->_tables.size (); ++index) {next = _ht->_tables[index];
			if (next) return to next;
	} return NULL;

}
}; Template<class k,class V,class hashfunc=_hashfunc<k>> class Hashtablebucket {Public:typedef hashnode<k, v> Node;
	typedef __hashtableiterator<k, V, Hashfunc, Pair<k, v>*, pair<k, v>&> iterator;
Friend iterator;
	Public:hashtablebucket (): _size (0) {} hashtablebucket (const size_t N): _size (0) {_tables.resize (n);
		} ~hashtablebucket () {_clear ();
	_size = 0;
		} v& operator[] (const k& key) {pair<node*,bool> ret = Insert (Make_pair (Key, V ()));
	Return ((Ret.first)->_kv). Second;
		Pair<node*,bool> Insert (const pair<k, v>& kv) {_check ();
		size_t index = _hashfunc (Kv.first);
		
		node* cur = _tables[index];
			while (cur) {if (Cur->_kv.first = = Kv.first) {return Make_pair (cur, false);
		} cur = cur->_next;
		}//Header node* NewNode = new Node (KV);
		Newnode->_next = _tables[index];
		_tables[index] = NewNode;
		++_size;
	Return Make_pair (_tables[index], true);
		} node* Find (const k& key) {size_t index = _hashfunc (key);
node* cur = _tables[index];		while (cur) {if (Cur->_kv.first = = key) return cur;
		Cur = cur->_next;
	return false;
		BOOL Remove (const k& key) {size_t index = _hashfunc (key);
		node* cur = _tables[index];
		node* parent = NULL;
		if (cur = NULL) return false; while (cur) {if (Cur->_kv.first = = key) {if (cur = = _tables[index]) {_tables[index] = Cur->_
				Next
				else {Parent->_next = cur->_next;
				} Delete cur;
				cur = NULL;
				--_size;
			Break
			parent = cur;
		Cur = cur->_next;
	return false;
			void Print () {for (size_t i = 0; i < _tables.size (); ++i) {node* cur = _tables[i];
				while (cur) {cout << cur->_kv.first << "";
			Cur = cur->_next;
	}} cout << Endl;
			Iterator Begin () {for (size_t i = 0; i < _tables.size (); ++i) {node* cur = _tables[i];
		if (cur) return iterator (cur, this);
	Return iterator (NULL, this);} iterator End () {return iterator (NULL, this); } protected:void _check () {if (_tables.size () = 0 | | _size/_tables.size () >= 1) {size_t newsize = _getp
			Rimenum (_tables.size ());
			Hashtablebucket<k, V, hashfunc> newtable (newsize);
				for (size_t i = 0; i < _tables.size (); ++i) {node* cur = _tables[i];
					while (cur) {Newtable.insert (Make_pair ((CUR-&GT;_KV). a), ((CUR-&GT;_KV). second));
				Cur = cur->_next;
		} _swap (newtable);
		} void _swap (hashtablebucket<k,v,hashfunc>& ht) {Swap (_size, ht._size);
	_tables.swap (Ht._tables);
		} size_t _hashfunc (const k& key) {HASHFUNC HF;
	return HF (key)% _tables.size ();
		} size_t _getprimenum (const size_t& SZ) {const int primesize = 28; static const unsigned long primenum[primesize] = {53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289u L, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 161
		0612741ul, 3221225473ul, 4294967291ul};
			for (int i = 0; i < primesize ++i) {if (Primenum[i] > SZ) {return primenum[i];
	} return to SZ;
			} void _clear () {for (size_t i = 0; i < _tables.size (); ++i) {node* cur = _tables[i];
				while (cur) {node* del = cur;
				Cur = cur->_next;
			Delete del;
		} _tables[i] = NULL;
	}} protected:vector<node*> _tables;
size_t _size;

};
	void Testhashtablebucket () {int a[] = {89, 18, 49, 58, 9};
	Hashtablebucket<int, int> ht; for (size_t i = 0; i < sizeof (a)/sizeof (a[0)); ++i) {ht.
	Insert (Make_pair (A[i], 1)); } ht.
	Insert (Make_pair (10, 1)); Ht.
	Insert (Make_pair (53, 1)); Ht.
	Insert (Make_pair (54, 1)); Ht.
	Insert (Make_pair (55, 1)); Ht.
	Insert (Make_pair (56, 1)); Ht.
	Insert (Make_pair (106, 1)); Ht.
	Insert (Make_pair (212, 1)); Ht.

	Print (); HashtablebUcket<int, int, _hashfunc<int>>::iterator it = ht.
	Begin (); while (it!= ht.
	End ()) {cout << it->first << "";
	++it;

	} cout << Endl; Ht.
	Remove (53); Ht.
	Remove (212); Ht.
	Remove (106); Ht.
	Remove (49); Ht.

	Print ();
	Hashtablebucket<string, string,_hashfunc<string>> ht1; Ht1.
	Insert (Make_pair ("left", "left-hand")); Ht1.
	Insert (Make_pair ("left", "remainder"));
	Ht1["Left" = "remaining"; Hashtablebucket<string, String, _hashfunc<string>>::iterator it1 = ht1.
	Begin (); while (It1!= ht1.
		End ()) {cout << (it1->first). C_STR () << "";
	++it1;
} cout << Endl;
	int main () {testhashtablebucket ();
	System ("pause");
return 0; }



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.