二叉查找树

二叉查找树

引入:因为虽然数据顺序排列的数组二分查找效率非常高,但在插入和删除上的效率是O(n)。为了降低插入和删除的复杂度,可以考虑使用二叉查找树。使用二叉查找树会使插入和删除时的复杂度大大降低,但其查找效率则和树高紧密关联。

对于任意一棵子树,其左子树比根节点小,右子树比根节点大。即:左 < 根 < 右

查找

比较目标值与根节点的大小关系,

  • 大就往右边找;
  • 小就往左边找;
  • 直到找到为止,如果到最后没有找到,则返回 nullptr
Node * BST::searchByIter(Node * bst, DataType target) {
    while (bst != nullptr) {
        //目标值比当前值大,往右走
        if (target > bst->data) {
            bst = bst->right;
        }
        //目标值比当前值小,往左走
        else if (target < bst->data) {
            bst = bst->left;
        }
        //不大不小,刚刚好
        else {
            return bst;
        }
    }
    
    //如果元素在树中,在前面循环执行的过程中就会返回,如果程序走到这里,就说明树中不存在该目标元素,返回空
    return nullptr;
}

获取最值

二叉查找树的特性是“左小右大”,所以找最大值直接向树的最右端找,找最小值直接去树的最左端找。

获取最大值:

DataType BST::getMax(Node * root) {
   	//寻找树最左端的值,即最小值
	while (root->right != nullptr) {
        root = root->right;
    }
    
    return root->data;
}

获取最小值:

DataType BST::getMin(Node * root) {
    while (root->left != nullptr) {
        root = root->left;
    }

    return root->data;
}

插入节点

  • 若节点为空:分配一个节点
  • 非空,比较大小,往对应的方向递归,直至为空;
void BST::insert(Node *& root, DataType target) {
    //为空,分配一个空间
    if (root == nullptr) {
		root = new Node();
        root->data = target;
        root->left = root->right = nullptr;
    }
    //比当前节点值小,向左找节点插入
    else if (target < root->data) {
        root->left = insert(root->left, target);
    }
    //比当前节点值大,向右找节点插入
    else if (target > root->data) {
        root->right = insert(root->right, target);
    }
    //else target存在,什么都不做
    return root;
}

删除节点

  • 节点为空:不可操作
  • 节点存在:
    • 要删除的节点是叶子节点:直接删除
    • 要删除的节点只有一个子节点:用该节点的子节点代替当前节点
    • 要删除的节点有两个子节点:找左子树中最大的节点或者右子树中最小的节点来代替当前要删除的节点
Node * BST::deleteBST(DataType x, Node *& root) {
    TN* tmp = nullptr;
    if (root == nullptr) {
        cout << "Tree is empty!\n";
    }
    //value at right
    else if (x > root->data) {
        root->right = deleteBST(x, root->right);
    }
    // at left
    else if (x < root->data) {
        root->left = deleteBST(x, root->left);
    }
    // x == root->data
    else {
        //two children
        if (root->left != nullptr && root->right != nullptr) {
            tmp = findMin(root->right);
            root->data = tmp->data;
            root->right = deleteBST(root->data, root->right);
        }
        // single child or not exist child
        else {
            tmp = root;
            if (root->left == nullptr) {
                root = root->right;
            }
            else if (root->right == nullptr) {
                root = root->left;
            }

            delete tmp;
            tmp = nullptr;
        }
    }

    return root;
}
posted @ 2025-01-15 23:05  codels  阅读(30)  评论(0)    收藏  举报