二叉搜索树的查询、插入与删除操作(Binary Search Tree, Search, Insert, Delete)(C++)

原创 2015年11月19日 16:09:41

一、概念

    设 x 是二叉搜索树中的一个结点。如果 y 是 x 左子树中的一个结点,那么 y.key ≦ x.key。如果 y 是 x 右子树中的一个结点,那么 y.key ≧ x.key。

    为了便于描述,我们按如下方式定义树结点:

struct TreeNode
{
    int key;
    TreeNode* left;
    TreeNode* right;
    TreeNode* parent;

    TreeNode(int key, TreeNode* left = nullptr, TreeNode* right = nullptr, TreeNode* parent = nullptr)
    : key(key)
    , left(left)
    , right(right)
    , parent(parent)
    {}
};

二、查询二叉搜索树

    二叉搜索树的查询操作包括 Search, Minimum, Maximum, Successor, Predecessor,在任何高度为 h 的二叉搜索树上,所有的查询操作时间复杂度均为 O(h)。

1. 查找

    输入一个指向树根结点的指针与一个关键字 key ,如果此节点存在,则返回一个指向关键字 key 的结点的指针,否则返回 null。递归与迭代版本分别如下:

TreeNode* treeSearch(TreeNode* root, int key)
{
    if(root == nullptr || key == root->key){
        return root;
    }

    if(key < root->key){
        return treeSearch(root->left, key);
    }else{
        return treeSearch(root->right, key);
    }
}

TreeNode* iterativeTreeSearch(TreeNode* root, int key)
{
    while(root && key != root->key){
        if(key < root->key){
            root = root->left;
        }else{
            root = root->right;
        }
    }

    return root;
}

2. 最大关键字与最小关键字

    通过从树根开始沿着 left 孩子指针直到遇到一个 null,我们可以得到最小元素,反之可以得到最大元素。

TreeNode* treeMinimum(TreeNode* root)
{
    while(root->left){
        root = root->left;
    }

    return root;
}

TreeNode* treeMaximum(TreeNode* root)
{
    while(root->right){
        root = root->right;
    }

    return root;
}

3. 后继与前驱

    一个结点 x 的后继是大于 x.key 的最小关键字的结点,前驱概念与之对称。

TreeNode* treeSuccessor(TreeNode* node)
{
    if(node->right){
        return treeMinimum(node->right);
    }

    TreeNode* y = node->parent;

    while(y && node == y->right){
        node = y;
        y = y->parent;
    }

    return y;
}

TreeNode* treePredecessor(TreeNode* node)
{
    if(node->left){
        return treeMaximum(node->left);
    }

    TreeNode* y = node->parent;

    while(y && node == y->left){
        node = y;
        y = y->parent;
    }

    return y;
}

三、插入和删除

1. 插入

    插入新元素后要保证二叉搜索树性质仍然成立,下图展示了元素 13 插入树的整个过程,红色代表从树根开始向下插入到数据项位置的简单路径,虚线表示了为插入数据项而加入的树中的一条链。

 

代码如下:

void treeInsert(TreeNode* root, TreeNode* node)
{
    TreeNode* y = nullptr;
    TreeNode* x = root;

    while(x){
        y = x;

        if(node->key < x->key){
            x = x->left;
        }else{
            x = x->right;
        }
    }

    node->parent = y;

    if(y == nullptr){
        root = node;
    }else if(node->key < y->key){
        y->left = node;
    }else{
        y->right = node;
    }
}

2. 删除

    删除操作较插入操作繁琐,大致分为四种情况,如下图所示:



    (a)结点 z 没有左孩子,用其右孩子 r 来替换 z,其中 r 可以是 NIL,也可以不是;

   (b)结点 z 有一个左孩子 l 但没有右孩子,用 l 来替换 z;

   (c)结点 z 有两个孩子,其左孩子是结点 l,其右孩子 y 还是其后继,y 的右孩子是结点 x,用 y 替换 z,修改使 l 成为 y 的左孩子,但保留 x 仍为 y 的右孩子;

   (d)结点 z 有两个孩子(左孩子 l,右孩子 r),并且 z 的后继 y ≠ r 位于以 r 为根的子树中,用 y 自己的右孩子 x 来代换 y,并且置 y 为 r 的双亲,然后,再置 y 为 q 的孩子和 l 的双亲。

    为了在二叉搜索树内移动子树,定义一个子过程 Transpalnt,它是用一棵子树替换一棵子树并成为其双亲的孩子结点,当 Transplant 用一棵以 v 为根的子树来替换一棵以 u 为根的子树时,结点 u 的双亲就变为 v 的双亲,并且最后 v 成为 u 的双亲的相应孩子。其代码如下:

