二叉排序树(BST)

定义

二叉排序树(Binary Search Tree,BST),又称二叉搜索树,是一种特殊的二叉树数据结构,要么为空树,要么为具有下面特性的二叉树

对于树中的任意节点:

  • 若左子树非空,左子树中所有节点的值都小于该节点的值
  • 若右子树非空,右子树中所有节点的值都大于该节点的值
  • 左右子树也都是二叉排序树

根据二叉排序树的定义,左子树节点值<根节点值<右子树节点值,因此对二叉排序树进行中序遍历,将得到一个递增有序序列,如下图,进行中序遍历将得到序列:8,10,11,12,13,15,16,17,18,19,22,25

定义一个二叉排序树结构:

typedef int DataType;
typedef struct BST_Node {
    DataType data;
    struct BST_Node *lchild, *rchild;
}BST_T, *BST_P;

二叉排序树的构造

代码实现:

void CreateBST(BST_P *T, int a[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        Insert_BST(T, a[i]);
    }
}

二叉排序树的查找

二叉排序树的查找从根节点开始,利用BST的有序性质,进行递归查找:

  • 如果目标值等于当前节点值,找到目标
  • 如果目标值小于当前节点值,在左子树查找
  • 如果目标值大于当前节点值,在右子树查找

时间复杂度:平均O(log2n),最坏情况查找的值在最右下方,复杂度为O(n)

递归实现:

BST_P Search_BST(BST_P root, DataType key)
{
    if (root == NULL)
        return NULL;
    if (key > root->data) //查找右子树  
        return Search_BST(root->rchild, key);
    else if (key < root->data) //查找左子树  
        return Search_BST(root->lchild, key);
    else
        return root;
}

非递归:

BST_P Search_BST(BST_P root, DataType key)
{
    while (root != NULL && root->data != key) 若树空或等于根节点值,退出循环
    {       
       if(key < T->data)  T = T->lchild; //小于,查找左子树
       else T = T->rchild; //大于,查找右子树
    }
    return NULL;
}

二叉排序树的插入

插入新节点时,从根节点开始比较:

  • 若当前节点为空,直接插入
  • 如果新值小于当前节点值,向左子树递归
  • 如果新值大于当前节点值,向右子树递归
  • 找到空位置后插入新节点

时间复杂度:平均O(log2n),最坏O(n)

代码实现:

int BST_Insert(BST_P T, DataType key){
    if(T == NULL){      // 原树为空,插入的值为空节点
        T = (BST_P)malloc(sizeof(BST_Node));
        T->data = key;
        T->lchild = T->rchild = NULL;
        return 1;     // 返回,插入成功
    }
    else if(key == T->data)
        return 0;   // 当前节点的值与要插入的值相同,插入失败
    else if(key < T->data)  // 插入左子树
        return BST_Insert(T->lchild, key);
    else  // 插入右子树
        return BST_Insert(T->rchild, key);
}

二叉排序树的删除

删除是最复杂的操作,需要考虑三种情况:

  • 情况1:删除叶子节点 直接删除,将父节点对应的指针设为空。
  • 情况2:删除只有一个子节点的节点 用该节点的子节点替换该节点。
  • 情况3:删除有两个子节点的节点 找到该节点的中序后继(右子树中的最小值)或中序前驱(左子树中的最大值),用后继/前驱的值替换要删除节点的值,然后删除后继/前驱节点。

代码实现(考的概率很小):

void DeleteBSTNode(BST_P *root, DataType data)
{
    BST_P p = *root, parent = NULL, s = NULL;

    if (!p) return;

    if (p->data == data) //找到要删除的节点了
    {
        /* It's a leaf node */
        if (!p->rchild && !p->lchild) 
            *root = NULL;

        // 只有一个左节点
        else if (!p->rchild&&p->lchild) 
            *root = p->lchild;

        // 只有一个右节点
        else if (!p->lchild&&p->rchild) 
            *root = p->rchild;

        //左右节点都不空
        else 
        {
            s = p->rchild;
            /* the s without left child */
            if (!s->lchild)
                s->lchild = p->lchild;
            /* the s have left child */
            else 
            {
                /* find the smallest node in the left subtree of s */
                while (s->lchild) 
                {
                    /* record the parent node of s */
                    parent = s;
                    s = s->lchild;
                }
                parent->lchild = s->rchild;
                s->lchild = p->lchild;
                s->rchild = p->rchild;
            }
            *root = s;
        }
        free(p);
    }
    else if (data > p->data) //向右找
        DeleteBSTNode(&(p->rchild), data);
    else if (data < p->data) //向左找
        DeleteBSTNode(&(p->lchild), data);
}

复杂度分析

操作平均情况最坏情况
查找O(log n)O(n)
插入O(log n)O(n)
删除O(log n)O(n)

遍历操作

  • 中序遍历:左→根→右,得到有序序列
  • 前序遍历:根→左→右,用于复制树结构
  • 后序遍历:左→右→根,用于删除树

二叉排序树的查找效率

二叉排序树的查找效率主要取决于树的高度,最优情况下,当左右子树高度之差绝对值不超过1时(即平衡二叉树),平均查找长度与O(log2n),最坏情况 ,退化为链表,即当插入的元素有序时,形成一个只有右孩子的单枝数,平均查找长度为(n+1)/2

文字可能略显抽象,不妨看看视频:https://www.bilibili.com/video/BV1uK421x7JJ/

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