C++|二叉搜索树

一、二叉搜索树的概念

二叉搜索树又称为二叉排序树,它或者是一颗空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根结点的值
  • 它的每一颗子树都是搜索二叉树,满足该三条规则。

可以简单的总结一下,整个左子树的值比根小,整个右子树的值比根大,且每一颗子树符合该规则

例如:                    二叉搜索树                                            非二叉搜索树,3的左子树大于根

 

二、二叉搜索树的实现

二叉搜索树的实现,首先得创建一个节点类,用来存放数据,接着再创建树的框架,用来管理节点的插入,查找,删除等操作 。

2.1节点创建

实现成模板,可以存放各种类型的数据,为了让节点与节点之间关联起来,所以有两个指针,_left,_right分别指向左右节点 ,_data则是存放具体值。构造函数则是初始化节点的内容

	template<class T>
	struct BSTnode
	{
		BSTnode(const T& data = T())//初始化节点内容
			:_left(nullptr)
			, _right(nullptr)
			, _data(data)
		{}
		BSTnode<T>* _left;
		BSTnode<T>* _right;
		T _data;
	};

2.2构造与拷贝构造

创建节点后,接着创建树,用来管理节点,首先就是实现构造函数对节点进行初识化,然后实现拷贝构造,拷贝构造需要将一颗树的所有节点值全拷贝过来,故可以采用递归的方式实现。

	template<class T>
	class BSTree
	{
		typedef BSTnode<T> Node;
		typedef Node* PNode;

	public:
		BSTree()
			:_Root(nullptr)
		{}
		BSTree(const BSTree<T>& t)
		{
			_Root = CopyNode(t._Root);
		}
		PNode CopyNode(PNode Root)
		{
			if (Root == nullptr)
			{
				return nullptr;
			}
			PNode node = new Node;//创建新结点,存放节点值

			node->_data = Root->_data;//拷贝节点值
			node->_left = CopyNode(Root->_left);//链接左节点
			node->_right = CopyNode(Root->_right);//链接右节点
			return node;
		}
        
	private:
		PNode _Root;//采用节点指针
	};

2.3插入(循环版本&&递归版本)

 接下来进行具体的管理节点,首先就是节点的插入,思想的实现可以分为两个步骤:

1.树为空,则直接新增节点,赋值给_Root 指针

2.树不为空,按二叉树的性质搜索查找插入位置,插入新节点

3.若出现相同的值则不插入

二叉搜索树需要不断的进行比较,最终插入,所以其实现可以用循环和递归实现,为了表示是否插入成功,所以使其需要返回值。

例如:插入新节点,16、0。根据二叉搜索树的性质,进行比较,插入 

 

循环版本

		bool Insert(const T& data)
		{
			//空树,新增节点
			if (_Root == nullptr)
			{
				_Root = new Node;
				_Root->_data = data;
				return true;
			}
			//不为空,进行比较
			PNode cur = _Root;
			PNode parent = nullptr;//存放cur的上一个位置
			while (cur)
			{
				parent = cur;
				if (data < cur->_data)//小于根节点,则往左子树
				{
					cur = cur->_left;
				}
				else if (data > cur->_data)//大于根节点,则往右子树
				{
					cur = cur->_right;
				}
				else//有相同值,返回假
				{
					return false;
				}
			}
            //循环结束,说明找到了要插入的位置,但cur为空
            //而parent是cur的上一个位置,所以用parent比较插入
			if (data < parent->_data)
			{
				PNode node = new Node;
				node->_data = data;
				parent->_left = node;
			}
			else if (data > parent->_data)
			{
				PNode node = new Node;
				node->_data = data;
				parent->_right = node;
			}
			return true;
		}

递归版本 

        bool Insert(const T& data)
		{
			
			return _Insert(_Root,data);
		}
		bool _Insert(PNode& Root,const T& data)
		{
            //为空,新增节点,直接返回,或者,不为空在最后插入节点,返回
			if (Root == nullptr)
			{
				//PNode node = new Node;
				//Root = node;
				//node->_data = data;
                Root = new Node(data);
				return true;
			}
			if (data < Root->_data)//小于根节点,往左子树
				return _Insert(Root->_left, data);
			else if (data > Root->_data)
				return _Insert(Root->_right, data);//大于根节点,往右子树
			else
				return false;
		}

2.4查找(循环版本&&递归版本)

同理,查找需要不断进行比较,依然可以通过循化和递归实现。 查找成功,返回当前位置指针,否则返回nullptr

循环版本

        PNode Find(const T& data)
		{
			//树空
			if (_Root == nullptr)
			{
				return nullptr;
			}
			//不为空
			PNode cur = _Root;
			while (cur)
			{

				if (data < cur->_data)
				{
					cur = cur->_left;
				}
				else if (data > cur->_data)
				{
					cur = cur->_right;
				}
				else
				{
					return cur;//找到,返回该位置指针
				}
			}
			return nullptr;
		}

 

递归版本

        PNode Find(const T& data)
		{
			return _Find(_Root,data);
		}
		PNode _Find(PNode Root,const T& data)
		{
			if (Root == nullptr)
			{
				return nullptr;
			}
			if (data < Root->_data)
			{
				return 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值