亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++中map和set封裝實(shí)現(xiàn)示例

 更新時(shí)間:2023年02月06日 10:09:31   作者:頭發(fā)沒(méi)有代碼多  
我們知道,map與set所使用的都是紅黑樹(shù),下面這篇文章主要給大家介紹了關(guān)于C++中map和set封裝實(shí)現(xiàn)的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

mao和set模擬實(shí)現(xiàn) 

 STL map和set只是包含了幾個(gè)頭文件

 主要在選中的這個(gè)文件里,打開(kāi)之后我們可以看到紅黑樹(shù)

用紅黑樹(shù)實(shí)現(xiàn)map和set

set的主要實(shí)現(xiàn)

set里面的value type和key type都是KEY

map里面的value type是pair,key type是KEY

這里用一顆泛型結(jié)構(gòu)的RBTree,通過(guò)不同的實(shí)例化參數(shù),實(shí)現(xiàn)出了map和set。

模擬實(shí)現(xiàn) 

這里不用說(shuō)明紅黑樹(shù)是K還是KV,用T來(lái)決定紅黑樹(shù),使用時(shí)T是什么,紅黑樹(shù)就是什么

如Map傳的是pair,T就是pair,Set傳的是K,T就是K

T傳給了節(jié)點(diǎn)里面的data,上面?zhèn)鲄鱇的原因是find函數(shù)要用到,find是通過(guò)K去進(jìn)行查找。

Insert插入數(shù)據(jù)的時(shí)候要比較數(shù)據(jù)的大小選擇合適的位置插入,但這里data是T類型,對(duì)于set可直接比較,而map傳過(guò)來(lái)的是pair,如果比較pair就要比較first和second,這種不滿足我們的需求,因?yàn)楸容^的時(shí)候既要滿足set也要滿足Map.

我們用仿函數(shù)來(lái)滿足這種要求,這里仿函數(shù)是把T里面的k取出來(lái),pair的K就是first

取K的仿函數(shù) 

對(duì)于set而言,直接返回就行 

對(duì)于map而言,就要取first

之后修改rbtree.h,創(chuàng)建一個(gè)仿函數(shù)對(duì)象,這個(gè)對(duì)象是什么類型的就根據(jù)什么類型取比較即可

Insert 

 對(duì)于Map而言,_t是RBTree類型,Map的insert只需調(diào)用紅黑樹(shù)的Insert即可

 set也一樣

迭代器 

 迭代器也依靠紅黑樹(shù)的迭代器實(shí)現(xiàn),tyoename作用,告訴編譯器是要把類型進(jìn)行重命名

 以下是紅黑樹(shù)的迭代器

enum Colour
{
	RED,
	BLACK
};
 
template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
 
	T _data;
	Colour _col;
 
	RBTreeNode(const T& data)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _data(data)
	{}
};
 
template<class T, class Ref, class Ptr>
struct __RBTreeIterator//迭代器
{
	typedef RBTreeNode<T> Node;
	typedef __RBTreeIterator<T, Ref, Ptr> Self;
	Node* _node;
 
	__RBTreeIterator(Node* node)//構(gòu)造
		:_node(node)
	{}
 
	Ref operator*()//返回引用
	{
		return _node->_data;
	}
 
	Ptr operator->()//返回指針
	{
		return &_node->_data;
	}
 
	bool operator!=(const Self& s) const
	{
		return _node != s._node;
	}
 
	bool operator==(const Self& s) const
	{
		return _node == s._node;
	}
};

begin和end 

template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef __RBTreeIterator<T, T&, T*> iterator;
 
	iterator begin()
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}
 
		return iterator(left);
	}
 
	iterator end()
	{
		return iterator(nullptr);
	}
};

 begin是找最左邊的節(jié)點(diǎn),這里的_root是紅黑樹(shù)的根節(jié)點(diǎn),end是最后一個(gè)節(jié)點(diǎn)的下一個(gè)位置就是空。

 ++和-- 

 這里++和--是按照中序進(jìn)行的

這里訪問(wèn)順序是左根右

1.如果右子樹(shù)不為空,++就是找右子樹(shù)中序的第一個(gè)(最左節(jié)點(diǎn))

2.右子樹(shù)是空,++找孩子不是父親右的那個(gè)父親

第二句話理解,這里7訪問(wèn)完,父親是6,7是6右子樹(shù),更新cur,parent,8是parent,6是cur,cur不是parent右子樹(shù)。所以下一個(gè)節(jié)點(diǎn)是8

--是反向左子樹(shù)

右根左

1.如果左子樹(shù)不為空,我們就訪問(wèn)它的最右節(jié)點(diǎn)

2.如果為空,訪問(wèn)孩子不是父親的左的父親

