树-二叉查找树

二叉查找树 BST

定义

这里给出平衡二叉树的一个实现

二叉查找树是一种特殊的二叉树,又称为二叉排序树、二叉搜索树。
这里给出一些经典的二叉查找树的题目:

递归定义如下:

  • 节点的左子树仅包含键值小于节点键值的节点。
  • 节点的右子树仅包含键大于或等于节点的键的节点。
  • 左和右子树都必须也是二叉搜索树。

这里主要是要对二叉树插入结点和删除结点做出说明:

插入结点

// 插入结点,记得带上取地址符
void insert(node* &root, int v) {
    if(root == NULL) {
        root = new node(v);
        return;
    }else if(v == root->data) {
        return; // 已经存在则不必继续
    }
    else if(v < root->data) {
        // 键值小于当前结点值的放到左边
        insert(root->left, v);
    }else {
        insert(root->right, v);
    }
}

删除结点

两种方法:

  1. 寻找比删除结点 大 的 最小结点(后驱)
  2. 寻找比删除结点 小 的 最大结点

然后将原结点删除,新找到的结点替换原来的位置。

思路:

  1. 如果当前结点为空,说明不存在该结点
  2. 如果当前结点 root 的权值恰好为给定的权值 x,那么说明找到来想要删除的结点
    • 如果当前结点 root 不存在左右孩子,说明是叶子结点,直接删除
    • 如果存在左孩子,则在左子树中寻找结点前驱 pre,然后让 pre 的数据覆盖root,接着在左子树中删除结点 pre
    • 如果存在右孩子,则在右子树中寻找结点前驱 next,然后让 next 的数据覆盖root,接着在右子树中删除结点 next
  3. 如果当前结点 root 的权值大于给定的权值,则在左子树中递归删除 x
  4. 如果当前结点 root 的权值小于给定的权值,则在右子树中递归删除 x
// 寻找最大的结点
node* findMax(node* root) {
    while(root->right != NULL) {
        root = root->right;
    }
    return root;
}

node* findMin(node* root) {
    while (root->left != NULL)
    {
        root = root->left;
    }
    return root;
}

void deleteNode(node* &root, int x) {
    if(root == NULL) return;
    if(root->data == x) {
        if(root->left == NULL && root->right == NULL) {
            root = NULL;    // 叶子结点直接删除
        }// 左子树和右子树只需要选择一种
        else if(root->left != NULL) {
            // 左子树不为空,则去左子树中寻找最大的值
            node* pre = findMax(root->left);
            root->data = pre->data;
            deleteNode(root->left, pre->data);  // 直接调用本身来进行删除
        }else if(root->right != NULL) {
            // 右子树不为空
            node* next = findMin(root->right);
            root->data = next->data;
            deleteNode(root->right, next->data);
        }
    }else if(x < root->data) {
        deleteNode(root->left, x);
    }else {
        deleteNode(root->right, x);
    }
}

查找结点

由于二叉查找树是有序的二叉树,所以可以在 logN 的时间内查找某个结点。

void search(node* root, int key) {
    if(root == NULL) {
        printf("查找失败\n");
        return;
    }
    if(root->data == key) {
        printf("find: %d\n", root->data);
    }else if(key < root->data) {
        // 比该结点小,则去左子树寻找
        search(root->left, key);
    }else {
        // 大于等于该结点,去右子树寻找
        search(root->right, key);
    }
}
发布了19 篇原创文章 · 获赞 6 · 访问量 770

猜你喜欢

转载自blog.csdn.net/weixin_41012699/article/details/105044429
今日推荐