首页 > 其他分享 >【手撕红黑树】

【手撕红黑树】

时间:2024-07-13 14:25:33浏览次数:13  
标签:黑树 Node return cur key left root 撕红

二叉搜索树

作为一种二叉树类型的数据结构,掌握期性质是首要.

总的说就是,以某结点为视角,其左子树均为小于该结点值的结点,而右子树相反,且无重复值的结点.

 性质:去重性,有序性.

自主实现

 构造逻辑:但凡实现某功能,作为程序员,既要站在底层的角度,也要多从用户角度去考虑;

这是个二叉树数据结构,对其访问,用户仅需声明对应的类,然后调用对应的功能接口,

那我们就应这样思考,首先这主角对象应构建出来,即对结点进行创建,他包含什么成员变量,可以或应该提供什么接口,在这仅需描述出具体对象即可,接口不需要

接下来是对是操作方面的构建,对着结点,以怎样的数据结构管理,因该或可以提供什么接口,

这是对操作的封装,站在用户角度更佳.

对一个任务的具体分析,在分解至较小步骤,这样不至于不知怎么着手

1.单值数据成员

 明确结构:1.一个含模板Node类描述结点,包括成员变量指针,数据成员,构造函数初始化;

2.一个BinarySearchTree类,提供二叉搜索树的功能接口,插入,删除,查找,判断(可补充 求高度,结点个数);

知识点:对链表的结点操作(增删查改),指针运用,递归的运用(前,中序遍历,如何通过递归返回需求值).体会类和对象的封装性,面相对象.

收获:为什么递归要封装一层函数(提供给用户接口,封装性),搜索树的拷贝需要深拷贝,

BSTree() =default;禁止生成默认构造函数-为什么,有什么意义:a.强制初始化,b.避免产生无意义的对象,c.强制采用特定的构造方式. 本例子中,创造没有根结点的二叉树是无意义的

2.双值数据成员

目的:为后续键值对数据类型的学习做铺垫

大致内容相似,就数据成员的改动.

3.实现代码

#pragma once

#include<iostream>
#include<cassert>
//命名空间
namespace key
{
    //结点的构建
	template<class K>
	struct BSTreeNode
	{

		typedef BSTreeNode<K> Node;
		Node* _left;
		Node* _right;
		K _key;
		BSTreeNode(const K key)
			:_left(nullptr), _right(nullptr), _key(key)
		{

		}
	};



    //二叉搜索树的接口实现--因为提供给用户,无法访问私有成员,所以在需要根节点是,封装一层函数
	template<class K>
	class BSTree
	{
		typedef BSTreeNode<K> Node;
	public:
		BSTree() =default;

		BSTree(const BSTree<K>& t)
		{
			_root = Copy(t._root);//?
		}

		void swap(Node* &p1, Node* &p2)
		{
			
			p1 = deepCopyTree(p2);
		}
		BSTree <K>& operator=( BSTree<K> &t)
		{
			swap(_root,t._root);
			return *this;
		}
		~BSTree()
		{
			Destroy(_root);
		}
		bool Find(const K key)
		{
			if (nullptr == _root)
			{
				return false;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					return true;
				}
			}
			return false;
		}
		bool Insert(const K key)
		{
			if (nullptr == _root)
			{
				//Node newNode = new Node(key);
				//_root = &newNode;
				_root = new Node(key);
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(key);
			if (key < parent->_key)
			{
				parent->_left = cur;;
			}
			else
			{
				parent->_right = cur;
			}
			return true;
		}
		bool Erase(const K key)
		{
			if (nullptr == _root)
			{
				return false;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					if (cur == _root)
					{
						delete cur;
						_root = nullptr;
					}
					if (cur->_left == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_right;
							delete cur;
							return true;
						}
						if (cur == parent->_left)
						{
							parent->_left = cur->_right;
						}
						else
						{
							parent->_right = cur->_right;
						}
						delete cur;
						return true;
					}
					else if (cur->_right == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_left;
							delete cur;
							return true;
						}
						if (cur == parent->_left)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
						delete cur;

						return true;

					}
					else
					{
						Node* LeftMaxParent = cur;
						Node* LeftMax = cur->_left;
						while (LeftMax->_right)
						{
							LeftMaxParent = LeftMax;
							LeftMax = LeftMax->_right;
						}
						cur->_key = LeftMax->_key;
						if (LeftMax == LeftMaxParent->_left)
						{
							LeftMaxParent->_left = LeftMax->_left;
						}
						else
						{
							LeftMaxParent->_right = LeftMax->_left;
						}
						delete LeftMax;
						return true;
					}
				}
			}
			return false;
			
		}
		void Inorder()
		{			
			return _Inorder(this->_root);

		}