Self& operator++()
	{
		if (_node->_right)
		{
			// 下一個(gè)就是右子樹(shù)的最左節(jié)點(diǎn)
			Node* left = _node->_right;
			while (left->_left)
			{
				left = left->_left;
			}
 
			_node = left;
		}
		else
		{
			// 找祖先里面孩子不是祖先的右的那個(gè)
			Node* parent = _node->_parent;
			Node* cur = _node;
			while (parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
 
			_node = parent;
		}
 
		return *this;
	}
 
	Self& operator--()
	{
		if (_node->_left)
		{
			// 下一個(gè)是左子樹(shù)的最右節(jié)點(diǎn)
			Node* right = _node->_left;
			while (right->_right)
			{
				right = right->_right;
			}
 
			_node = right;
		}
		else
		{
			// 孩子不是父親的左的那個(gè)祖先
			Node* parent = _node->_parent;
			Node* cur = _node;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
 
			_node = parent;
		}
 
		return *this;
	}

operator[]

 []的實(shí)現(xiàn)要改造一個(gè)迭代器

map和set的insert也做修改

只有map有[],我們不需要在紅黑樹(shù)里面實(shí)現(xiàn)[],單獨(dú)給map實(shí)現(xiàn)即可

ret.first是迭代器,->second是KV的value

Map中使用方括號(hào)訪問(wèn)鍵對(duì)應(yīng)的值map[key]時(shí):

  1. 若該key存在,則訪問(wèn)取得value值;
  2. 若該key不存在,訪問(wèn)仍然成功,取得value對(duì)象默認(rèn)構(gòu)造的值。具體如下:
    用 []訪問(wèn),但key不存在時(shí),C++會(huì)利用該key及默認(rèn)構(gòu)造的value,組成{key,value}對(duì),插入到map中。
    value為 string對(duì)象,則構(gòu)造空串;value為int對(duì)象,構(gòu)造為0。

范圍for也可以使用

完整代碼 

set.h 

#include"rbtree.h"
namespace myspace
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
 
		iterator begin()
		{
			return _t.begin();
		}
 
		iterator end()
		{
			return _t.end();
		}
 
		pair<iterator, bool> insert(const K& key)
		{
			return _t.Insert(key);
		}
	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
 
	void test_set()
	{
		set<int> s;
 
		set<int>::iterator it = s.begin();
		while (it != s.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
 
		s.insert(3);
		s.insert(2);
		s.insert(1);
		s.insert(5);
		s.insert(3);
		s.insert(6);
		s.insert(4);
		s.insert(9);
		s.insert(7);
 
 
		it = s.begin();
		while (it != s.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}
}

map.h 

#include"rbtree.h"
#pragma once
 
namespace myspace
{
	template<class K, class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
 
		iterator begin()
		{
			return _t.begin();
		}
 
		iterator end()
		{
			return _t.end();
		}
 
		pair<iterator, bool> insert(const pair<K, V>& kv)
		{
			return _t.Insert(kv);
		}
 
		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = insert(make_pair(key, V()));
			return ret.first->second;
		}
	private:
		RBTree<K, pair<K, V>, MapKeyOfT> _t;
	};
 
	void test_map()
	{
		string arr[] = { "蘋(píng)果", "西瓜", "蘋(píng)果", "西瓜", "蘋(píng)果", "蘋(píng)果", "西瓜", "蘋(píng)果", "香蕉", "蘋(píng)果", "香蕉" };
 
		map<string, int> countMap;
		for (auto& str : arr)
		{
			// 1、str不在countMap中,插入pair(str, int()),然后在對(duì)返回次數(shù)++
			// 2、str在countMap中,返回value(次數(shù))的引用,次數(shù)++;
			countMap[str]++;
		}
 
		map<string, int>::iterator it = countMap.begin();
		while (it != countMap.end())
		{
			cout << it->first << ":" << it->second << endl;
			++it;
		}
 
		for (auto& kv : countMap)
		{
			cout << kv.first << ":" << kv.second << endl;
		}
	}
}

rbtree.h 

enum Colour
{
	RED,
	BLACK
};
 
template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
 
	T _data;
	Colour _col;
 
	RBTreeNode(const T& data)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _data(data)
	{}
};
 
