【C++】STL之map、set类源码剖析

这篇具有很好参考价值的文章主要介绍了【C++】STL之map、set类源码剖析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

概述

算法

源码

Iterator.h

RBTree.h

Map.h

Set.h

test.cpp


概述

map和set都是STL中的关联式容器,而vector、list、deque是序列式容器。

map是映像,set是集合,map元素的数据类型是std::pair<K,V>格式(key/value形成映像),set元素的数据类型只有key值。

map和set的实现是对红黑树的封装,map根据key值进行排序,map和set的key值都是不可修改的,但是map的value值可以修改。

map和set支持迭代器、反向迭代器、常量迭代器,并且通过精妙的泛型设计,大大简化了代码,但是完成两个STL容器的基本功能封装,依旧需要千行代码左右。

算法

本文里面的红黑树模块相较于上一篇博客,做了部分修改,设计了红黑树的迭代器,并将迭代器单独作为一个模块,通过普通迭代器构造出反向迭代器,这里采用的设计思路与之前 list 容器的迭代器设计思路是相同的。

红黑树在普通迭代器类中,设计出通过普通迭代器拷贝出const迭代器,这样解决了set模块的insert函数的返回值由红黑树的iterator转换为const_iterator问题。

红黑树迭代器的自增、自减都有其独特的算法,但是本文中的红黑树结构,与stl标准库中的红黑树略有不同,本文的红黑树没有一个空的头结点,即:当迭代器迭代到end(),即迭代器指向nullptr。而在stl标准库中,迭代器走到end()时,迭代器指向空的头结点。

红黑树的构造可以通过元素插入构造或者拷贝构造,拷贝构造设计了迭代器构造,这也是拷贝构造的核心。map和set的迭代器构造、拷贝构造、赋值构造本质都是调用红黑树的迭代器构造。

红黑树的泛型设计十分精妙(红黑树自身并不知道自己是要构造出一个map还是set,但是他必须兼容这两种容器的所有特性),并通过仿函数KofT设计,实现了从传入的元素数据(key值或key/value键值对)之中提取到key值进行排序

set模块的迭代器设计十分精妙,因为set里面元素都是key值,而红黑树的key值是不允许修改的,所以无论是set的普通迭代器iterator还是const_iterator,其本质都是const_iterator,所以set在设计时用const_iterator来重命名iterator,在普通迭代器的构造函数时加上了const修饰,而省略了const_iterator的构造函数,使iterator的构造函数能够对const_iterator构成重载。

map的 "[ ]" 运算符有特殊功能,即可以通过 "[ ] " 来进行数据插入、查找、统计,原理是:若 "[ ]" 里面数据的key值已经存在的话,则插入失败,insert函数返回已有节点的迭代器和一个bool值false,然后 "[ ] " 运算符返回这个迭代器(pair<key, value>)的第二个数据(value);若 "[ ]"  里面数据的key不存在,则插入成功,insert函数返回新插入节点的迭代器和bool值true,然后 "[ ]" 运算符返回这个键值对迭代器的value值。因此我们可以通过这个原理对键值对的第二个数据为整型类型的数据进行计数操作。文章来源地址https://www.toymoban.com/news/detail-434741.html

源码

Iterator.h

#pragma once

enum Colour
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	T _data;
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	Colour _col;

	RBTreeNode(const T data)
		: _data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)
	{}
};

template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;
	typedef RBTreeIterator<T, T&, T*> iterator;

	Node* _node;

	RBTreeIterator(Node* node)
		: _node(node)
	{}

	// 普通迭代器构造const迭代器
	RBTreeIterator(const iterator& it)
	{
		_node = it._node;
	}

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

	Self& operator++()
	{
		if (_node->_right)
		{
			Node* min = _node->_right;
			while (min->_left)
			{
				min = min->_left;
			}
			_node = min;
		}
		else
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}

		return *this;
	}
	Self operator++(int)
	{
		Self tmp(*this);
		++(*this);
		return tmp;
	}

	Self& operator--()
	{
		if (_node->_left)
		{
			Node* max = _node->_left;
			while (max->_right)
			{
				max = max->_right;
			}
			_node = max;
		}
		else
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}

		return *this;
	}
	Self operator--(int)
	{
		Self tmp(*this);
		--(*this);
		return tmp;
	}

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

