中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中紅黑樹的示例分析

發布時間:2022-03-24 14:04:56 來源:億速云 閱讀:157 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關C++中紅黑樹的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

    紅黑樹

    紅黑樹的概念

    紅黑樹的概念 紅黑樹,是一種二叉搜索樹,但在每個結點上增加一個存儲位表示結點的顏色,可以是Red或Black。 通過對任何一條從根到葉子的路徑上各個結點著色方式的限制,紅黑樹確保沒有一條路徑會比其他路徑長出倆倍,因而是接近平衡的。

    紅黑樹和AVL樹都是高效的平衡二叉樹,增刪改查的時間復雜度都是O(),紅黑樹不追求絕對平衡,其只需保證最長路徑不超過最短路徑的2倍,相對而言,降低了插入和旋轉的次數,所以在經常進行增刪的結構中性能比AVL樹更優,而且紅黑樹實現比較簡單,所以實際運用中紅黑樹更多。

    C++中紅黑樹的示例分析

    紅黑樹的性質

    • 每個結點不是紅色就是黑色

    • 根節點是黑色的

    • 如果一個結點是紅色的,則它的兩個孩子結點是黑色的

    • 對于每個結點,從該節點到其所有后代葉節點的簡單路徑上,均包含相同數目的黑色結點

    • 每個葉子結點都是黑色的(此處的葉子節點指的是空結點,如上圖路徑數為11條)

    紅黑樹結點的定義

    enum Color {
    	BLACK,
    	RED
    };
    
    template<class T>
    struct RBTreeNode
    {
    	RBTreeNode<T>* _left;
    	RBTreeNode<T>* _right;
    	RBTreeNode<T>* _parent;
    
    	Color _col;
    	T _data;
    
    	RBTreeNode(const T& data)
    		: _left(nullptr)
    		, _right(nullptr)
    		, _parent(nullptr)
    		, _col(RED)
    		,_data(data)
    	{}
    };

    紅黑樹的插入操作

    約定:cur為當前節點,p為父節點,g為祖父節點,u為叔叔節點

    情況一
    • 情況一:cur為紅,p為紅,g為黑,u存在且為紅注意:此處看到的樹,可能是一棵完整的樹,也可能是一棵子樹

    • 解決方式:將p,u改為黑,g改為紅,然后把g當成cur,繼續向上調整

    如果g是根節點,調整完成后,需要將g改為黑色

    如果g是子樹,g一定有雙親,且g的雙親如果是紅色,需要繼續向上調整。

    C++中紅黑樹的示例分析

    C++中紅黑樹的示例分析

    C++中紅黑樹的示例分析

    情況二

    情況二:cur為紅,p為紅,g為黑,u不存在/u為黑

    解決方法:p為g的左孩子,cur為p的左孩子,則進行右單旋;p為g的右孩子,cur為p的右孩子,則進行左單旋。

    p變黑,g變紅。

    1.如果u節點不存在,則cur一定是新插入節點,因為如果cur不是新插入節點,則cur和p一定有一個節點的顏色是黑色,就不滿足性質4:每條路徑黑色節點個數相同。

    2.如果u節點存在,則其一定是黑色的,cur一定不是新增節點,那么cur節點原來的顏色一定是黑色的,是作為子樹的祖父,由第一種情況變化過來的

    C++中紅黑樹的示例分析

    C++中紅黑樹的示例分析

    情況三

    情況三:cur為紅,p為紅,g為黑,u不存在/u為黑(折線型)

    p為g的左孩子,cur為p的右孩子,則針對p做左單旋轉;

    p為g的右孩子,cur為p的左孩子,則針對p做右單旋轉。

    即轉換為了情況二。再對g做對于旋轉。即進行雙旋轉。

    C++中紅黑樹的示例分析

    C++中紅黑樹的示例分析

    // T->K  set
    // T->pair<const K, V> map
    template<class K, class T, class KeyOfT>
    class RBTree
    {
    	typedef RBTreeNode<T> Node;
    public:
    	typedef RBTreeIterator<T, T&, T*> iterator;
    	typedef RBTreeIterator<T, const T&, const T*> const_iterator;
    
    	iterator begin();
    	iterator end();
    
    	RBTree()
    		:_root(nullptr)
    	{}
    
    	// 拷貝構造和賦值重載
    	// 析構
    
    	Node* Find(const K& key);
    
    	pair<iterator, bool> Insert(const T& data)
    	{
    		if (_root == nullptr)
    		{
    			_root = new Node(data);
    			_root->_col = BLACK;
    			return make_pair(iterator(_root), true);
    		}
    
    		Node* parent = nullptr;
    		Node* cur = _root;
    
    		KeyOfT kot;
    		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);
    			}
    		}
    
    		// 新增節點,顏色是紅色,可能破壞規則3,產生連續紅色節點
    		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;
    				// 情況一:uncle存在且為紅,進行變色處理,并繼續往上更新處理
    				if (uncle && uncle->_col == RED)
    				{
    					parent->_col = uncle->_col = BLACK;
    					grandfather->_col = RED;
    
    					cur = grandfather;
    					parent = cur->_parent;
    				} // 情況二+三:uncle不存在,或者存在且為黑,需要旋轉+變色處理
    				else
    				{
    					// 情況二:單旋+變色
    					if (cur == parent->_left)
    					{
    						RotateR(grandfather);
    						parent->_col = BLACK;
    						grandfather->_col = RED;
    					}
    					else // 情況三:雙旋 + 變色
    					{
    						RotateL(parent);
    						RotateR(grandfather);
    						cur->_col = BLACK;
    						grandfather->_col = RED;
    					}
    
    					break;
    				}
    			}
    			else  // (parent == grandfather->_right)
    			{
    				Node* uncle = grandfather->_left;
    				if (uncle && uncle->_col == RED)
    				{
    					parent->_col = uncle->_col = BLACK;
    					grandfather->_col = RED;
    
    					cur = grandfather;
    					parent = cur->_parent;
    				}
    				else
    				{
    					if (parent->_right == cur)
    					{
    						RotateL(grandfather);
    						parent->_col = BLACK;
    						grandfather->_col = RED;
    					}
    					else
    					{
    						RotateR(parent);
    						RotateL(grandfather);
    						cur->_col = BLACK;
    						grandfather->_col = RED;
    					}
    
    					break;
    				}
    			}
    		}
    
    		_root->_col = BLACK;
    		return make_pair(iterator(newnode), true);
    	}
    
    	void RotateR(Node* parent);
    	void RotateL(Node* parent);
    
    private:
    	Node* _root;
    };

    紅黑樹的驗證

    紅黑樹的檢測分為兩步:

    • 檢測其是否滿足二叉搜索樹(中序遍歷是否為有序序列)

    • 檢測其是否滿足紅黑樹的性質

    此處用未改造過的紅黑樹

    template<class K, class V>
    struct RBTreeNode
    {
    	RBTreeNode<K, V>* _left;
    	RBTreeNode<K, V>* _right;
    	RBTreeNode<K, V>* _parent;
    
    	Colour _col;
    	pair<K, V> _kv;
    
    	RBTreeNode(const pair<K, V>& kv)
    		:_left(nullptr)
    		, _right(nullptr)
    		, _parent(nullptr)
    		, _col(RED)
    		, _kv(kv)
    	{}
    };
    
    template<class K, class V>
    class RBTree
    {
    	typedef RBTreeNode<K, V> Node;
    public:
    	RBTree()
    		:_root(nullptr)
    	{}
    
    	bool Insert(const pair<K, V>& kv);
    
    	void RotateR(Node* parent);
    	void RotateL(Node* parent);
    
    	void _InOrder(Node* root)
    	{
    		if (root == nullptr)
    		{
    			return;
    		}
    
    		_InOrder(root->_left);
    		cout << root->_kv.first << " ";
    		_InOrder(root->_right);
    	}
    
    	void InOrder()
    	{
    		_InOrder(_root);
    		cout<<endl;
    	}
    
    	bool CheckRED_RED(Node* cur)
    	{
    		if (cur == nullptr)
    		{
    			return true;
    		}
    
    		if (cur->_col == RED && cur->_parent->_col == RED)
    		{
    			cout << "違反規則三,存在連續的紅色節點" << endl;
    			return false;
    		}
    
    		return CheckRED_RED(cur->_left)
    			&& CheckRED_RED(cur->_right);
    	}
    
    	// 檢查每條路徑黑色節點的數量
    	bool CheckBlackNum(Node* cur, int blackNum, int benchmark) {
    		if (cur == nullptr) {
    			if (blackNum != benchmark){
    				cout << "違反規則四:黑色節點的數量不相等" << endl;
    				return false;}
    			return true;
    		}
    
    		if (cur->_col == BLACK)
    			++blackNum;
    
    		return CheckBlackNum(cur->_left, blackNum, benchmark)
    			&& CheckBlackNum(cur->_right, blackNum, benchmark);
    	}
    
    	bool IsBalance()
    	{
    		if (_root == nullptr)
    		{
    			return true;
    		}
    
    		if (_root->_col == RED)
    		{
    			cout << "根節點是紅色,違反規則二" << endl;
    			return false;
    		}
    
    		// 算出最左路徑的黑色節點的數量作為基準值
    		int benchmark = 0;
    		Node* cur = _root;
    		while (cur)
    		{
    			if (cur->_col == BLACK)
    			{
    				++benchmark;
    			}
    
    			cur = cur->_left;
    		}
    
    		int blackNum = 0;
    		return CheckRED_RED(_root) && CheckBlackNum(_root, blackNum, benchmark);
    	}
    
    private:
    	Node* _root;
    };
    
    void TestRBTree1()
    {
    	const int n = 1000000;
    	vector<int> a;
    	a.reserve(n);
    	srand(time(0));
    	for (size_t i = 0; i < n; ++i)
    	{
    		a.push_back(rand());
    	}
    
    	RBTree<int, int> t1;
    	for (auto e : a)
    	{
    		t1.Insert(make_pair(e, e));
    	}
    
    	cout << t1.IsBalance() << endl;
    	//t1.InOrder();
    }

    用紅黑樹封裝map、set

    紅黑樹的迭代器

    begin()與end()

    begin()可以放在紅黑樹中最小節點(即最左側節點)的位置

    end()放在最大節點(最右側節點)的下一個位置

    	typedef RBTreeIterator<T, T&, T*> iterator;
    	typedef RBTreeIterator<T, const T&, const T*> const_iterator;
    
    	iterator begin()
    	{
    		Node* left = _root;
    		while (left && left->_left)
    		{
    			left = left->_left;
    		}
    
    		//return left
    		return iterator(left);
    	}
    
    	iterator end()
    	{
    		return iterator(nullptr);
    	}

    操作符重載

    template<class T, class Ref, class Ptr>
    struct RBTreeIterator
    {
    	typedef RBTreeNode<T> Node;
    	typedef RBTreeIterator<T, Ref, Ptr> Self;
    	Node* _node;
    	RBTreeIterator(Node* node = nullptr)
    		:_node(node)
    	{}
    
    	Ref operator*()
    	{
    		return _node->_data;
    	}
    
    	Ptr operator->()
    	{
    		return &_node->_data;
    	}
    
    	Self& operator--()
    	{
    		// 跟++基本是反過來
    		return *this;
    	}
    
    	Self& operator++()
    	{
    		if (_node->_right)
    		{
    			// 右子樹中序第一個節點,也就是右子樹的最左節點
    			Node* subLeft = _node->_right;
    			while (subLeft->_left)
    			{
    				subLeft = subLeft->_left;
    			}
    
    			_node = subLeft;
    		}
    		else
    		{
    			// 當前子樹已經訪問完了,要去找祖先訪問,沿著到根節點的路徑往上走,
    			// 找孩子是父親左的那個父親節點
    			Node* cur = _node;
    			Node* parent = cur->_parent;
    			while (parent && parent->_right == cur)
    			{
    				cur = parent;
    				parent = parent->_parent;
    			}
    
    			_node = parent;
    		}
    
    		return *this;
    	}
    
    	bool operator!=(const Self& s) const
    	{
    		return _node != s._node;
    	}
    
    	bool operator==(const Self& s) const
    	{
    		return _node == s._node;
    	}
    };

    封裝map

    #pragma once
    #include "RBTree.h"
    
    namespace MyMap
    {
    	template < class K, class V>
    	class map
    	{
    		struct MapKeyOfT
    		{
    			const K& operator()(const pair<const K, V>& kv)
    			{
    				return kv.first;
    			}
    		};
    	public:
    		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
    
    		iterator begin()
    		{
    			return _t.begin();
    		}
    
    		iterator end()
    		{
    			return _t.end();
    		}
    
    		pair<iterator, bool> insert(const pair<const K, V>& kv)
    		{
    			return _t.Insert(kv);
    		}
    
    		V& operator[](const K& key)
    		{
    			pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
    			return ret.first->second;
    		}
    	private:
    		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
    	};
    
    	void test_map()
    	{
    		map<string, string> dict;
    		dict.insert(make_pair("sort", "排序"));
    		dict.insert(make_pair("string", "字符串"));
    		dict.insert(make_pair("debug", "找蟲子"));
    		dict.insert(make_pair("set", "集合"));
    
    		map<string, string>::iterator it = dict.begin();
    		while (it != dict.end())
    		{
    			cout << it->first << ":" << it->second << endl;
    			++it;
    		}
    		cout << endl;
    	}
    }

    封裝set

    #pragma once
    #include "RBTree.h"
    
    namespace MySet
    {
    	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;
    		s.insert(1);
    		s.insert(3);
    		s.insert(7);
    		s.insert(2);
    		s.insert(12);
    		s.insert(22);
    		s.insert(2);
    		s.insert(23);
    		s.insert(-2);
    		s.insert(-9);
    		s.insert(30);
    
    		set<int>::iterator it = s.begin();
    		while (it != s.end())
    		{
    			cout << *it << " ";
    			++it;
    		}
    		cout << endl;
    
    		for (auto e : s)
    		{
    			cout << e << " ";
    		}
    		cout << endl;
    	}
    }

    關于“C++中紅黑樹的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    c++
    AI

    白银市| 九龙县| 安庆市| 拜泉县| 双柏县| 金秀| 句容市| 廉江市| 手游| 扶风县| 乌兰县| 钟山县| 芜湖县| 乐亭县| 军事| 镇安县| 玉山县| 大庆市| 湟中县| 宁明县| 藁城市| 武陟县| 千阳县| 新和县| 平乡县| 大安市| 遵义市| 永胜县| 麻江县| 吉隆县| 揭阳市| 自贡市| 同心县| 聂荣县| 方城县| 濉溪县| 延安市| 南雄市| 泽州县| 溆浦县| 郁南县|