C++:二叉搜索树的模拟实现

  • 二叉搜索树的查找效率:
    最优情况下,二叉搜索树为完全二叉树时,效率为logN;
    最坏情况下,二叉搜索树为单支树,效率为N/2。
  • 定义结点:
	template <class T>
	struct BSTNode
	{
		BSTNode(const T& kv = T())
		:_left(nullptr)
		, _right(nullptr)
		, _kv(kv)
		{}

		BSTNode<T>* _left;
		BSTNode<T>* _right;
		T _kv;
	};

  • 二叉搜索树的构造和析构:
	class BSTree
	{
		typedef BSTNode<T> Node;//结点
		typedef Node* pNode;//指向结点的指针
	public:
		//构造
		BSTree()
			:root(nullptr)
		{}

		//析构
		~BSTree()
		{
			_Destroy(root);
		}
		
    private:
       void _Destroy(pNode& root)
       {
           if(root)
           {
               _Destroy(root->_left);
               _Destroy(root->_right);
               root = nullptr;
           }
        }
        
       pNode root;
   }
  • 拷贝和赋值(可以用swap函数):
   Node* Copy(Node* root)
   {
       if(root == nullptr)
           return nullptr;
       Node* newroot = new Node(root->_kv);
       newroot->_left = Copy(root->_left);
       newroot->_right = Copy(root->_right);
       return newroot;
   }
   //拷贝
  BSTree(const BSTree<T>& tree)
  {
       root = Copy(tree->root);
  }
  //复制
  BSTree<T>& operator = (const BSTree<T>& tree)
  {
		if (this != &tree)
		{
			_Destroy(this->root);
			this->root = Copy(tree->root);
			return *this;
		}
  }
  BSTree<T>& operator = (const BSTree<T>& tree)
  {
		swap(this->root, tree->root);
		return *this;
  }
  • 二叉搜索树的插入和遍历:
		//插入
		bool Insert(const T& kv)
		{
			//1.如果树为空,直接插入根节点
			if (root == nullptr)
			{
				root = new Node(kv);
				return true;
			}
			//2.树不为空,找插入位置
			Node* cur = root;
			Node* parent = nullptr;
			while (cur)
			{
				parent = cur;
				if (kv < cur->_kv)
					cur = cur->_left;
				else if (kv > cur->_kv)
					cur = cur->_right;
				else
					return false;
				//否则,存在该结点,返回false
			}
			//3.位置找到(此时,cur为空),插入元素
			cur = new Node(kv);
			if (kv < parent->_kv)
				parent->_left = cur;
			else
				parent->_right = cur;
			return true;
		}
	//遍历
		void _inorder(Node* root)
		{
			if (root == nullptr)
				return;
			_inorder(root->_left);
			cout << root->_kv << " ";
			_inorder(root->_right);
			cout << endl;
		}

		void Print()
		{
			_inorder(root);
		}
  • 二叉树的删除:
		bool Erase(const T& kv)
		{
			//1.树为空,删除失败
			if (root == nullptr)
				return false;
	        //2.树不为空,找位置
			Node* cur = root;
			Node* parent = nullptr;
			while(cur)
			{
				if (cur->_kv == kv)
				{
					break;
				}
				else if (kv < cur->_kv)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					parent = cur;
					cur = cur->_right;
				}
			}
			//此时cur为空,表示没找到
			if (cur == nullptr)
				return false;

			//3.删除元素
			//结点的左为空,父亲指向结点的有右
			if (cur->_left == nullptr)
			{
				if (cur == root)//结点为根节点
					root = cur->_right;
				else
				{
					if (cur == parent->_left)//结点在父亲的左边
						parent->_left = cur->_right;
					else
						parent->_right = cur->_right;//结点在父亲的右边
				}
				delete cur;
			}
			//结点的右为空,父亲指向结点的左
			else if (cur->_right == nullptr)
			{
				if (cur == nullptr)
					root = cur->_left;
				else
				{
					if (cur == parent->_left)
						parent->_left = cur->_left;
					else
						parent->_right = cur->_left;
				}
				delete cur;
			}
			//结点的左右都不为空,找左树的最大结点或者右树的最小结点作为替换结点
			else
			{
				Node* replace = cur->_right;
				Node* preplace = nullptr;
				while (replace->_left)
				{
					preplace = replace;
					replace = replace->_left;
				}
				cur->_kv = replace->_kv;
				if (replace == preplace->_left)
					preplace->_left = nullptr;
				else
					preplace->_right = nullptr;
				delete replace;
				replace = nullptr;
			}
			return true;
		}
  • 二叉树的查找:
		Node* Find(const T& kv)
		{
			Node* cur = root;
			while (cur)
			{
				if (kv == cur->_kv)
					return cur;
				else if (kv < cur->_kv)
					cur = cur->_left;
				else
					cur = cur->_right;
			}
			return nullptr;
		}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值