二叉排序树

二叉排序树

二叉排序树(BST)又称“二叉查找树”、“二叉搜索树”。

二叉排序树的性质

  1. 是一颗空树
  2. 具有下列性质的二叉树
    • 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值
    • 若它的有字数不空,则右子树上所有节点的值均大于它的根节点的值
    • 它的左、右子树也分别为二叉排序树

二叉排序树的实现

// 二叉排序树使用二叉链表作为存储结构
typedef struct BNode {
        int value;
        struct BNode *left;
        struct BNode *right;
} BNode, *PBTree, *PBNode;

// 定义根二叉树节点指针
PBTree root = NULL;

// 创建指定value的二叉排序树的节点
PBNode _makeBNode(int value) 
{
        PBNode pBNode = (PBTree)malloc(sizeof(BNode));
        pBNode->value = value;
        pBNode->left = NULL;
        pBNode->right = NULL;
        return pBNode;
}

二叉排序树的删除

void _insertHelper(PBTree *root, int value) 
{

        PBTree pBTree = *root;
        BNode *pBNode = _makeBNode(value);
        if (pBTree == NULL) {
                *root = pBNode;
        } else {
                if (pBTree->value < value) {
                        _insertHelper(&(pBTree->right), value);
                } else if (pBTree->value > value) {
                        _insertHelper(&(pBTree->left), value);
                } else {
                        puts("element is exist!!");
                        return;
                }
        }
}
// 使用insert方式创建二叉排序树
void InsertToBinarySearchTree(int value)
{
        _insertHelper(&root, value);
}

二叉排序树的中序遍历

// 中序遍历二叉排序树
void Traversal(PBTree root)
{
        if (root == NULL)
                return;

        if (root->left) {
                Traversal(root->left);
        }
        printf(" %d", root->value);
        if (root->right) {
                Traversal(root->right);
        }
}

二叉排序树节点的查找

PBNode _findHelper(PBTree root, int value)
{
        if (root) {
                if (root->value < value) {
                        return _findHelper(root->right, value);
                } else if (root->value > value) {
                        return _findHelper(root->left, value);
                } else {
                        return root;
                }
        }
        return NULL;
}
// 二叉排序树中查找 value,成功返回其指针失败返回NULL
PBNode FindBNode(int value)
{
        return _findHelper(root, value);
}

// 二叉排序树中序遍历时的某值的后继节点
PBNode TreeSuccessor(int value)
{
        PBNode pBNode = NULL;
        pBNode = FindBNode(value);
        pBNode = TreeMinimum(pBNode->right);
        return pBNode;
}

二叉排序树节点的删除

删除指定节点

删除节点时要注意三种情况:

  1. 叶节点
    这里写图片描述
  2. 仅有左子树或右子树的节点
    这里写图片描述
  3. 左右子树都有的节点
    这里写图片描述
bool _delNodeHelper(PBNode* ppNode) 
{
    PBNode q = NULL, s = NULL;
    // 1. 叶节点
    if ((*ppNode)->left == NULL
    && (*ppNode)->right == NULL) {
        free((*ppNode));
        *ppNode = NULL;

    // 2. 仅有左子树或右子树
    // 2.1 仅有右子树
    } else if ((*ppNode)->left == NULL) {
        q = *ppNode;
        *ppNode = (*ppNode)->right;
        free((q);
    // 2.2 仅有左子树
    } else if ((*ppNode)->right == NULL) {
        q = *ppNode;
        *ppNode = (*ppNode)->left;
        free(q);

    // 3. 左右子树均不为空
    } else {
        q = (*ppNode);
        s = (*ppNode)->left;
        while (s->right) { // 左转,向右走到尽头
            q = s;
            s = s->right;
        }

        (*ppNode)->value = s->value;
        if (q != *ppNode)         // 是否执行while循环
            q->right = s->left;// 执行,重接右子树
        else 
            q->left = s->left;// 未执行,重接左子树
        free(s);
    }
    return true;
}
bool DeleteBTreeNode(PBTree root, int value) 
{
    if (root == NULL) 
        return false;

    if (root->value > value) {
        return DeleteBTreeNode(root->left, value);
    } else if (root->value < value) {
        return DeleteBTreeNode(root->right, value);
    }

    return _delNodeHelper(&root);
}
删除所有节点
void _deleteHelper(PBTree *root)
{
        PBNode pBNode = *root;
        if (pBNode) {
                if (pBNode->left) {
                        _deleteHelper(&(pBNode->left));
                        printf("%p\n", pBNode->left);
                }
                if (pBNode->right) {
                        _deleteHelper(&(pBNode->right));
                        printf("%p\n", pBNode->left);
                }
                if (pBNode->left == NULleft||
                        pBNode->right == NULL) {
                        free(pBNode);
                        *root = NULL;
                }
        }
}
// 删除二叉排序树
void DeleteBTree()
{
        _deleteHelper(&root);
}

二叉排序树的最大值和最小值

// 二叉排序树的最小值
PBNode TreeMinimum(PBTree root) 
{
        PBNode pBNode= root; 
        if (!pBNode) 
                return NULL;


        while (pBNode->left) {
                pBNode = pBNode->left;
        }
        return pBNode;
}
// 二叉排序树的最大值
PBNode TreeMaximum(PBTree root)
{
        PBNode pBNode = root;
        if (!pBNode) 
                return NULL;

        while (pBNode->right) {
                pBNode = pBNode->right;
        }
        return pBNode;
}

二叉排序树的高度

// 二叉排序树的高度
int Height(PBTree root, int h)
{
        if (!root) {
                return h;
        }

        h++;
        int h1 = Height(root->left, h); 
        int h2 = Height(root->right, h); 

        return h1 > h2 ? h1 : h2; 
}

// 常用版本
int Height2(PBTree root)
{
    if (!root)
        return 0;

    int hLeft = Height2(root->left);
    int hRight = Height2(root->right);

    return hLeft > hRight ? hLeft:hRight + 1;
}

二叉排序树的测试

// 测试二叉排序树
int main()
{
        // 创建二叉排序树
        int a[] = {8, 2, 10, 3, 7, 1, 6};
        size_t count = sizeof(a)/sizeof(a[0]);
        for (size_t i = 0; i < count; i++) {
                InsertToBinarySearchTree(a[i]);
        }

        // 二叉排序树的高度
        printf("The height of BTree is %d\n", Height(root, 0));

        // 遍历二叉排序树
        Traversal(root);
        puts("");

        // 二叉排序树的最小值
        PBNode p = TreeMinimum(root);
        printf("Min node is %p, value is %d\n", p, p->value);
        // 二叉排序树的最大值
        p = TreeMaximum(root);
        printf("Max node is %p, value is %d\n", p, p->value);
        // 二叉排序树中某值的后继节点(或值)
        p = TreeSuccessor(3);
        printf("3's successor is %d\n", p->value);

        // 查找指定value
        PBNode pBNode = FindBNode(7);
        printf("Node %d's adress is %p\n", 7, pBNode);
        // 删除二叉排序树
        DeleteBTree();
        Traversal(root);
}

二叉排序树性能

  • 最好情况是二叉排序树的形态和这般查找的判定树相同,其平均查找长度和logN成正比(Olog2(N))。

  • 最坏情况是插入的关键字有序,构成的二叉排序树为一颗斜树,树的深度为N,其平均查找长度为(N+1)/2;时间复杂度也为O(N),和顺序查找一样。

参考

二叉排序树(查询、插入、删除)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值