【C++ 二叉搜索树】

目录

  • 1.什么是二叉搜索树
  • 2.构建二叉搜索树
    • 2.1首先搭建树的框架
    • 2.2搭建搜索树的框架
  • 3.二叉搜索树的插入
    • 3.1非递归式插入
    • 3.2递归式插入
  • 4.二叉搜索树的查找
    • 4.1非递归查找
    • 4.2递归查找
  • 5.二叉搜索树的删除
    • 5.1非递归删除
    • 5.2递归删除
  • 6.整个代码实现

1.什么是二叉搜索树

简单来讲就是一个树的左子树的值都小于根,右子树的值都大于根。如:
【C++ 二叉搜索树】_第1张图片
这个树的特点是走一趟中序就完成了对一组树的排序。查找一个树也特别的方便,最多只需要走树的高度次。所以当这个树比较饱满时搜索的效率很高,所以被称为二叉搜索树。

2.构建二叉搜索树

2.1首先搭建树的框架

struct TreeNode
{
	TreeNode<V>* _left;
	TreeNode<V>* _right;
	V _val;

	//构造函数
	TreeNode(V val)
	{
		_left = nullptr;
		_right = nullptr;
		_val = val;
	}
};

2.2搭建搜索树的框架

template<class V>
class BSTree
{
	typedef TreeNode<V> Node;
public:
	BSTree()
	{
		_head = nullptr;
	}
	private:
	Node* _head;
	
};

3.二叉搜索树的插入

3.1非递归式插入

1.思路
【C++ 二叉搜索树】_第2张图片
2.代码

//插入(非递归)
	bool insert(V val)
	{
		if (_head == nullptr)
		{
			_head = new Node(val);
			return true;
		}
		//找到要插入结点的位置
		Node* parent = _head;
		Node* cur = _head;
		while (cur)
		{
			if (cur->_val < val)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_val > val)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				//相等  返回false
				return false;
			}
		}
		//判断val插在parent的左还是右
		if (parent->_val >val)
		{
			parent->_left = new Node(val);
			return true;
		}
		else
		{
			parent->_right = new Node(val);
			return true;
		}

3.2递归式插入

	bool insertR(V val)
	{
		return _insertR(_head, val);
	}
	
    bool _insertR(Node*& head, V val)
	{
		if (head == nullptr)
		{
			head = new Node(val);
			return true;
		}
		if (head->_val > val)
		{
			_insertR(head->_left,val);
		}
		else if (head->_val < val)
		{
			_insertR(head->_right, val);
		}
		else
		{
			return false;
		}
		return false;
		
	}

注意点:这个递归式插入其实也没什么难的,就是有个注意点是要引用传参。如果不是引用传参是不会修改-head的。

4.二叉搜索树的查找

4.1非递归查找

//非递归查找
bool find(V val)
{
	if (_head == nullptr)
	{
		return false;
	}
	Node* cur = _head;
	while (cur)
	{
		if (cur->_val < val)
		{
			cur = cur->_right;
		}
		else if (cur->_val > val)
		{
			cur = cur->_left;
		}
		else
		{
			return true;
		}
	}
}

4.2递归查找

bool findR(const V& val)
{
	return _findR(_head, val);
}

bool _findR(Node* head, const V& val)
{
	if (head == nullptr)
	{
		return false;
	}
	if (head->_val == val)
	{
		return true;
	}
	return _findR(head->_left, val) || _findR(head->_right, val);
}

比较常规,没什么要解释的。

5.二叉搜索树的删除

5.1非递归删除

算法思路:
【C++ 二叉搜索树】_第3张图片

代码实现:

