定义:BST--二叉排序树,二叉搜索树 1.要么是空树,要么具有下列性质 2.如果左子树不空,则左子树的结点的值小于根结点,并且左子树也是一棵BST 3.如果右子树不空,则右子树的结点的值大于根结点,并且右子树也是一棵BST 4.按照中序遍历,则从小到大排序好的 5.最左边的孩子,一定是最小的 6.最右边的孩子,一定是最大的 7.查找方便,插入和删除也比较方便(不用大量的移动元素)
使用排序二叉树的原因:
顺序表如果按顺序存储虽然有利于查找,但是插入删除需要移动大量的元素。即使我们现在使用链表结构,但是要保证数据有序存储,插入、删除虽然不需要像线性表那样大量的移动元素,但是查找依旧很麻烦。
所以我们使用二叉排序树,依照它的特性,不仅可以将数据有序存储,插入、删除数据结点也很方便。对于查找最少1次,即是根节点,最多也就是树的深度;由于保持了链表存储结构,所以在插入、删除时只需要找到合适的位置,修改链接指针即可。(这里的删除我们使用的是替换,因为如果是单纯的删除,需要改动的链接指针较多,性能不高)
插入结点:
void BSTree::InsertBSTValue(Node*& root, int v)
{//BSTree是二叉排序树的类型,Node是结点类型
//BSTree类中有Node类型的m_root, 还有相关的方法
if(root == NULL)
{
root = new Node(v);
}
else if(v < root->m_value)
{
InsertBSTValue(root->m_left, v);
}
else if(v > root->m_value)
{
InsertBSTValue(root->m_right, v);
}
}
int main()
{
int num[] = { 62,88,58,47,35,73,51,99,37,93 };
BSTree t;
int n=sizeof(num)/sizeof(num[0]);
for(int i=0;i<n;i++)
{//循环插入
t.InsertBSTValue(t.m_root,num[i])
}
rturn 0;
}
排序:
//根据二叉排序树的特点直接中序遍历输出就是排好序的
void BSTree::Sort(Node* root)
{
if(root!=NULL)
{
Sort(root->m_left);
cout<<root->m_value<<" ";
Sort(root->m_right);
}
}
查找值为k的结点:
Node* BSTree::SearchValue(Node* root, int k)
{
if(root==NULL)
return NULL;//已经找到叶子结点的孩子了,还没有找到,即是没有
else if(k < root->m_value)
SearchValue(root->m_left, k);
else if(k > root->m_value)
{
SearchValue(root->m_right, k);
}
else
{
return root;
}
}
删除值为k 的结点:
分三种情况:
1、k 为根结点,直接删除即可。
2、k 只有左孩子或者右孩子,将 k 结点删除后,将它的左子树或者右子树整个移动到删除结点也就是 k 结点的位置。
3、k 既有左孩子又有右孩子,为了删除后保持二叉排序树的特点,需要用第一个左孩子的右侧孩子替换(直接前驱),或者用第一个右孩子的最左侧孩子替换(直接后继),最后将替换结点删掉即可,而替换 k 的结点肯定符合1或2的情况,很容易删掉;之所以不用删除而用替换是因为删除以后,需要对其右子树或者左子树重新插入,不仅效率不高,而且二叉排序树的结构也会发生变化,树的高度也可能会增加,这也会影响到效率。
代码:
void BSTree::DelValue(Node*& root, int k)
{
Node* temp=NULL:
if(root != NULL)
{
if(k < root->m_value)
{
DelValue(root->m_left, k);
}
else if(k > root->m_value)
{
DelValue(root->m_right, k);
}
else if(root->m_left != NULL && root->m_right != NULL)
{
//用第一个右孩子的最左侧孩子替换
temp = root->m_right;
while(temp != NULL)
{
temp =temp->m_left;
}
root->m_value=temp->m_value;
//最后在被替换(k)结点的右子树中找到替换它的结点并删除
DelValue(root->m_right, root->m_value);
}
else//1,2两种情况
{
temp = root;
if (root->m_left == NULL)
root = root->m_right;
else
root = root->m_left;
delete temp;
temp = NULL;
}
}
}