/*---------------------------------------------------------*/
		bool FindR(const K& key)
		{
			return _FindR(_root,key);
		}

		bool InsertR(const K& key)
		{
			return _InsertR(_root, key);
		}

		bool EraseR(const K& key)
		{
			return _EraseR(_root, key);
		}

	private:
			bool _FindR(Node* root, const K& key)
			{
				if (root == nullptr)
				{
					return false;
				}
				if (key < root->_key)
				{
					return _FindR(root->_left,key);
				}
				else if (key > root->_key)
				{
					return _FindR(root->_right, key);
				}
				else
				{
					return true;
				}
			}

			bool _InsertR(Node*& root, const K& key)
			{
				if (root == nullptr)
				{
					root = new Node(key);
					return true;
				}
				if (key < root->_key)
				{
					return _InsertR(root->_left, key);
				}
				else if (key > root->_key)
				{
					return _InsertR(root->_right, key);
				}
				else
				{
					return false;
				}
			}

			bool _EraseR(Node*& root, const K& key)
			{
				if (root == nullptr)
				{
					return false;
				}
				if (key < root->_key)
				{
					return _EraseR(root->_left, key);
				}
				else if (key > root->_key)
				{
					return _EraseR(root->_right, key);
				}
				else
				{
					if (root->_left == nullptr)
					{
						Node* tmp = root;
						root = root->_right;
						delete tmp;
						return true;
					}
					else if (root->_right == nullptr)
					{
						Node* tmp = root;
						root = root->_left;
						delete tmp;
						return true;
					}
					else
					{
						Node* LeftMaxParent = root;
						Node* LeftMax = root->_left;
						while (LeftMax->_right)
						{
							LeftMaxParent = LeftMax;
							LeftMax = LeftMax->_right;
						}
						root->_key = LeftMax->_key;
						if (LeftMax == LeftMaxParent->_left)
						{
							LeftMaxParent->_left = LeftMax->_left;
						}
						else
						{
							LeftMaxParent->_right = LeftMax->_left;
						}
						delete LeftMax;
						return true;
					}
				}
			}
	private:
		Node* deepCopyTree(const Node* root) {
			if (root == nullptr) {
				return nullptr;
			}

			// 创建当前节点的拷贝
			Node* newNode = new Node(root->_key);

			// 递归拷贝左子树和右子树
			newNode->_left = deepCopyTree(root->_left);
			newNode->_right = deepCopyTree(root->_right);

			return newNode;
		}
		void Destroy(const Node* root)
		{
			if (root == nullptr) return;
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
		}
		Node* Copy(const Node* root)
		{
			/*Node* newRoot = new Node(root->_key);
			newRoot->_left = root->_left;
			newRoot->_right = root->_right;
			return newRoot;*/
			return deepCopyTree(root);
		}
		void _Inorder(const Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			_Inorder(root->_left);
			std::cout << root->_key << " ";
			_Inorder(root->_right);
		}
	private:
		Node* _root = nullptr;
	};
}


//体会双值的区别,为键值对做铺垫
namespace key_value
{
	template<class K,class V>
	struct BSTreeNode
	{

		typedef BSTreeNode<K,V> Node;
		Node* _left;
		Node* _right;
		K _key;
		V _value;
		BSTreeNode(const K key,const V value)
			:_left(nullptr), _right(nullptr), _key(key), _value(value)
		{

		}
	};
	template<class K,class V>
	class BSTree
	{
		typedef  BSTreeNode<K,V> Node;
	public:
		bool Find(const K key)
		{
			if (nullptr == _root)
			{
				return false;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					return true;
				}
			}
			return false;
		}
		bool Insert(const K key,const V value)
		{
			if (nullptr == _root)
			{
				//Node newNode = new Node(key);
				//_root = &newNode;
				_root = new Node(key, value);
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(key, value);
			if (key < parent->_key)
			{
				parent->_left = cur;;
			}
			else
			{
				parent->_right = cur;
			}
			return true;
		}
		bool Erase(const K key)
		{
			if (nullptr == _root)
			{
				return false;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					if (cur == _root)
					{
						delete cur;
						_root = nullptr;
					}
					if (cur->_left == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_right;
							delete cur;
							return true;
						}
						if (cur == parent->_left)
						{
							parent->_left = cur->_right;
						}
						else
						{
							parent->_right = cur->_right;
						}
						delete cur;
						return true;
					}
					else if (cur->_right == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_left;
							delete cur;
							return true;
						}
						if (cur == parent->_left)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
						delete cur;

						return true;

					}
					else
					{
						Node* LeftMaxParent = cur;
						Node* LeftMax = cur->_left;
						while (LeftMax->_right)
						{
							LeftMaxParent = LeftMax;
							LeftMax = LeftMax->_right;
						}
						cur->_key = LeftMax->_key;
						if (LeftMax == LeftMaxParent->_left)
						{
							LeftMaxParent->_left = LeftMax->_left;
						}
						else
						{
							LeftMaxParent->_right = LeftMax->_left;
						}
						delete LeftMax;
						return true;
					}
				}
			}
			return false;

		}
		void Inorder()
		{
			return _InOrder(this->_root);
			std::cout << std::endl;
		}
		private:
			void _InOrder(Node* root)
			{
				if (root == nullptr)
					return;

				_InOrder(root->_left);
				std::cout << root->_key << " "<<root->_value<<" "<<std::endl;
				_InOrder(root->_right);
			}
		private:
			Node* _root = nullptr;
	};
}

