国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例

這篇具有很好參考價值的文章主要介紹了C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

本文將介紹如何使用哈希表來實現(xiàn)C++ STL庫中的unordered_map和unordered_set容器。我們將會解釋哈希表的基本原理,并給出具體的代碼示例,幫助讀者更好地理解和應(yīng)用哈希表。

哈希原理講解–鏈接入口

set和map的實現(xiàn)的文章,與unordered_map實現(xiàn)類似

對HashTable的改造

#pragma once

template<class K>
struct Hashfunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};
//特化
template<>
struct Hashfunc<string>
{
	size_t operator()(const string& s)
	{
		size_t hash = 0;
		for (auto a : s)
		{
			hash += a;
			hash *= 31;
		}
		return hash;
	}
};



namespace hash_bucket
{
	template <class T>
	struct HashNode
	{
		HashNode<T>* _next;
		T _data;

		HashNode(const T& data)
			:_next(nullptr),
			_data(data)
		{}
		
	};

	// 前置聲明
	template<class K, class T, class KeyOfT, class Hash>
	class HashTable;

	template<class K, class T, class KeyOfT, class Hash>
	struct _HTIterator
	{
		typedef HashNode<T> Node;
		typedef HashTable<K, T, KeyOfT, Hash> HT;
		typedef _HTIterator<K, T, KeyOfT, Hash> Self;

		Node* _node;
		HT* _ht;

		_HTIterator(Node* node,HT* ht)
			:_node(node),
			_ht(ht)
		{}

		T& operator*()
		{
			return _node->_data;
		}

		T* operator->()
		{
			return &_node->_data;
		}

		Self& operator++()
		{
			if (_node->_next)
			{
				_node = _node->_next;
			}
			else
			{
				KeyOfT kot;
				Hash hs;
				size_t hashi = hs(kot(_node->_data)) % _ht->_tables.size();

				hashi++;
				//循環(huán)找出存在的哈希桶位置;
				while (hashi < _ht->_tables.size())
				{
					if (_ht->_tables[hashi])
					{
						_node = _ht->_tables[hashi];
						break;
					}

					hashi++;
				}

				if (hashi == _ht->_tables.size())
				{
					_node = nullptr;
				}

				return *this;
			}
		}
			bool operator!=(const Self & s)
			{
				return _node != s._node;
			}

			bool operator ==(const Self& s)
			{
				return _node == s._node;
			}
		
	};

	template<class K,class T,class KeyOfT, class Hash>
	class HashTable
	{
		template<class K,class T,class KeyOfT,class Hash>
		friend struct _HTIterator;

		typedef HashNode<T> Node;
	public:
		typedef _HTIterator<K, T, KeyOfT, Hash> iterator;
		
		iterator begin()
		{
			for (size_t i = 0; i < _tables.size(); i++)
			{
				// 找到第一個桶的第一個節(jié)點
				if (_tables[i])
				{
					return iterator(_tables[i], this);
				}
			}

			return end();
		}

		iterator end()
		{
			return iterator(nullptr, this);
		}
		
		HashTable()
		{
			_tables.resize(10, nullptr);
			_n = 0;
		}

		~HashTable()
		{
			for (size_t i= 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}
				_tables[i] = nullptr;
			}
		}

		iterator Find(const K& key)
		{
			KeyOfT kot;
			Hash hs;
			size_t hashi = hs(key) % _tables.size();
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (kot(cur->_data) == key)
				{
					return iterator(cur,this);
				}

				cur=cur->_next;
			}

			return iterator(nullptr,this);
		}

 		pair<iterator,bool> Insert(const T& data)
		{
			KeyOfT kot;
			Hash hs;
			//查找是否有相同元素
			iterator it = Find(kot(data));
			if (it != end())
				return make_pair(it,false);

			//擴容
			if (_n == _tables.size())
			{
				vector<Node*> newTables(_tables.size() * 2, nullptr);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					Node* cur = _tables[i];
					while (cur)
					{
						Node* next = cur->_next;

						size_t hashi = hs(kot(cur->_data)) % newTables.size();
						cur->_next = newTables[hashi];
						newTables[hashi] = cur;

						cur = next;
					}
					_tables[i] = nullptr;
				}
				_tables.swap(newTables);
			}	

			size_t hashi = hs(kot(data)) % _tables.size();
			Node* newnode = new Node(data);
			it = iterator(newnode, this);
			newnode->_next = _tables[hashi];
			_tables[hashi] = newnode;

			++_n;
			return make_pair(it,true);
		}

		bool Erase(const K& key)
		{
			KeyOfT kot;
			Hash hs;
			size_t hashi = hs(key) % _tables.size();
			Node* prev = nullptr;
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (kot(cur->_data)==key)
				{
					if (prev)
					{
						prev->_next = cur->_next;
					}
					else
					{
						_tables[hashi] = cur->_next;
					}
					delete cur;
					_n--;
					return true;
				}
				prev = cur;
				cur = cur->_next;
			}
			return false;
		}
	private:
		vector<Node*> _tables;
		size_t _n;
	};
}