template<class T, class Ref, class Ptr>
struct __RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef __RBTreeIterator<T, Ref, Ptr> Self;
	Node* _node;
 
	__RBTreeIterator(Node* node)
		:_node(node)
	{}
 
	Ref operator*()
	{
		return _node->_data;
	}
 
	Ptr operator->()
	{
		return &_node->_data;
	}
 
	bool operator!=(const Self& s) const
	{
		return _node != s._node;
	}
 
	bool operator==(const Self& s) const
	{
		return _node == s._node;
	}
 
	Self& operator++()
	{
		if (_node->_right)
		{
			// 下一個(gè)就是右子樹(shù)的最左節(jié)點(diǎn)
			Node* left = _node->_right;
			while (left->_left)
			{
				left = left->_left;
			}
 
			_node = left;
		}
		else
		{
			// 找祖先里面孩子不是祖先的右的那個(gè)
			Node* parent = _node->_parent;
			Node* cur = _node;
			while (parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
 
			_node = parent;
		}
 
		return *this;
	}
 
	Self& operator--()
	{
		if (_node->_left)
		{
			// 下一個(gè)是左子樹(shù)的最右節(jié)點(diǎn)
			Node* right = _node->_left;
			while (right->_right)
			{
				right = right->_right;
			}
 
			_node = right;
		}
		else
		{
			// 孩子不是父親的左的那個(gè)祖先
			Node* parent = _node->_parent;
			Node* cur = _node;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
 
			_node = parent;
		}
 
		return *this;
	}
};
 
template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef __RBTreeIterator<T, T&, T*> iterator;
 
	iterator begin()
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}
 
		return iterator(left);
	}
 
	iterator end()
	{
		return iterator(nullptr);
	}
 
	pair<iterator, bool> Insert(const T& data)
	{
		KeyOfT kot;
 
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}
 
		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 make_pair(iterator(cur), false);
			}
		}
 
		cur = new Node(data);
		Node* newnode = cur;
		cur->_col = RED;
 
		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
 
		cur->_parent = parent;
 
		while (parent && parent->_col == RED)
		{
			Node* grandfater = parent->_parent;
			assert(grandfater);
			assert(grandfater->_col == BLACK);
			// 關(guān)鍵看叔叔
			if (parent == grandfater->_left)
			{
				Node* uncle = grandfater->_right;
				// 情況一 : uncle存在且為紅,變色+繼續(xù)往上處理
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfater->_col = RED;
					// 繼續(xù)往上處理
					cur = grandfater;
					parent = cur->_parent;
				}// 情況二+三:uncle不存在 + 存在且為黑
				else
				{
					// 情況二:右單旋+變色
					//     g 
					//   p   u
					// c
					if (cur == parent->_left)
					{
						RotateR(grandfater);
						parent->_col = BLACK;
						grandfater->_col = RED;
					}
					else
					{
						// 情況三:左右單旋+變色
						//     g 
						//   p   u
						//     c
						RotateL(parent);
						RotateR(grandfater);
						cur->_col = BLACK;
						grandfater->_col = RED;
					}
 
					break;
				}
			}
			else // (parent == grandfater->_right)
			{
				Node* uncle = grandfater->_left;
				// 情況一
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfater->_col = RED;
					// 繼續(xù)往上處理
					cur = grandfater;
					parent = cur->_parent;
				}
				else
				{
					// 情況二:左單旋+變色
					//     g 
					//   u   p
					//         c
					if (cur == parent->_right)
					{
						RotateL(grandfater);
						parent->_col = BLACK;
						grandfater->_col = RED;
					}
					else
					{
						// 情況三:右左單旋+變色
						//     g 
						//   u   p
						//     c
						RotateR(parent);
						RotateL(grandfater);
						cur->_col = BLACK;
						grandfater->_col = RED;
					}
 
					break;
				}
			}
 
		}
 
		_root->_col = BLACK;
		return make_pair(iterator(newnode), true);
	}
 
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
 
	bool IsBalance()
	{
		if (_root == nullptr)
		{
			return true;
		}
 
		if (_root->_col == RED)
		{
			cout << "根節(jié)點(diǎn)不是黑色" << endl;
			return false;
		}
 
		// 黑色節(jié)點(diǎn)數(shù)量基準(zhǔn)值
		int benchmark = 0;
		/*Node* cur = _root;
		while (cur)
		{
		if (cur->_col == BLACK)
		++benchmark;
		cur = cur->_left;
		}*/
 
		return PrevCheck(_root, 0, benchmark);
	}
 