//非递归式删除
bool erase(const V& val)
{
	//第一步找到要删除的结点
	Node* parent = _head;
	Node* cur = _head;
	while (cur)
	{
		if (cur->_val > val)
		{
			parent = cur;
			cur = cur->_left;
		}
		else if (cur->_val < val)
		{
			parent = cur;
			cur = cur->_right;
		}
		else
		{
			//找到了
			//分情况讨论
			if (cur->_left == nullptr)
			{
				//特殊情况
				if (cur == _head)
				{
					_head = _head->_right;
					return true;
				}
				if (parent->_left == cur)
				{
					parent->_left = cur->_right;
				}
				else
				{
					parent->_right = cur->_right;
				}
				delete cur;
				return true;
			}
			else if (cur->_right == nullptr)
			{
				//特殊情况
				if (cur == _head)
				{
					_head = _head->_left;
					return true;
				}
				if (parent->_left == cur)
				{
					parent->_left = cur->_left;
				}
				else
				{
					parent->_right = cur->_left;
				}
				delete cur;
				return true;
			}
			else
			{
				//找LeftMax
				Node* parent = cur;
				Node* LeftMax = cur->_left;
				while (LeftMax->_right)
				{
					parent = LeftMax;
					LeftMax = LeftMax->_right;
				}

				//交换cur与LeftMax的val
				swap(cur->_val, LeftMax->_val);

				if (parent->_left == LeftMax)
				{
					parent->_left = LeftMax->_right;
				}
				else
				{
					parent->_right = LeftMax->_right;
				}
				delete LeftMax;
				return true;
			}
		}
	}
	return false;
}

注:这个非递归主要就是要完全考虑到删除结点会出现的可能,代码实现不复杂,但是很难一起写对,写错了调试也好很久(本人亲身经历调试了一个下午)。

5.2递归删除

算法思路:
【C++ 二叉搜索树】_第4张图片

代码实现:

bool _eraseR(Node*& head, const V& val)
	{
		if (head == nullptr)
		{
			return false;
		}
		else if (head->_val > val)
		{
			_eraseR(head->_left, val);
		}
		else if (head->_val < val)
		{
			_eraseR(head->_right, val);
		}
		else
		{
			//递归找到了
			Node* del = head;
			//三种情况
			//1.左子树为空
			if (head->_left == nullptr)
			{
				head = head->_right;
			}
			//2.右子树为空
			else if(head->_right == nullptr)
			{
				head = head->_left;
			}
			//3.左右子树都不为空
			else
			{
				//找LeftMax
				Node* LeftMax = head->_left;
				while (LeftMax->_right)
				{
					LeftMax = LeftMax->_right;
				}
				 //交换
				swap(head->_val, LeftMax->_val);
				//递归删除
				return _eraseR(head->_left, val);
			}
			delete del;
			return true;
		}
	}

6.整个代码实现

#pragma once
template<class V>
struct TreeNode
{
	TreeNode<V>* _left;
	TreeNode<V>* _right;
	V _val;

	//构造函数
	TreeNode(V val)
	{
		_left = nullptr;
		_right = nullptr;
		_val = val;
	}
};

template<class V>
class BSTree
{
	typedef TreeNode<V> Node;
public:
	BSTree()
	{
		_head = nullptr;
	}

	//深拷贝
	BSTree(BSTree<V>& bs)
	{
		_head = CopyTree(bs._head);
	}

	//赋值
	BSTree<V>& operator=(BSTree<V> bs)
	{
		swap(_head, bs._head);
		return *this;
	}
	