void transplant(TreeNode* root, TreeNode* oldNode, TreeNode* newNode)
{
    if(oldNode->parent == nullptr){
        root = newNode;
    }else if(oldNode == oldNode->parent->left){
        oldNode->parent->left = newNode;
    }else{
        oldNode->parent->right = newNode;
    }

    if(newNode){
        newNode->parent = oldNode->parent;
    }
}

于是整个删除过程如下所示:

void treeDelete(TreeNode* root, TreeNode* node)
{
    if(node->left == nullptr){
        transplant(root, node, node->right);
    }else if(node->right == nullptr){
        transplant(root, node, node->left);
    }else{
        TreeNode* y = treeMinimum(node->right);

        if(y->parent != node){
            transplant(root, y, y->right);
            y->right = node->right;
            y->right->parent = y;
        }

        transplant(root, node, y);
        y->left = node->left;
        y->left->parent = y;
    }
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

二叉树详解 binary tree && binary search tree

本文参考stanford大学一位计算机教授所写的关于二叉树的文章: http://download.csdn.net/detail/stevemarbo/4097865 二叉树,一个经...

二叉搜索树(Binary Search Tree)的插入与删除

二叉搜索树的插入关键是要找到元素应该插入的位置,可以采用与Find类似的方法。 二叉搜索树的删除则要考虑三种情况:   1.要删除的是叶节点:直接删除,并再修改其父节点指针置为NULL ...

二分查找树的C++实现 Binary Search Tree(BST)

用C++实现了二叉查找树的 创建 插入 删除 遍历(宽度优先和三种深度优先[前序,中序,后序]) 查找某值 查找最大值和最小值 清空 复制二叉树(深复制) #include #include u...

二叉搜索树(Binary Search Tree)的插入与删除

二叉搜索树的插入关键是要找到元素应该插入的位置,可以采用与Find类似的方法。 二叉搜索树的删除则要考虑三种情况:   1.要删除的是叶节点:直接删除,并再修改其父节点指针置为NULL ...

java中使用sort()对ArrayList进行排序

java中的ArrayList需要通过collections类的sort方法来进行排序 如果想自定义排序方式则需要有类来实现Comparator接口并重写compare方法 调用sort方法时将A...

二叉搜索树(Binary Search Tree)的递归和非递归代码实现(C++)

二叉搜索树(Binary Search Tree)的递归和非递归代码实现(C++) 二叉搜索树简单介绍 二叉搜索树(Binary Search Tree)是满足: 左子树的根节点...

从二叉搜索树(Binary Search Tree)入手,学习C++中类的构建 --(二)class与struct, 构造函数,重载函数

一、Class与Struct class是C++的特性,而struct则是沿用自C。通常意义上来说,我们认为struct仅仅是用来存放一些数据的集合,而不包含成员函数。这个理解是简单的,也建议初学cl...

从二叉搜索树(Binary Search Tree)入手,学习C++中类的构建 --(一)BST与基本框架

一、二叉搜索树 二叉搜索树(以下简称BST)是树形数据结构的常见应用之一,其特点是: 1 - 插入单个元素操作 (Insert) 的时间复杂度为 O(lgn) 2 - 构建二叉搜索树的时间复杂度为: ...

PAT - 甲级 - 1099. Build A Binary Search Tree (30)(二叉搜索树+层次遍历+中序遍历)

题目描述: A Binary Search Tree (BST) is recursively defined as a binary tree which has the following ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉搜索树的查询、插入与删除操作(Binary Search Tree, Search, Insert, Delete)(C++)
举报原因:
原因补充:

(最多只允许输入30个字)