zoukankan      html  css  js  c++  java
  • 从零开始写STL—哈希表

    static const int _stl_num_primes = 28;
    	template<typename T, typename Hash = xhash<T>>
    	class hashtable;
    
    	 ministl::vector<int> prime_list = 
    	{
    		53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241,
    		786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611,
    		402653189, 805306457, 1610612741, 3221225473, 4294967291,
    	};
    
    	template<typename T>
    	class hash_iterator : public bidirectional_iterator<T>
    	{
    	public:
    		hashtable<T>* hash_ptr;
    		list_iterator<T> node_ptr;
    		list<T>* bucket_ptr;
    		hash_iterator(hashtable<T>* hp, list<T>* bp, list_iterator<T> np) :hash_ptr(hp), bucket_ptr(bp), node_ptr(np) {}
    		
    		hash_iterator& operator++()
    		{
    			if (++node_ptr == bucket_ptr->end())
    			{
    				auto tmp = node_ptr;
    				--tmp;
    				size_t cur = hash_ptr->hash(*tmp, hash_ptr->bucket_size()) + 1;
    				while (cur < hash_ptr->bucket_size() && (*hash_ptr).data[cur].empty())
    					cur++;
    				bucket_ptr = cur < hash_ptr->bucket_size() ? &(hash_ptr->data[cur]) : hash_ptr->data.end();
    				node_ptr = (bucket_ptr == hash_ptr->data.end() ? nullptr : bucket_ptr->begin());
    			}
    			return *this;
    		}
    
    		hash_iterator operator++(int)
    		{
    			hash_iterator tmp = *this;
    			++*this;
    			return tmp;
    		}
    
    		hash_iterator& operator--()
    		{
    			if (node_ptr-- = bucket_ptr->begin())
    			{
    				size_t cur = hash_ptr->hash(*node_ptr, hash_ptr->bucket_size()) - 1;
    				if (cur < 0) cur = 0;
    				else
    				{
    					while (cur >= 0 && (*hash_ptr).data[cur].empty())
    						cur--;
    				}
    				bucket_ptr = &(hash_ptr->data[cur]);
    				node_ptr =  bucket_ptr->begin();
    			}
    			return *this;
    		}
    
    		hash_iterator operator--(int)
    		{
    			hash_iterator tmp = *this;
    			--*this;
    			return tmp;
    		}
    
    		T& operator* ()
    		{
    			return *node_ptr;
    		}
    
    		bool operator==(const hash_iterator& rhs)
    		{
    			return hash_ptr == rhs.hash_ptr && node_ptr == rhs.node_ptr && bucket_ptr == rhs.bucket_ptr;
    		}
    
    		bool operator!=(const hash_iterator& rhs)
    		{
    			return !(*this == rhs);
    		}
    	};
    
    	template<typename T,typename Hash = xhash<T> >
    	class hashtable
    	{
    		friend class hash_iterator<T>;
    	public:
    		typedef T value_type;
    		typedef Hash hash_type;
    		typedef vector<list<T>> table;
    		typedef hash_iterator<T> iterator;
    	private:
    		Hash hash;
    		table data;
    		size_t elem_num;//the sum of all elements
    		pair<iterator, bool> _insert_unique_noresize(T val)
    		{
    			size_t index = hash(val, data.size());
    
    			for (auto it = data[index].begin(); it != data[index].end(); it++)
    			{
    				if (*it == val)
    					return make_pair<iterator, bool >(iterator(this, &data[index], it), false);
    			}
    			
    			data[index].push_front(val);
    			elem_num++;
    			return make_pair<iterator, bool>(iterator(this, &data[index], data[index].begin()), true);
    		}
    		
    		iterator _insert_equal_noresize(T val)
    		{
    			size_t index = hash(val, data.size());
    			for (auto it = data[index].begin(); it != data[index].end(); it++)
    			{
    				if (*it == val)
    				{
    					return iterator(this, &data[index], data[index].insert(it, val));
    				}
    			}
    			data[index].push_front(val);
    			elem_num++;
    			return iterator(this, &data[index], data[index].begin());
    		}
    
    		void initialize_buckets(size_t n)	 
    		{
    			data.resize(n);
    			elem_num = 0;
    		}
    
    	public:
    		hashtable()
    		{
    			initialize_buckets(53);
    		}
    		hashtable(size_t n)
    		{
    			initialize_buckets(next_prime(n));
    		}
    
    		void clear()
    		{
    			for (auto& it : data) 
    			{
    				it.clear();
    			}
    			elem_num = 0;
    		}
    
    		bool empty()
    		{
    			return elem_num == 0;
    		}
    
    		pair<iterator, bool>find(const T& val)
    		{
    			size_t index = hash(val, data.size());
    
    			for (auto it = data[index].begin(); it != data[index].end(); it++)
    			{
    				if (*it == val)
    					return ministl::make_pair<iterator, bool >(iterator(this, &data[index], it), true);
    			}
    
    			return ministl::make_pair<iterator, bool >(end(), false);
    		}
    
    
    		iterator begin() const
    		{
    			auto it = data.begin();
    			while (it != data.end() && it->empty())
    				it++;
    			return iterator(const_cast<hashtable<T>*>(this), it, it == data.end() ? nullptr : it->begin());
    		}
    
    		iterator begin()
    		{
    			auto it = data.begin();
    			while (it != data.end() && it->empty())
    				it++;
    			return iterator(this, it, it == data.end() ? nullptr : it->begin());
    		}
    
    		iterator end() const
    		{
    			return iterator(const_cast<hashtable<T>*>(this), data.end(), nullptr);
    		}
    
    		iterator end()
    		{
    			return iterator(this, data.end(), nullptr);
    		}
    
    
    		inline unsigned long next_prime(unsigned long n)
    		{
    			for (auto it : prime_list)
    			{
    				if (it >= n)
    					return n;
    			}
    			return prime_list[_stl_num_primes - 1];
    		}
    
    		size_t bucket_size() 
    		{
    			return data.size();
    		}
    
    		size_t bucket_size() const
    		{
    			return data.size();
    		}
    
    		size_t size()
    		{
    			return elem_num;
    		}
    		size_t hash_val(const T& val)
    		{
    			return hash(val, data.size());
    		}
    		pair<iterator, bool> insert_unique(T val)
    		{
    			rehash(elem_num + 1);
    			return _insert_unique_noresize(val);
    		}
    
    		iterator insert_equal(T val)
    		{
    			rehash(elem_num + 1);
    			return _insert_equal_noresize(val);
    		}
    
    		iterator erase_iter(iterator pos)
    		{
    			iterator ret = pos;
    			ret++;
    			pos.bucket_ptr->erase(pos.node_ptr);
    			return ret;
    		}
    
    		void erase_val(const T& val)
    		{
    			size_t index = hash(val, data.size());
    			for (auto it = data[index].begin(); it != data[index].end();)
    			{
    				if (*it == val)
    					it = data[index].erase(it);
    				else
    					it++;
    
    			}
    		}
    
    		void rehash(size_t n)
    		{
    			if (n > bucket_size())
    			{
    				elem_num = elem_num ? elem_num:1;
    				while (n > elem_num) elem_num *= 2;
    				size_t new_size = next_prime(elem_num);
    				hashtable new_table(new_size);
    				if (!empty())
    				{
    					iterator it = begin();
    					for (; it != end(); it++)
    					{
    						//std::cout << *it << std::endl;
    						new_table.insert_equal(*it);
    					}
    				}
    				swap(*this, new_table);
    			}
    		}
    
    		hashtable& operator=(const hashtable& rhs)
    		{
    			clear();
    			for (auto it = rhs.begin(); it != rhs.end(); it++)
    			{
    				insert_equal(*it);
    			}
    			return *this;
    		}
    	};
    
    	template<typename T>
    	void swap(const hashtable<T>& lhs, const hashtable<T>& rhs)
    	{
    		using ministl::swap;
    		swap(lhs.data, rhs.data);
    		swap(lhs.elem_num, rhs.elem_num);
    		swap(lhs.hash, rhs.hash);
    	}
    
    
    	template<typename T, typename Hash = xhash<T> >
    	class unordered_set
    	{
    	public:
    		typedef T value_type;
    		typedef Hash hash_type;
    		typedef vector<list<T>> table;
    		typedef hash_iterator<T> iterator;
    		typedef hashtable<T> seq;
    	private:
    		seq con;
    	public:
    		unordered_set() :con() {}
    		unordered_set(std::initializer_list<T> l)
    		{
    			unordered_set();
    			insert(l.begin(), l.end());
    		}
    		iterator begin()
    		{
    			return con.begin();
    		}
    
    		iterator end()
    		{
    			return con.end();
    		}
    
    		iterator find(const value_type& key)
    		{
    			return con.find(key).first;
    		}
    
    		iterator insert(const value_type& key)
    		{
    			return con.insert_unique(key).first;
    		}
    
    		iterator insert(value_type& key)
    		{
    			return con.insert_unique(key);
    		}
    		template <class InputIterator>
    		void insert(InputIterator first, InputIterator last)
    		{
    			for (auto it = first; it != last; it++)
    				insert(*it);
    		}
    
    		size_t erase(const value_type& key)
    		{
    			size_t num = count(key);
    			if(num)
    				con.erase_val(key);
    			return num;
    		}
    
    		iterator erase(const iterator it)
    		{
    			return con.erase_iter(it);
    		}
    
    		iterator erase(const iterator first, const iterator last)
    		{
    			iterator it = first;
    			for (; it != last;)
    				it = con.erase_iter(it);
    			return it;
    		}
    
    		size_t count(const value_type& val)
    		{
    			return (con.find(val).second == true) ? 1 : 0;
    		}
    
    		bool empty()
    		{
    			return con.empty();
    		}
    
    		size_t size()
    		{
    			return con.size();
    		}
    
    		void clear()
    		{
    			con.clear();
    		}
    
    		void swap(unordered_set<T>& rhs)
    		{
    			using ministl::swap;
    			swap(con, rhs.con);
    		}
    
    		size_t bucket_count()
    		{
    			return con.bucket_size();
    		}
    
    		void rehash()
    		{
    			con.rehash(con.elem_num + 1);
    		}
    
    		double load_factor()
    		{
    			return 1.0 * con.elem_num / bucket_count();
    		}
    
    	};
    
    	//Todo: map_pair的hashval
    	//模板特化无法匹配?
    	template<typename K , typename T, typename Hash = xhash<map_pair<K,T>> >
    	class unordered_map
    	{
    	public:
    		typedef K key_type;
    		typedef T value_type;
    		typedef Hash hash_type;
    		typedef vector<list<map_pair<K,T>>> table;
    		typedef hash_iterator<map_pair<K,T>> iterator;
    		typedef hashtable<map_pair<K, T>, xhash<map_pair<K, T>> > seq;
    	private:
    		seq con;
    	public:
    		unordered_map() :con() {}
    		
    		iterator begin()
    		{
    			return con.begin();
    		}
    		iterator begin() const
    		{
    			return con.begin();
    		}
    
    		iterator end()
    		{
    			return con.end();
    		}
    		iterator end() const
    		{
    			return con.end();
    		}
    
    		value_type& operator[](const key_type& key)
    		{
    			map_pair<K, T> p(key, T());
    			auto tmp = con.find(p);
    			iterator it = tmp.first;
    			if (tmp.second == false)
    			{
    				it = con.insert_equal(p);
    			}
    			return (*it).second;
    
    		}
    
    		value_type& at(const key_type& key)
    		{
    			auto tmp = con.find(key);
    			if (tmp.second == false)
    			{
    				std::cerr << "unordered_map out of range 
    ";
    				std::exit(1);
    			}
    			return (*it).second;
    		}
    
    		const value_type& at(const key_type& key) const
    		{
    			auto tmp = con.find(key);
    			if (tmp.second == false)
    			{
    				std::cerr << "unordered_map out of range 
    ";
    				std::exit(1);
    			}
    			return (*it).second;
    		}
    
    		iterator find(const key_type& key)
    		{
    			return con.find(key).first;
    		}
    
    		pair<iterator, iterator>
    			equal_range(const key_type& k)
    		{
    			auto first = con.find(k).first;
    			if (first == con.end())
    				return make_pair<iterator, iterator>(first, first);
    			else
    			{
    				iterator last = ++first;
    				while (last != con.end() && (*last == *first))
    				{
    					last++;
    				}
    				return make_pair<iterator, iterator>(first, last);
    			}
    		}
    
    		size_t count(const key_type& k)
    		{
    			auto first = con.find(k).first;
    			if (first == con.end())
    				return 0;
    			else
    			{
    				iterator last = ++first;
    				size_t cnt = 1;
    				while (last != con.end() && (*last == *first))
    				{
    					last++, cnt++;
    				}
    				return cnt;
    			}
    		}
    
    		auto insert(const map_pair<K, T> p)
    		{
    			return con.insert_unique(p);
    		}
    
    		size_t erase(const value_type& key)
    		{
    			size_t num = count(key);
    			if (num)
    				con.erase_val(key);
    			return num;
    		}
    
    		iterator erase(const iterator it)
    		{
    			return con.erase_iter(it);
    		}
    
    		iterator erase(const iterator first, const iterator last)
    		{
    			iterator it = first;
    			for (; it != last;)
    				it = con.erase_iter(it);
    			return it;
    		}
    
    		void rehash(size_t n)
    		{
    			con.rehash(n);
    		}
    
    	};
    
  • 相关阅读:
    Python:解析PDF文本及表格——pdfminer、tabula、pdfplumber 的用法及对比
    2018数学建模国赛B题
    目标检测综述整理
    numpy实现两层layer
    应用安全
    应用安全
    应用安全
    应用安全
    应用安全
    应用安全
  • 原文地址:https://www.cnblogs.com/joeylee97/p/8877254.html
Copyright © 2011-2022 走看看