C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set

對unordered_map和unordered_set的實現(xiàn)

unordered_set是一種集合存儲的容器,它存儲唯一的元素。我們同樣可以使用哈希表來實現(xiàn)unordered_set,將元素映射到數(shù)組的索引。

  • 插入操作:通過哈希函數(shù)計算元素的索引,如果索引位置為空,則直接插入;否則,使用開放地址法尋找下一個可用的槽進行插入。
  • 查找操作:通過哈希函數(shù)計算元素的索引,然后比較該索引位置的元素是否與目標(biāo)元素相等,如相等則返回存在;如不相等,則使用開放地址法依次查找下一個槽,直到找到相等的元素或者遇到空槽為止。
  • 刪除操作:通過哈希函數(shù)計算元素的索引,然后通過循環(huán)找到對應(yīng)的元素,如果這個元素有前一個結(jié)點,那么就讓前一個結(jié)點鏈上當(dāng)前結(jié)點的下一個結(jié)點,然后刪除當(dāng)前結(jié)點;如果當(dāng)前元素沒有前一個結(jié)點,那么就表示刪除該節(jié)點后,哈希桶的頭結(jié)點將為空;
namespace fnc
{
	template<class K,class Hash=Hashfunc<K>>
	class unordered_set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};

	public:
		typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::iterator iterator;

		iterator begin()
		{
			return _ht.begin();
		}

		iterator end()
		{
			return _ht.end();
		}

		pair<iterator,bool> insert(const K& k)
		{
			return _ht.Insert(k);
		}

		iterator find(const K& k)
		{
			return _ht.Find(k);
		}

		bool Erase(const K& k)
		{
			return _ht.Erase(k);
		}


	private:
		hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;
		
	};
}

unordered_map是一種鍵值對存儲的容器,它允許通過鍵快速查找對應(yīng)的值。我們可以使用哈希表來實現(xiàn)unordered_map,將鍵映射到數(shù)組的索引,值存儲在對應(yīng)的槽中。

  • 插入操作:通過哈希函數(shù)計算鍵的索引,如果索引位置為空,則直接插入;否則,使用開放地址法尋找下一個可用的槽進行插入。
  • 查找操作:通過哈希函數(shù)計算鍵的索引,然后比較該索引位置的鍵是否與目標(biāo)鍵相等,如相等則返回對應(yīng)的值;如不相等,則使用開放地址法依次查找下一個槽,直到找到相等的鍵或者遇到空槽為止。
  • 刪除操作:通過哈希函數(shù)計算元素的索引,然后通過循環(huán)找到對應(yīng)的元素,如果這個元素有前一個結(jié)點,那么就讓前一個結(jié)點鏈上當(dāng)前結(jié)點的下一個結(jié)點,然后刪除當(dāng)前結(jié)點;如果當(dāng)前元素沒有前一個結(jié)點,那么就表示刪除該節(jié)點后,哈希桶的頭結(jié)點將為空;
namespace fnc
{
	template<class K, class V, class Hash = Hashfunc<K>>
	class unordered_map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};

	public:
		typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;

		iterator begin()
		{
			return _ht.begin();
		}

		iterator end()
		{
			return _ht.end();
		}

		pair<iterator,bool> insert(const pair<K, V>& kv)
		{
			return _ht.Insert(kv);
		}

		iterator find(const K& k)
		{
			return _ht.Find(k);
		}

		bool Erase(const K& k)
		{
			return _ht.Erase(k);
		}

		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = insert(make_pair(key, V()));
			return ret.first->second;
		}
	private:
		hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;
	};
}

C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set

測試

insert

C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set
C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set

find和erase

