zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    leetcode每日刷题计划-简单篇day28
    leetcode每日刷题计划-简单篇day27
    leetcode每日刷题计划-简单篇day26
    leetcode每日刷题计划-简单篇day25
    java多线程--大作业相关
    leetcode每日刷题计划-简单篇day24
    leetcode每日刷题计划-简单篇day23
    SpringBoot集成JWT实现token验证
    RabbitMQ 延迟队列,消息延迟推送的实现
    Redis精进:List的使用和应用场景
  • 原文地址:https://www.cnblogs.com/flyuz/p/9484100.html
Copyright © 2011-2022 走看看