什么是BST
BST树(Binary Search Tree)二叉搜索树
其性质如下:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉查找树。
如下图所示:
BST的构造
// 定义BST树节点的类型
struct BSTNode
{
BSTNode(T data = T())
:_data(data)
, _left(nullptr)
, _right(nullptr)
{
}
T _data;
BSTNode *_left;
BSTNode *_right;
};
BSTNode *_root; // 指向树的根节点
BST的遍历和排序(中序遍历即可)
对于已知的二叉查找树的从小到大排序就是他的中序遍历顺序
即从根节点开始,若有左子树则递归输出左子树直到叶子结点,再输出自身,再递归输出右子树。
如图所示:
如图:
前序遍历:45->20->10->35->31->25->37->56->49->51->60
中序遍历:10->20->25->31->35->37->45->49->51->56->60
后序遍历:10->25->31->37->35->20->51->49->60->56->45
代码如下:
public:
void Pre_out()
{
Pre_out(_root);
cout << endl;
}
void Mid_out()
{
Mid_out(_root);
cout << endl;
}
void Last_out()
{
Last_out(_root);
cout << endl;
}
private:
void Pre_out(BSTNode *node) //前序遍历
{
if (node != nullptr)
{
cout << node->_data << " ";
Pre_out(node->_left);
Pre_out(node->_right);
}
}
void Mid_out(BSTNode *node) //中序遍历
{
if (node != nullptr)
{
Mid_out(node->_left);
cout << node->_data << " ";
Mid_out(node->_right);
}
}
void Last_out(BSTNode *node) //后序遍历
{
if (node != nullptr)
{
Last_out(node->_left);
Last_out(node->_right);
cout << node->_data << " ";
}
}
BST的查找
在已存在的BST中查找值为value的结点
思路:
从根结点开始查找
如果要查的值value等于当前节点的值,则返回true。
如果要查的值value小于当前节点的值,则在当前节点的左子树中查找;
如果要查的值value大于当前节点的值,则在当前节点的右子树中查找;
如果查完没有找到一个结点的值为value则返回false,否则返回true。
bool query(const T &val) //实现BST树查找指定的元素值val是否存在
{
if (_root == nullptr) //判断树是否存在
{
return false;
}
BSTNode*ptmp = _root;
while (ptmp != nullptr&&ptmp->_data != val) //若ptmp为空则已经遍历完整个树了
{
if (val < ptmp->_data)
{
ptmp = ptmp->_left;
}
if (val > ptmp->_data)
{
ptmp = ptmp->_right;
}
}
//退出的while循环的条件有两个
//一个是搜索完了整个树,没有找到一个结点的值为val
if (ptmp == nullptr)
{
return false;
}
//另外一个是找到了
return true;
}
BST的插入
思路:
从根节点开始插入
如果要插入的值value小于等于当前节点的值,则在当前节点的左子树中插入;
如果要插入的值value大于当前节点的值,在当前节点的右子树中插入;
如果节点为空节点,则找到该结点的父结点在此建立新的结点并判断是父结点的左孩子还是右孩子
//非递归实现BST树的插入操作
void noninsert(const T &val)
{
if (_root == nullptr) //判断树是否存在
{
_root = new BSTNode(val);
return;
}
BSTNode *pre = nullptr; //插入点,用于最后一步的插入
BSTNode *tmp = _root; //用于寻找插入点
while (tmp != nullptr)
{
pre = tmp; //实时更新插入点的父结点