最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

 STL map和set只是包含了幾個頭文件

 主要在選中的這個文件里,打開之后我們可以看到紅黑樹

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

set的主要實現(xiàn)

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

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

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

模擬實現(xiàn) 

這里不用說明紅黑樹是K還是KV,用T來決定紅黑樹,使用時T是什么,紅黑樹就是什么

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

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

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

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

取K的仿函數(shù) 

對于set而言,直接返回就行 

對于map而言,就要取first

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

Insert 

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

 set也一樣

迭代器 

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

 以下是紅黑樹的迭代器

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é)點,這里的_root是紅黑樹的根節(jié)點,end是最后一個節(jié)點的下一個位置就是空。

 ++和-- 

 這里++和--是按照中序進行的

這里訪問順序是左根右

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

2.右子樹是空,++找孩子不是父親右的那個父親

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

--是反向左子樹

右根左

1.如果左子樹不為空,我們就訪問它的最右節(jié)點

2.如果為空,訪問孩子不是父親的左的父親

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

operator[]

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

map和set的insert也做修改

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

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

Map中使用方括號訪問鍵對應(yīng)的值map[key]時:

  1. 若該key存在,則訪問取得value值;
  2. 若該key不存在,訪問仍然成功,取得value對象默認構(gòu)造的值。具體如下:
    用 []訪問,但key不存在時,C++會利用該key及默認構(gòu)造的value,組成{key,value}對,插入到map中。
    value為 string對象,則構(gòu)造空串;value為int對象,構(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[] = { "蘋果", "西瓜", "蘋果", "西瓜", "蘋果", "蘋果", "西瓜", "蘋果", "香蕉", "蘋果", "香蕉" };
 
		map<string, int> countMap;
		for (auto& str : arr)
		{
			// 1、str不在countMap中,插入pair(str, int()),然后在對返回次數(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)
		{
			// 下一個就是右子樹的最左節(jié)點
			Node* left = _node->_right;
			while (left->_left)
			{
				left = left->_left;
			}
 
			_node = left;
		}
		else
		{
			// 找祖先里面孩子不是祖先的右的那個
			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)
		{
			// 下一個是左子樹的最右節(jié)點
			Node* right = _node->_left;
			while (right->_right)
			{
				right = right->_right;
			}
 
			_node = right;
		}
		else
		{
			// 孩子不是父親的左的那個祖先
			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é)點不是黑色" << endl;
			return false;
		}
 
		// 黑色節(jié)點數(shù)量基準值
		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é)點的數(shù)量不相等" << endl;
				return false;
			}
			else
			{
				return true;
			}
		}
 
		if (root->_col == BLACK)
		{
			++blackNum;
		}
 
		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "存在連續(xù)的紅色節(jié)點" << 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封裝實現(xiàn)的文章就介紹到這了,更多相關(guān)C++ map和set封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言中單鏈表(不帶頭結(jié)點)基本操作的實現(xiàn)詳解

    C語言中單鏈表(不帶頭結(jié)點)基本操作的實現(xiàn)詳解

    鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。本文主要和大家聊聊C語言中單鏈表(不帶頭結(jié)點)的基本操作,感興趣的小伙伴可以了解一下
    2022-11-11
  • C語言數(shù)據(jù)結(jié)構(gòu)與算法之單鏈表

    C語言數(shù)據(jù)結(jié)構(gòu)與算法之單鏈表

    單鏈表是一種鏈式存取的數(shù)據(jù)結(jié)構(gòu),用一組地址任意的存儲單元存放線性表中的數(shù)據(jù)元素。本文將為大家介紹C語言中單鏈表的基本概念與讀取數(shù)據(jù)元素,需要的可以參考一下
    2021-12-12
  • C++超詳細講解函數(shù)重載

    C++超詳細講解函數(shù)重載

    C++ 允許多個函數(shù)擁有相同的名字,只要它們的參數(shù)列表不同就可以,這就是函數(shù)的重載(Function Overloading),借助重載,一個函數(shù)名可以有多種用途
    2022-05-05
  • C 語言指針變量的運算詳解

    C 語言指針變量的運算詳解

    本文主要介紹 C語言指針變量運算的知識,這里整理了詳細的知識點,并附示例代碼,有需要學(xué)習(xí)C語言指針的朋友可以參考下
    2016-08-08
  • C語言編程C++動態(tài)內(nèi)存分配示例講解

    C語言編程C++動態(tài)內(nèi)存分配示例講解

    這篇文章主要介紹了C語言編程C++動態(tài)內(nèi)存分配示例講解,為什么存在動態(tài)內(nèi)存分配?本文通過動態(tài)內(nèi)存介紹及常見內(nèi)存錯誤等示例來為大家講解
    2021-09-09
  • C語言實現(xiàn)倉庫物資管理系統(tǒng)

    C語言實現(xiàn)倉庫物資管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)倉庫物資管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++異步調(diào)用方法詳解

    C++異步調(diào)用方法詳解

    這篇文章主要介紹了C++異步調(diào)用方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • C++指向類成員函數(shù)的指針詳細解析

    C++指向類成員函數(shù)的指針詳細解析

    由于這幾天在開發(fā)中要用到函數(shù)指針,所以就整理了一下關(guān)于函數(shù)指針的概念
    2013-08-08
  • c++ 解析yaml文件的步驟

    c++ 解析yaml文件的步驟

    這篇文章主要介紹了c++ 解析yaml文件的步驟,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下
    2020-12-12
  • Qt C++實現(xiàn)錄屏錄音功能的示例詳解

    Qt C++實現(xiàn)錄屏錄音功能的示例詳解

    實現(xiàn)一個錄屏+錄音的功能且需要快速開發(fā),Qt無疑是一個非常好的選擇。他有豐富的類庫和接口可以很好的滿足開發(fā)需求。本文就來和大家聊聊具體的實現(xiàn)方法吧
    2023-03-03

最新評論

西乡县| 迁西县| 措勤县| 金平| 塔河县| 巴彦县| 古交市| 邯郸市| 营山县| 旅游| 沁源县| 白沙| 定陶县| 瑞安市| 东光县| 武宁县| 长顺县| 揭阳市| 乐都县| 寻乌县| 德钦县| 兰考县| 纳雍县| 湘潭市| 威远县| 密山市| 扶沟县| 临武县| 扎鲁特旗| 抚顺市| 西平县| 安乡县| 万州区| 民乐县| 察雅县| 福海县| 依兰县| 天祝| 兴城市| 游戏| 田东县|