template<class Iterator, class Ref, class Ptr>
struct RBTreeReverseIterator
{
	typedef RBTreeReverseIterator<Iterator, Ref, Ptr> Self;

	Iterator _it;
	RBTreeReverseIterator(Iterator it)
		: _it(it)
	{}

	Ref operator*()
	{
		Iterator tmp = _it;
		return *tmp;
	}
	Ptr operator->()
	{
		return &(operator*());
	}

	Self& operator++()
	{
		--_it;
		return *this;
	}
	Self operator++(int)
	{
		Self tmp(*this);
		--_it;
		return tmp;
	}

	Self& operator--()
	{
		++_it;
		return *this;
	}
	Self operator--(int)
	{
		Self tmp(*this);
		++_it;
		return tmp;
	}

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

RBTree.h

#pragma once
#include "Iterator.h"

template<class K, class T, class KofT>
class RBTree
{
	// 私有
	typedef RBTreeNode<T> Node;
public:
	typedef RBTreeIterator<T, T&, T*> iterator;
	typedef RBTreeIterator<T, const T&, const T*> const_iterator;
	typedef RBTreeReverseIterator<iterator, T&, T*> reverse_iterator;
	typedef RBTreeReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;

	iterator begin()
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}

		return iterator(left);
	}
	iterator end()
	{
		return iterator(nullptr);
	}

	const_iterator begin()const
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}

		return const_iterator(left);
	}
	const_iterator end()const
	{
		return const_iterator(nullptr);
	}

	reverse_iterator rbegin()
	{
		Node* right = _root;
		while (right && right->_right)
		{
			right = right->_right;
		}

		return reverse_iterator(iterator(right));
	}
	reverse_iterator rend()
	{
		return reverse_iterator(iterator(nullptr));
	}

	const_reverse_iterator rbegin()const
	{
		Node* right = _root;
		while (right && right->_right)
		{
			right = right->_right;
		}

		return const_reverse_iterator(const_iterator(right));
	}
	const_reverse_iterator rend()const
	{
		return const_reverse_iterator(const_iterator(nullptr));
	}

	// 迭代器构造
	template<class Iterator>
	RBTree(Iterator first, Iterator last)
	{
		_root = nullptr;
		while (first != last)
		{
			insert(*first);
			++first;
		}
	}

	RBTree()
		: _root(nullptr)
	{}

	std::pair<iterator, bool> insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return std::make_pair(iterator(_root), true);
		}

		KofT kot;

		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (kot(cur->_data) < kot(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > kot(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return std::make_pair(iterator(cur), false);
			}
		}

		cur = new Node(data);
		Node* newNode = cur;
		cur->_col = RED;
		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		// 变色、旋转
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;

				if (uncle && uncle->_col == RED)
				{
					// 情况1:叔叔存在且为红
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{
						// 情况2: 右单旋
						rotate_right(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						// 情况3: 左右双旋
						rotate_left(parent);
						rotate_right(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else
			{
				Node* uncle = grandfather->_left;

				if (uncle&& uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_right)
					{
						// 情况2: 左单旋
						rotate_left(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						// 情况3: 右左双旋
						rotate_right(parent);
						rotate_left(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}

		}

		_root->_col = BLACK;

		return std::make_pair(iterator(newNode), true);
	}

	void rotate_right(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}

		subL->_right = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subL;
		if (ppNode == nullptr)
		{
			subL->_parent = nullptr;
			_root = subL;
		}
		else
		{
			if (parent == ppNode->_left)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
			subL->_parent = ppNode;
		}
	}

	void rotate_left(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = parent;
		}

		subR->_left = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;
		if (ppNode == nullptr)
		{
			subR->_parent = nullptr;
			_root = subR;
		}
		else
		{
			if (parent == ppNode->_left)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
			subR->_parent = ppNode;
		}
	}

	void in_order()
	{
		_in_order(_root);
		std::cout << std::endl;
	}

	bool is_balance()
	{
		if (_root == nullptr)
		{
			return true;
		}

		if (_root->_col != BLACK)
		{
			return false;
		}

		int ref = 0;
		Node* left = _root;
		while (left)
		{
			if (left->_col == BLACK)
			{
				++ref;
			}
			left = left->_left;
		}

		return _is_balance(_root, 0, ref);
	}

private:
	void _in_order(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_in_order(root->_left);
		std::cout << root->_data << std::endl;
		_in_order(root->_right);
	}

	// 检查是否有联系的红节点
	bool _is_balance(Node* root, int blackNum, const int ref)
	{
		if (root == nullptr)
		{
			if (blackNum != ref)
			{
				std::cout << "路径黑色节点跟最左路径不相等" << std::endl;
				return false;
			}
			return true;
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			std::cout << "出现连续红节点: " << root->_data.first << ", " << root->_parent->_data.first << std::endl;
			return false;
		}

		if (root->_col == BLACK)
		{
			++blackNum;
		}

		return _is_balance(root->_left, blackNum, ref)
			&& _is_balance(root->_right, blackNum, ref);
	}

private:
	Node* _root = nullptr;
};

Map.h

#pragma once

#include "RBTree.h"

template<class K, class V>
class Map
{
	struct MapKofT
	{
		const K& operator()(const std::pair<const K, V>& kv)
		{
			return kv.first;
		}
	};
public:
	typedef typename RBTree<K, std::pair<const K, V>, MapKofT>::iterator iterator;
	typedef typename RBTree<K, std::pair<const K, V>, MapKofT>::const_iterator const_iterator;
	typedef typename RBTree<K, std::pair<const K, V>, MapKofT>::reverse_iterator reverse_iterator;
	typedef typename RBTree<K, std::pair<const K, V>, MapKofT>::const_reverse_iterator const_reverse_iterator;

	iterator begin()
	{
		return _t.begin();
	}
	iterator end()
	{
		return _t.end();
	}

	const_iterator begin()const
	{
		return _t.begin();
	}
	const_iterator end()const
	{
		return _t.end();
	}

	reverse_iterator rbegin()
	{
		return _t.rbegin();
	}
	reverse_iterator rend()
	{
		return _t.rend();
	}

	const_reverse_iterator rbegin()const
	{
		return _t.rbegin();
	}
	const_reverse_iterator rend()const
	{
		return _t.rend();
	}

	template<class Iterator>
	Map(Iterator first, Iterator last)
	{
		_t = RBTree<K, std::pair<const K, V>, MapKofT>(first, last);
	}

	void swap(Map<K, V>& m)
	{
		std::swap(_t, m._t);
	}

	Map()
		: _t(RBTree<K, std::pair<const K, V>, MapKofT>())
	{}
	Map(const Map<K, V>& m)
	{
		Map<K, V> tmp(m._t.begin(), m._t.end());
		swap(tmp);
	}
	Map<K, V>& operator=(const Map<K, V> m)
	{
		swap(m);
		return *this;
	}

	std::pair<iterator, bool> insert(const std::pair<const K, V>& kv)
	{
		return _t.insert(kv);
	}

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

private:
	RBTree<K, std::pair<const K, V>, MapKofT> _t;
};

Set.h

#pragma once

#include "RBTree.h"

template<class K>
class Set
{
	struct SetKofT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
public:
	typedef typename RBTree<K, K, SetKofT>::const_iterator iterator;
	typedef typename RBTree<K, K, SetKofT>::const_iterator const_iterator;
	typedef typename RBTree<K, K, SetKofT>::const_reverse_iterator reverse_iterator;
	typedef typename RBTree<K, K, SetKofT>::const_reverse_iterator const_reverse_iterator;

	iterator begin()const
	{
		return _t.begin();
	}
	iterator end()const
	{
		return _t.end();
	}

	reverse_iterator rbegin()const
	{
		return _t.rbegin();
	}
	reverse_iterator rend()const
	{
		return _t.rend();
	}

	template<class Iterator>
	Set(Iterator first, Iterator last)
	{
		_t = RBTree<K, K, SetKofT>(first, last);
	}

	void swap(Set<K>& s)
	{
		std::swap(_t, s._t);
	}

	Set()
		: _t(RBTree<K, K, SetKofT>())
	{}
	Set(const Set<K>& s)
	{
		Set<K> tmp(s.begin(), s.end());
		swap(tmp);
	}
	Set<K>& operator=(const Set<K> s)
	{
		swap(s);
		return *this;
	}

	std::pair<iterator, bool> insert(const K& k)
	{
		std::pair<typename RBTree<K, K, SetKofT>::iterator, bool> ret = _t.insert(k);
		return std::pair<iterator, bool>(ret.first, ret.second);
	}

private:
	RBTree<K, K, SetKofT> _t;
};

test.cpp

#include <iostream>
#include <string>
#include <vector>
#include "Map.h"
#include "Set.h"

void test_map()
{
	int a[] = { 8, 4, 12, 2, 6, 10, 30, 14, 32, 28 };

	Map<int, int> m;
	for (auto e : a)
	{
		m.insert(std::make_pair(e, e));
	}

	Map<int, int>::iterator it = m.begin();
	while (it != m.end())
	{
		std::cout << (*it).first << ": " << (*it).second << std::endl;
		//++it;
		it++;
	}
	std::cout << std::endl;
	for (auto e : m)
	{
		std::cout << e.first << ": " << e.second << std::endl;
	}
	std::cout << std::endl;

	Map<int, int>::reverse_iterator rit = m.rbegin();
	while (rit != m.rend())
	{
		std::cout << rit->first << ": " << rit->second << std::endl;
		rit++;
	}
	std::cout << std::endl;

	const Map<int, int> m1(m.begin(), m.end());
	Map<int, int>::const_iterator cit = m1.begin();
	while (cit != m1.end())
	{
		std::cout << cit->first << ": " << cit->second << std::endl;
		cit++;
	}
	std::cout << std::endl;

	const Map<int, int> m2(m1);
	Map<int, int>::const_reverse_iterator crit = m2.rbegin();
	while (crit != m2.rend())
	{
		std::cout << crit->first << ": " << crit->second << std::endl;
		++crit;
	}
	std::cout << std::endl;

	Map<int, int> m3 = m2;
	for (auto& e : m3)
	{
		// map的key不可修改,value可改
		//e.first += 1;
		e.second /= 2;
		std::cout << e.first << ": " << e.second << std::endl;
	}
	std::cout << std::endl;

	std::vector<std::string> food = {
		"蛋糕", "西瓜", "啤酒", "苹果", "香蕉", "蛋糕", "牛肉",
		"西瓜", "苹果", "啤酒", "西瓜", "牛肉", "蛋糕", "蛋糕",
		"西瓜", "西瓜", "牛肉", "苹果", "香蕉", "蛋糕", "西瓜"
	};
	Map<std::string, int> foodMap;
	for (auto& e : food)
	{
		foodMap[e]++;
	}
	for (auto& e : foodMap)
	{
		std::cout << e.first << ": " << e.second << std::endl;
	}
	std::cout << std::endl;
}

void test_set()
{
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };

	Set<int> s;
	for (auto e: a)
	{
		s.insert(e);
	}
	
	Set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		std::cout << *it << ' ';
		++it;
	}
	std::cout << std::endl;
	for (const auto& e : s)
	{
		std::cout << e << ' ';
	}
	std::cout << std::endl;

	Set<int>::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		std::cout << *rit << ' ';
		++rit;
	}
	std::cout << std::endl;

	const Set<int> s1(s.begin(), s.end());
	Set<int>::const_iterator cit = s1.begin();
	while (cit != s1.end())
	{
		std::cout << *cit << ' ';
		++cit;
	}
	std::cout << std::endl;

	const Set<int> s2(s1);
	Set<int>::const_reverse_iterator crit = s2.rbegin();
	while (crit != s2.rend())
	{
		std::cout << *crit << ' ';
		++crit;
	}
	std::cout << std::endl;

	const Set<int> s3 = s2;
	for (auto& e : s3)
	{	
		// set的值不可修改
		// e++;
		std::cout << e << ' ';
	}
	std::cout << std::endl;
}