	//插入(非递归)
	bool insert(V val)
	{
		if (_head == nullptr)
		{
			_head = new Node(val);
			return true;
		}
		//找到要插入结点的位置
		Node* parent = _head;
		Node* cur = _head;
		while (cur)
		{
			if (cur->_val < val)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_val > val)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				//相等  返回false
				return false;
			}
		}
		//判断val插在parent的左还是右
		if (parent->_val >val)
		{
			parent->_left = new Node(val);
			return true;
		}
		else
		{
			parent->_right = new Node(val);
			return true;
		}
	}

	bool insertR(V val)
	{
		return _insertR(_head, val);
	}

	//非递归查找
	bool find(V val)
	{
		if (_head == nullptr)
		{
			return false;
		}
		Node* cur = _head;
		while (cur)
		{
			if (cur->_val < val)
			{
				cur = cur->_right;
			}
			else if (cur->_val > val)
			{
				cur = cur->_left;
			}
			else
			{
				return true;
			}
		}
	}

	bool findR(const V& val)
	{
		return _findR(_head, val);
	}



	~BSTree()
	{
		destory(_head);
	}

	void inorder()
	{
		_inorder(_head);
		cout << endl;
	}

	//非递归式删除
	bool erase(const V& val)
	{
		//第一步找到要删除的结点
		Node* parent = _head;
		Node* cur = _head;
		while (cur)
		{
			if (cur->_val > val)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_val < val)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				//找到了
				//分情况讨论
				if (cur->_left == nullptr)
				{
					//特殊情况
					if (cur == _head)
					{
						_head = _head->_right;
						return true;
					}
					if (parent->_left == cur)
					{
						parent->_left = cur->_right;
					}
					else
					{
						parent->_right = cur->_right;
					}
					delete cur;
					return true;
				}
				else if (cur->_right == nullptr)
				{
					//特殊情况
					if (cur == _head)
					{
						_head = _head->_left;
						return true;
					}
					if (parent->_left == cur)
					{
						parent->_left = cur->_left;
					}
					else
					{
						parent->_right = cur->_left;
					}
					delete cur;
					return true;
				}
				else
				{
					//找LeftMax
					Node* parent = cur;
					Node* LeftMax = cur->_left;
					while (LeftMax->_right)
					{
						parent = LeftMax;
						LeftMax = LeftMax->_right;
					}

					//交换cur与LeftMax的val
					swap(cur->_val, LeftMax->_val);

					if (parent->_left == LeftMax)
					{
						parent->_left = LeftMax->_right;
					}
					else
					{
						parent->_right = LeftMax->_right;
					}
					delete LeftMax;
					return true;
				}
			}
		}
		return false;
	}


	bool eraseR(const V& val)
	{
		return _eraseR(_head, val);
	}




private:
	Node* _head;

	void destory(Node*& head)
	{
		if (head == nullptr)
		{
			return;
		}
		destory(head->_left);
		destory(head->_right);

		delete head;
		head = nullptr;
	}

	bool _insertR(Node*& head, V val)
	{
		if (head == nullptr)
		{
			head = new Node(val);
			return true;
		}
		if (head->_val > val)
		{
			_insertR(head->_left,val);
		}
		else if (head->_val < val)
		{
			_insertR(head->_right, val);
		}
		else
		{
			return false;
		}
		return false;
		
	}

	void _inorder(Node* head)
	{
		if (head == nullptr)
		{
			return;
		}
		_inorder(head->_left);
		cout << head->_val << " ";
		_inorder(head->_right);
	}

	bool _findR(Node* head, const V& val)
	{
		if (head == nullptr)
		{
			return false;
		}
		if (head->_val == val)
		{
			return true;
		}
		return _findR(head->_left, val) || _findR(head->_right, val);
	}

	bool _eraseR(Node*& head, const V& val)
	{
		if (head == nullptr)
		{
			return false;
		}
		else if (head->_val > val)
		{
			_eraseR(head->_left, val);
		}
		else if (head->_val < val)
		{
			_eraseR(head->_right, val);
		}
		else
		{
			//递归找到了
			Node* del = head;
			//三种情况
			//1.左子树为空
			if (head->_left == nullptr)
			{
				head = head->_right;
			}
			//2.右子树为空
			else if(head->_right == nullptr)
			{
				head = head->_left;
			}
			//3.左右子树都不为空
			else
			{
				//找LeftMax
				Node* LeftMax = head->_left;
				while (LeftMax->_right)
				{
					LeftMax = LeftMax->_right;
				}
				 //交换
				swap(head->_val, LeftMax->_val);
				//递归删除
				return _eraseR(head->_left, val);
			}
			delete del;
			return true;
		}
	}

	Node* CopyTree(Node* head)
	{
		if (head == nullptr)
		{
			return nullptr;
		}
		Node* newhead = new Node(head->_val);
		newhead->_left = CopyTree(head->_left);
		newhead->_right = CopyTree(head->_right);

		return newhead;
	}
	
};

你可能感兴趣的:(c++,算法,数据结构)