private:
	bool PrevCheck(Node* root, int blackNum, int& benchmark)
	{
		if (root == nullptr)
		{
			//cout << blackNum << endl;
			//return;
			if (benchmark == 0)
			{
				benchmark = blackNum;
				return true;
			}
 
			if (blackNum != benchmark)
			{
				cout << "某條黑色節(jié)點(diǎn)的數(shù)量不相等" << endl;
				return false;
			}
			else
			{
				return true;
			}
		}
 
		if (root->_col == BLACK)
		{
			++blackNum;
		}
 
		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "存在連續(xù)的紅色節(jié)點(diǎn)" << endl;
			return false;
		}
 
		return PrevCheck(root->_left, blackNum, benchmark)
			&& PrevCheck(root->_right, blackNum, benchmark);
	}
 
	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
 
		_InOrder(root->_left);
		cout << root->_kv.first << ":" << root->_kv.second << endl;
		_InOrder(root->_right);
	}
 
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
 
		parent->_right = subRL;
		if (subRL)
			subRL->_parent = parent;
 
		Node* ppNode = parent->_parent;
 
		subR->_left = parent;
		parent->_parent = subR;
 
		if (_root == parent)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
 
			subR->_parent = ppNode;
		}
 
	}
 
	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
 
		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}
 
		Node* ppNode = parent->_parent;
 
		subL->_right = parent;
		parent->_parent = subL;
 
		if (_root == parent)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
 
			subL->_parent = ppNode;
		}
 
	}
 
private:
	Node* _root = nullptr;
};

總結(jié)

到此這篇關(guān)于C++中map和set封裝實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ map和set封裝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 類成員函數(shù)的重載、覆蓋與隱藏之間的區(qū)別總結(jié)

    類成員函數(shù)的重載、覆蓋與隱藏之間的區(qū)別總結(jié)

    以下是對(duì)類成員函數(shù)的重載、覆蓋與隱藏之間的區(qū)別進(jìn)行了詳細(xì)的總結(jié)分析,需要的朋友可以過(guò)來(lái)參考下。希望對(duì)大家有所幫助
    2013-10-10
  • 用C/C++代碼檢測(cè)ip能否ping通(配合awk和system可以做到批量檢測(cè))

    用C/C++代碼檢測(cè)ip能否ping通(配合awk和system可以做到批量檢測(cè))

    今天小編就為大家分享一篇關(guān)于用C/C++代碼檢測(cè)ip能否ping通(配合awk和system可以做到批量檢測(cè)),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • 深入解析C++中的auto自動(dòng)類型推導(dǎo)

    深入解析C++中的auto自動(dòng)類型推導(dǎo)

    C++標(biāo)準(zhǔn)委員會(huì)在C++11標(biāo)準(zhǔn)中改變了auto關(guān)鍵字的語(yǔ)義,使它變成一個(gè)類型占位符,允許在定義變量時(shí)不必明確寫(xiě)出確切的類型,讓編譯器在編譯期間根據(jù)初始值自動(dòng)推導(dǎo)出它的類型,下面我們就來(lái)看看auto自動(dòng)類型推導(dǎo)的推導(dǎo)規(guī)則吧
    2024-04-04
  • c語(yǔ)言解析bmp圖片的實(shí)例

    c語(yǔ)言解析bmp圖片的實(shí)例

    下面小編就為大家?guī)?lái)一篇c語(yǔ)言解析bmp圖片的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • C++實(shí)現(xiàn)Go的defer功能(示例代碼)

    C++實(shí)現(xiàn)Go的defer功能(示例代碼)

    defer和go一樣都是Go語(yǔ)言提供的關(guān)鍵字。defer用于資源的釋放,會(huì)在函數(shù)返回之前進(jìn)行調(diào)用。接下來(lái)通過(guò)本文給大家介紹C++實(shí)現(xiàn)Go的defer功能,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • C/C++中運(yùn)算符的優(yōu)先級(jí)、運(yùn)算符的結(jié)合性詳解

    C/C++中運(yùn)算符的優(yōu)先級(jí)、運(yùn)算符的結(jié)合性詳解

    這篇文章主要介紹了C/C++中運(yùn)算符的優(yōu)先級(jí)、運(yùn)算符的結(jié)合性詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 基于C++中覆蓋,重載,隱藏的一點(diǎn)重要說(shuō)明

    基于C++中覆蓋,重載,隱藏的一點(diǎn)重要說(shuō)明

    下面小編就為大家?guī)?lái)一篇基于C++中覆蓋,重載,隱藏的一點(diǎn)重要說(shuō)明。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • Java C++ 算法題解leetcode1608特殊數(shù)組特征值

    Java C++ 算法題解leetcode1608特殊數(shù)組特征值

    這篇文章主要為大家介紹了Java C++ 算法題解拓展leetcode1608特殊數(shù)組特征值實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 封裝常用正則表達(dá)式的用法

    封裝常用正則表達(dá)式的用法

    這篇文章主要介紹了使用C++封裝常用正則表達(dá)式的用法,方便以后直接使用,最后還給出了測(cè)試代碼,大家可運(yùn)行測(cè)試使用
    2014-03-03
  • C++實(shí)現(xiàn)旅館住宿管理系統(tǒng)

    C++實(shí)現(xiàn)旅館住宿管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)旅館住宿管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評(píng)論