833系列——二叉排序树

考纲中,二叉排序树在“查找”章节,要求为:二叉排序树及其基本操作。

其基本操作有:查找操作,插入操作,删除操作


一:定义

二叉排序树(Binary Sort Tree),又称二叉查找树,它是一颗空树,或者是具有以下性质的二叉树:

若它的左子树不空,则左子树上所有结点的值均小于它的根节点的值。

若它的右子树不空,则右子树上所有结点的值均大于它的根节点的值。

它的左右子树也都是二叉排序树

二:首先定义一个二叉树的结构

 1 struct BSTree
 2 {
 3     int data;
 4     BSTree *lchild, *rchild;
 5     BSTree(int d = 0, BSTree *l = NULL, BSTree *r = NULL)
 6     {
 7         data = d;
 8         lchild = l;
 9         rchild = r;
10     }
11 };

三:建立一个二叉排序树

二叉排序树的建立,其实就是由一个空树,一个一个的插入数据形成的,也就是需要插入操作

而在插入操作中,我们需要找到插入数据合适的位置,这里又可以看做是查找操作

插入操作有递归和循环两种写法

循环写法:

void insertTree1(BSTree* &root, int key)
{
    if(root == NULL)
    {
        BSTree *s = new BSTree(key);
        root = s;
        return;
    }
    BSTree *t = root;
    while(t->data != key)
    {
        if(key > t->data && t->rchild != NULL)
            t = t->rchild;
        else if(key < t->data && t->lchild != NULL)
            t = t->lchild;
        else if(key > t->data && t->rchild == NULL)
        {
            BSTree *s = new BSTree(key);
            t->rchild = s;
        }
        else if(key < t->data && t->lchild == NULL)
        {
            BSTree *s = new BSTree(key);
            t->lchild = s;
        }
    }
}

递归写法:

void insertTree2(BSTree* &root, int key)
{
    if(root == NULL)
    {
        BSTree *s = new BSTree(key);
        root = s;
        return;
    }
    if(key > root->data)
        insertTree2(root->rchild, key);
    else
        insertTree2(root->lchild,key);
}

查找操作由插入操作简单修改得到,不再上代码

四:删除操作(重点)

删除节点有三种情况:

要删除的点为叶子节点,直接删除即可;

要删除的点只有左子树,或只有右子树,删除节点后,将左子树或右子树整体移动到被删除节点的位置即可;

要删除的节点即有左子树,又有右子树;

第一、二种情况可以合并为第二种,第三种情况比较复杂

根据二叉排序树的定义,节点删除后,这个位置应该由与它大小相邻的数代替,对于下面这张图:

假设要删除的节点为47,那么能够代替这个位置的就是37和48,可以发现,这两个数都有一个特点,37为47的左子树中的最右子树,48为47的右子树的最左子树

基于此可以这样做:假定每次都用较小的数来代替,也就是37,此时51这边整体就不用动了,只需要将37移动到47的位置,然后将37的整个左子树移动到37原来的位置

代码:

void Delete(BSTree* &node)
{
    if(node->lchild == NULL)
    {
        BSTree *temp = node;
        node = node->rchild;
        delete(temp);
    }
    else if(node->rchild == NULL)
    {
        BSTree *temp = node;
        node = node->lchild;
        delete(temp);
    }
    else //用与该节点临近且小于的点代替
    {
        BSTree *newnode = node->lchild;
        BSTree *temp = node;
        while(newnode->rchild != NULL)
        {
            temp = newnode;
            newnode = newnode->rchild;
        }
        node->data = newnode->data;
        if(temp != node)
            temp->rchild = newnode->lchild;
        else
            temp->lchild = newnode->lchild;
        delete(newnode);
    }
}
void DeleteTree(BSTree* &root, int key)
{
    if(root == NULL)
        return;
    if(key == root->data)
        Delete(root);
    else if(key > root->data)
        return DeleteTree(root->rchild, key);
    else
        return DeleteTree(root->lchild, key);
}

五:遍历及测试数据

建好二叉排序树后,使用中序遍历,即可得到一个排好序的数列

void InOrder(BSTree *root)
{
    if(root != NULL)
    {
        InOrder(root->lchild);
        cout << root->data << " ";
        InOrder(root->rchild);
    }
}

测试数据

int main()
{
    int a[12] = {29, 36, 62, 88, 58, 47, 35, 73, 51, 99, 37, 93};
    BSTree *root = NULL;
    for(int i=0; i<12; i++)
    {
        insertTree2(root, a[i]);
    }
    InOrder(root);
    cout << endl;
    DeleteTree(root, 47);
    InOrder(root);
    return 0;
}

 

posted @ 2018-08-15 21:20  feifei97  阅读(165)  评论(0编辑  收藏  举报