int main()
{
	test_map();
	test_set();
	
	return 0;
}

到了这里,关于【C++】STL之map、set类源码剖析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++高级编程——STL:list容器、set容器和map容器

    本专栏记录C++学习过程包括C++基础以及数据结构和算法,其中第一部分计划时间一个月,主要跟着黑马视频教程,学习路线如下, 不定时更新,欢迎关注 。 当前章节处于: ---------第1阶段-C++基础入门 ---------第2阶段实战-通讯录管理系统, ---------第3阶段-C++核心编程, -----

    2024年01月25日
    浏览(47)
  • 【C++】 使用红黑树模拟实现STL中的map与set

    前面的文章我们学习了红黑树,也提到了C++STL中的map和set的底层其实就是用的红黑树来实现的(而map和set的使用我们前面也学过了)。 既然红黑树我们也学习过了,那这篇文章我们就用红黑树来简单实现一下STL中的map和set,重点是学习它的框架。 上一篇文章我们实现了红黑

    2024年02月12日
    浏览(31)
  • 【C++】STL——用一颗红黑树封装出map和set

    我们都知道set是K模型的容器,而map是KV模型的容器,但是它俩的底层都是用红黑树实现的,上篇博文中我们模拟实现了一颗红黑树,接下来将对其进行改造,继而用一颗红黑树封装出map和set。 本质上map和set其内部的主要功能都是套用了红黑树现成的接口,只是稍作改动即可

    2023年04月15日
    浏览(34)
  • 【C++练级之路】【Lv.17】【STL】set类和map类的模拟实现

    快乐的流畅:个人主页 个人专栏:《C语言》《数据结构世界》《进击的C++》 远方有一堆篝火,在为久候之人燃烧! STL库中的set类和map类,其底层原理都是 通过红黑树来实现 的。尽管set和map可以各自实现一棵红黑树,但是为了提高代码的复用率,STL库中将红黑树进行了一定

    2024年04月16日
    浏览(38)
  • C++:stl中set(multiset)和map(multimap)的介绍和使用

    本文主要从概念、常用接口和使用方法方面介绍set(multiset)和map(multimap)。 目录 一、概念介绍 1.关联式容器 2.键值对 3. 树形结构的关联式容器 二、set和multiset 1.set的介绍 2.set使用 1. set模板参数列表 2. set构造 3. set迭代器 4. set容量 5. set修改操作 6.set使用举例 3.multiset介绍 4.mul

    2024年02月08日
    浏览(40)
  • 【C++进阶04】STL中map、set、multimap、multiset的介绍及使用

    vector/list/deque… 这些容器统称为 序列式容器 因为其底层为线性序列的数据结构 里面存储的是元素本身 map/set… 这些容器统称为 关联式容器 关联式容器也是用来存储数据的 与序列式容器不同的是 其里面存储的是key, value结构的键值对 在数据检索时比序列式容器效率更高 “键

    2024年02月03日
    浏览(47)
  • 【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C++从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C++   🔝🔝 在学习了二叉搜索树后,现在 就可以来学习map和set了,虽然 它们的底层是红黑树结构,但是红黑树 的本质也是一颗二叉搜索树! 本质重点: 本

    2024年02月05日
    浏览(39)
  • 【C++入门到精通】哈希 (STL) _ unordered_map _ unordered_set [ C++入门 ]

    欢迎各位大佬们的关顾,本文将介绍unordered系列容器以及其中的两个重要成员: unordered_map 和 unordered_set 。unordered_map是一种无序的关联容器,它使用哈希表来存储键值对,并提供高效的插入、查找和删除操作。在本文中,我们将首先介绍unordered_map的基本概念和特点,然后详

    2024年02月08日
    浏览(43)
  • C++ 哈希+unordered_map+unordered_set+位图+布隆过滤器(深度剖析)

    想象一下,你有一个巨大的图书馆,里面摆满了成千上万本书。如果你想要找到其中一本特定的书,你会怎么做?如果你按照书的编号来有序地排列它们,找到特定的书本可能会很容易。但是,如果书籍是随机地摆放,你可能需要逐本地查找,这个过程会非常耗时。 而哈希函

    2024年02月21日
    浏览(54)
  • 【C++】STL——用一个哈希表封装出unordered_map和unordered_set

    根据先前对unordered_map和unordered_set的学习,我们得知其底层是借助哈希表来实现的,接下来我们会使用上篇博客实现的开散列哈希表来模拟实现unordered_map和unordered_set,哈希表源代码链接: Hash/Hash/HashBucket.h · wei/cplusplus - 码云 - 开源中国 (gitee.com) 下面我们对哈希表进行改造,

    2023年04月18日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包