//find和erase
	void test_set2()
	{
		vector<int> v = { 3,1,5,15,45,7 };
		unordered_set<int> us;
		us.insert(3);
		us.insert(1);
		us.insert(5);
		us.insert(15);
		us.insert(45);
		us.insert(7);

		unordered_set<int>::iterator it = us.begin();
		while (it != us.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		if (us.find(15) != us.end())
		{
			cout << "15:在" << endl;
		}
		else
		{
			cout << "15:不在" << endl;
		}
		if (us.find(16) != us.end())
		{
			cout << "16:在" << endl;
		}
		else
		{
			cout<<"16:不在" << endl;
		}
		cout << endl;
		us.Erase(5);
		us.Erase(7);
		it = us.begin();
		while (it != us.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}
}
void test_map2()
	{
		unordered_map<string, string> dict;
		dict.insert(make_pair("sort", "排序"));
		dict.insert(make_pair("left", "左"));
		dict.insert(make_pair("right", "右"));

		for (auto& kv : dict)
		{
			cout << kv.first << ":" << kv.second << endl;
		}
		cout << endl;
		fnc::unordered_map<string, string>::iterator it = dict.find("sort");
		if (it!=dict.end())
		{
			cout <<"找到了:" << (*it).first << ":" << (*it).second << endl;
		}
		cout << endl;
		dict.Erase("left");
		for (auto& kv : dict)
		{
			cout << kv.first << ":" << kv.second << endl;
		}

	}

C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set

operator[]

void test_map3()
	{
		vector<string> v = { "香蕉","蘋果","橙子","西瓜","香蕉",
			"蘋果","橙子","西瓜","香蕉","蘋果","橙子" ,"香蕉","蘋果" };
		unordered_map<string, int> dict;
		for (auto a : v)
		{
			dict[a]++;
		}

		for (auto a : dict)
		{
			cout << a.first << ":" << a.second << endl;
		}
	}

C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例,C++進階,散列表,c++,哈希算法,unordered_map,unordered_set文章來源地址http://www.zghlxwxcb.cn/news/detail-845495.html

到了這里,關(guān)于C++進階--使用哈希表實現(xiàn)unordered_map和unordered_set的原理與實例的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【C++】開散列哈希表封裝實現(xiàn)unordered_map和unordered_set

    【C++】開散列哈希表封裝實現(xiàn)unordered_map和unordered_set

    在未達(dá)成目的之前,一切具有誘惑力的事物都顯得那么不堪一擊 1. 在C++98中,STL提供了底層為紅黑樹結(jié)構(gòu)的一系列關(guān)聯(lián)式容器,在查詢時效率可達(dá)到 l o g 2 N log_2 N l o g 2 ? N ,即最差情況下需要比較紅黑樹的高度次,當(dāng)樹中的節(jié)點非常多時,查詢效率也不理想。 最好的查詢是

    2023年04月09日
    瀏覽(22)
  • C++【unordered_map/set的底層實現(xiàn)-哈希表】—含有源代碼

    C++【unordered_map/set的底層實現(xiàn)-哈希表】—含有源代碼

    前面講了STL中的map和set容器以及封裝實現(xiàn),雖然它們的查找效率是O(logN),但是當(dāng)紅黑樹中的節(jié)點非常多時,因為紅黑樹不是嚴(yán)格平衡,樹的高度可能變得很大,就是一變高一邊低的情況,這會導(dǎo)致查詢操作的時間復(fù)雜度變?yōu)镺(N),所以后面就出現(xiàn)了四個unordered系列的關(guān)聯(lián)式容

    2024年02月08日
    瀏覽(26)
  • C++ unordered_map哈希表

    leetcode: 49. 字母異位詞分組 給你一個字符串?dāng)?shù)組,請你將 字母異位詞 組合在一起。可以按任意順序返回結(jié)果列表。 字母異位詞 是由重新排列源單詞的字母得到的一個新單詞,所有源單詞中的字母通常恰好只用一次。 示例 1: 輸入: strs = [“eat”, “tea”, “tan”, “ate”, “

    2023年04月25日
    瀏覽(18)
  • 【C++學(xué)習(xí)】哈希表的底層實現(xiàn)及其在unordered_set與unordered_map中的封裝

    【C++學(xué)習(xí)】哈希表的底層實現(xiàn)及其在unordered_set與unordered_map中的封裝

    ??個人名片: ??作者簡介:一名樂于分享在學(xué)習(xí)道路上收獲的大二在校生 ??個人主頁??:GOTXX ??個人WeChat:ILXOXVJE ??本文由GOTXX原創(chuàng),首發(fā)CSDN?????? ??系列專欄:零基礎(chǔ)學(xué)習(xí)C語言----- 數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí)之路----C++的學(xué)習(xí)之路 ??每日一句:如果沒有特別幸運,那就請?zhí)?/p>

    2024年04月16日
    瀏覽(38)
  • C++進階--unordered_set、unordered_map的介紹和使用

    ??在C++98中,STL提供了底層為紅黑樹結(jié)構(gòu)的一系列關(guān)聯(lián)式容器,在查詢時效率可達(dá)到 l o g 2 N log_2N l o g 2 ? N ,即最差情況下需要比較紅黑樹的高度次,當(dāng)樹中的節(jié)點非常多時,查詢效率也不理想。最好的查詢是,進行很少的比較次數(shù)就能夠?qū)⒃卣业?,因此在C++11中,STL又

    2024年01月16日
    瀏覽(47)
  • C++利用開散列哈希表封裝unordered_set,unordered_map

    C++利用開散列哈希表封裝unordered_set,unordered_map

    1.之前我們已經(jīng)實現(xiàn)了開散列的哈希表,今天我們來用它封裝unordered_set,unordered_map 2.本文的封裝比利用紅黑樹封裝set和map更加復(fù)雜 建議大家先去看我的紅黑樹封裝set和map再來看本文 因為有很多地方跟紅黑樹封裝set和map時是同樣的思路和方法,所以本文不會太去贅述一遍 因為un

    2024年03月24日
    瀏覽(20)
  • C++ 哈希+unordered_map+unordered_set+位圖+布隆過濾器(深度剖析)

    C++ 哈希+unordered_map+unordered_set+位圖+布隆過濾器(深度剖析)

    想象一下,你有一個巨大的圖書館,里面擺滿了成千上萬本書。如果你想要找到其中一本特定的書,你會怎么做?如果你按照書的編號來有序地排列它們,找到特定的書本可能會很容易。但是,如果書籍是隨機地擺放,你可能需要逐本地查找,這個過程會非常耗時。 而哈希函

    2024年02月21日
    瀏覽(24)
  • 【C++入門到精通】哈希 (STL) _ unordered_map _ unordered_set [ C++入門 ]

    【C++入門到精通】哈希 (STL) _ unordered_map _ unordered_set [ C++入門 ]

    歡迎各位大佬們的關(guān)顧,本文將介紹unordered系列容器以及其中的兩個重要成員: unordered_map 和 unordered_set 。unordered_map是一種無序的關(guān)聯(lián)容器,它使用哈希表來存儲鍵值對,并提供高效的插入、查找和刪除操作。在本文中,我們將首先介紹unordered_map的基本概念和特點,然后詳

    2024年02月08日
    瀏覽(20)
  • 【C++】如何用一個哈希表同時封裝出unordered_set與unordered_map

    【C++】如何用一個哈希表同時封裝出unordered_set與unordered_map

    ?? 樊梓慕: 個人主頁 ??? 個人專欄: 《C語言》 《數(shù)據(jù)結(jié)構(gòu)》 《藍(lán)橋杯試題》 《LeetCode刷題筆記》 《實訓(xùn)項目》 《C++》 《Linux》 《算法》 ?? 每一個不曾起舞的日子,都是對生命的辜負(fù) 目錄 前言 1.哈希桶源碼 ?2.哈希表模板參數(shù)的控制 3.字符串作為鍵值如何映射哈希值

    2024年03月26日
    瀏覽(40)
  • 【C++】STL——用一個哈希表封裝出unordered_map和unordered_set

    【C++】STL——用一個哈希表封裝出unordered_map和unordered_set

    根據(jù)先前對unordered_map和unordered_set的學(xué)習(xí),我們得知其底層是借助哈希表來實現(xiàn)的,接下來我們會使用上篇博客實現(xiàn)的開散列哈希表來模擬實現(xiàn)unordered_map和unordered_set,哈希表源代碼鏈接: Hash/Hash/HashBucket.h · wei/cplusplus - 碼云 - 開源中國 (gitee.com) 下面我們對哈希表進行改造,

    2023年04月18日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包