Binary search tree
Defined
binary search trees (binary sort tree) may be an empty tree (no nodes)
may be:
if its left subtree is not empty, the left sub-tree nodes are all less than the value of the root node
If its right subtree is not empty, then all nodes have the right subtree of the root node is greater than the value of
its left and right subtrees are also binary search tree must be
shown:
the left-most value is the minimum constant, the far right is the maximum value must
Node Structure
template<class T> //模板参数
struct BSTNode
{
BSTNode(const T& data = T()) //初识化时先将其指针都置空
:_data(data)
, _pLeft(nullptr)
, _pRight(nullptr)
{}
T _data;
BSTNode<T>* _pLeft; //左孩子指针
BSTNode<T>* _pRight; //右孩子指针
};
Insert
The first case: the tree is empty tree
PRoot node directly apply the value of the data placed in the Root node
The second case: the tree is not empty
Defined pParent, pCur node, a node is traversed downward with Pcur (traverse conditions: the value of the data> data is greater than pCur-, pCur traverse right child, otherwise, the left child Pcur traversal, followed pParent )
bool Insert(const T& data)
{
//空树
if (_pRoot == nullptr)
{
_pRoot = new Node(data);
return true;
}
//按照二叉搜索树性质找当前接结点的位置
Node* pCur = _pRoot;
Node* pParent = nullptr;
while (pCur)
{
pParent = pCur;
if (data < pCur->_data)
pCur = pCur->_pLeft;
else if (data > pCur->_data)
pCur = pCur->_pRight;
else
return false;
}
//进行插入
pCur = new Node(data);
if (data < pParent->_data)
pParent->_pLeft = pCur;
else
pParent->_pRight = pCur;
return true;
}
Deletion
The first case: Remove leaf nodes (nodes there are two empty Delete Tree)
Just delete it.
The second case: Remove only one child node (there is an empty deleted node tree)
The direct delete nodes, the parent node and the node to the next node. There is only need to divide the child's situation and the presence of left only with children.
The first case may merge in the second case
The third case: delete nodes with two children
We need to find a replacement node.
Replace the nodes may be looking in the left subtree largest node, or to find the smallest node in the right subtree below shows a summary of points to find the best replacement in the right sub-tree, remove the specified node, then change some pointers
Finally, a total of two cases, as follows:
//删除结点
/*1.叶子结点---直接删除
2.只有左孩子||只有右孩子(叶子节点可以合并于此)---直接删除
3.左右孩子都村在---找一个替代节点(该结点的左子树中最大或者右子树中最小)
*/
bool Delete(const T& data)
{
//空树,直接返回
if (_pRoot == nullptr)
return false;
Node* pCur = _pRoot;
Node* pParent = nullptr;
//找待删除结点pCur
while (pCur)
{
if (data == pCur->_data)
break;
else if (data < pCur->_data)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else
{
pParent = pCur;
pCur = pCur->_pRight;
}
}
//pCur只有右孩子
if (nullptr == pCur->_pLeft)
{
//根节点
if (pCur == _pRoot)
_pRoot = pCur->_pRight;
//待删除结点在父节点的左边还是右边
else
{
if (pParent->_pLeft == pCur)
pParent->_pLeft = pCur->_pRight;
else
pParent->_pRight = pCur->_pRight;
}
}
else if (nullptr == pCur->_pRight) //pCur只有左孩子
{
if (pCur == _pRoot)
_pRoot = pCur->_pLeft;
else
{
if (pParent->_pLeft == pCur)
pParent->_pLeft = pCur->_pLeft;
else
pParent->_pRight = pCur->_pLeft;
}
}
else //左右孩子都有
{
//找右边最左边的结点进行替换
Node* pRSwap = pCur->_pRight;
pParent = pCur;
while (pRSwap->_pLeft)
{
pParent = pRSwap;
pRSwap = pRSwap->_pLeft;
}
pCur->_data = pRSwap->_data;
//将pSwap右边的树与pParent结点连接
if (pRSwap == pParent->_pLeft)
pParent->_pLeft = pRSwap->_pRight;
else
pParent->_pRight = pRSwap->_pRight;
pCur = pRSwap;
}
Find operation
Find the specified node same time lookup and delete operations, use direct comparison can traverse.
Node* Find(const T& data) const
{
Node* pCur = _pRoot;
while (pCur)
{
if (data == pCur->_data)
return pCur;
else if (data < pCur->_data)
pCur = pCur->_pLeft;
else
pCur = pCur->_pRight;
}
return nullptr;
}
Take maximum and minimum
Minimum: stored in the leftmost binary search tree of
maximum: Store in the rightmost binary search tree
Node* LeftMost() const
{
if (nullptr == _pRoot)
return nullptr;
Node* pCur = _pRoot;
while (pCur->_pLeft)
pCur = pCur->_pLeft;
return pCur;
}
Node* RightMost() const
{
if (nullptr == _pRoot)
return nullptr;
Node* pCur = _pRoot;
while (pCur->_pRight)
pCur = pCur->_pRight;
return pCur;
}
Traversal operation
Preorder traversal: first traversal root, traversing the left subtree, traversing right subtree
traversal sequence: first traverse the left subtree, the root node in the traversal, the traversal right subtree
traversal sequence : can print two ascending binary search tree
postorder: binary search tree while complete destruction operation
preorder codes:
void _InOrder(Node* _pRoot)
{
if (_pRoot)
{
_InOrder(_pRoot->_pLeft);
cout << _pRoot->_data << " ";
_InOrder(_pRoot->_pRight);
}
}
Destruction Empty
Use post-order traversal of the destruction of binary search tree, so you can make more orderly release nodes, so as to achieve no leakage, no heavy destruction.
void _Destroy(Node*& _pRoot)
{
if (_pRoot)
{
_Destroy(_pRoot->_pLeft);
_Destroy(_pRoot->_pRight);
delete _pRoot;
}
}
to sum up
- Insert and delete operations must find the location to be operated in a manner to find, so look for performance also represents the performance of insertions and deletions.
- Binary tree of the deeper nodes, the more the number of cycles to find .
- For insertion order will affect the structure of a binary search tree, the different structure of the same binary search tree, it affects the search efficiency of a binary tree. As shown below: Insert {6,4,5,8,3,5,7,9} {3,4,5,6,7,8,9} and the insertion of different binary search tree.