标签:黑树,Node,return,cur,key,left,root,撕红
From: https://blog.csdn.net/2303_76993116/article/details/140397088

相关文章

  • 【简易版tinySTL】 红黑树- 定义, 插入, 构建
    文章目录旋转左旋右旋左旋右旋代码实现红黑树的基本性质红黑树的插入红黑树的插入示例红黑树修复代码实现参考资料旋转对于一个平衡二叉搜索树,左子树高度为4,右子树高度为2,它们的高度差为2,破坏了平衡性(高度差<2才算平衡,因此需要调整二叉树使其平衡)二叉树最基本的......
  • 数据结构与算法-红黑树的java实现-构建红黑树
    红黑树红黑树是一种二分查找树,与普通的二分查找树不同的一点是,红黑树的每个节点都有一个颜色(color)属性。该属性的值要么是红色,要么是黑色。通过限制从根到叶子的任何简单路径上的节点颜色,红黑树确保没有比任何其他路径长两倍的路径,从而使树近似平衡。节点红黑树的节......
  • [C++][数据结构][红黑树]详细讲解
    目录1.红黑树的概念2.红黑树的性质3.红黑树节点的定义4.红黑树的结构5.红黑树的插入操作1.cur为红,p为红,g为黑,u存在且为红2.cur为红,p为红,g为黑,u不存在/u存在且为黑--单旋+变色3.cur为红,p为红,g为黑,u不存在/u存在且为黑--双旋+变色6.红黑树的迭代器1.begin()与end()2.o......
  • C++ -- 红黑树的基本操作
    目录摘要基本规则基本操作利用Graphviz库总结摘要红黑树是一种自平衡的二叉搜索树,它在插入和删除节点时,通过颜色和旋转操作保持树的平衡,确保插入、删除和查找的时间复杂度都是(O(logn))。红黑树的每个节点都有一个颜色属性,红色或黑色。通过一些规则,红黑树保持了相对......
  • Java基础:B树、B+树和红黑树的数据结构,三者区别
    B树(B-Tree)数据结构节点结构:每个节点包含多个键值和子节点指针。阶(Degree):B树的阶定义了每个节点的最小和最大键值数。对于阶为(m)的B树:每个节点最多有(m-1)个键值和(m)个子节点。每个节点(除了根节点)至少有(\lceilm/2\rceil-1)个键值和(\lceilm/......
  • 红黑树/红黑树迭代器封装(C++)
        本篇将会较为全面的讲解有关红黑树的特点,插入操作,然后使用代码模拟实现红黑树,同时还会封装出红黑树的迭代器。    在STL库中的set和map都是使用红黑树封装的,在前文中我们讲解了AVL树,对于红黑树和AVL树来说,这两种树都是效率很高的搜索二叉树,但是......
  • 拿捏红黑树(C++)
    文章目录前言一、红黑树介绍二、插入操作三、验证红黑树四、红黑树与AVL性能比较与应用五、总体代码总结前言我们之前介绍了一种AVL的高阶数据结构,在本篇文章中,我们将会介绍一种与AVL旗鼓相当的数据结构–红黑树。我们并且会对它的部分接口进行模拟实现一、红黑树......
  • 红黑树-数据结构
    平衡二叉B树每个节点可以是红或者是黑红黑树不是高度平衡的,他的平衡是“通过自己的红黑规则实现的”红黑规则每个节点是红或者为黑根节点必须是黑色如果一个节点没有子节点或者是父节点,这个节点的相应的指针属性为nil,这些nil视为叶节点,每个叶节点nil是黑色的如果某个节......
  • 重学java 58.红黑树相关集合
    现在还来得及                ——24.6.3一、TreeSet1.概述:        Treeset是set的实现类2.特点:        a.对元素进行排序        b.无索引        c.不能存null        d.线程不安全    ......