数据结构之二叉查找树

1、基本概念

  二叉查找树,在二叉树的基础上加了以下限制条件:对于树中的任意节点,其键值大于左子树中的任意节点的键值,小于右子树中的任意节点的键值。根据此结构,我们可以得到对数级的查找和插入效率。同时,从根节点一直向左查找可得到最小值,一直向右查找就可得到最大值。

2、查找操作

  二叉查找树在查找元素时,相比于二叉树的查找需要同时查找左右子树,二叉查找树根据键值比较只只用查找其中一个子树,代码如下:

bool BSTree::contains(int key, BTreeNode* node)
{
    if (node == NULL)
    {
        return false;
    }

    if (key == node->data)
    {
        return true;
    }

    if (key < node->data)
    {
        return contains(key, node->leftChild);
    } 
    else
    {
        return contains(key, node->rightChild);
    }
}

3、插入操作

  二叉查找树在插入节点时,根据定义限制,我们需要不断进行键值比较从而找到最终的插入位置,代码如下:

void BSTree::insert(int key, BTreeNode* node)
{
    if (node == NULL)
    {
        node = new BTreeNode(key);
    } 

    if (key < node->data)
    {
        insert(key, node->leftChild);
    } 
    else if (key > node->data)
    {
        insert(key,node->rightChild);
    }
    else
    {
        //对于相等的情况可选择性处理
    }
}

  这里需要说明的是,根据二叉查找树的定义,是不允许有相同键值的节点的,若要满足这种需求,需要自行处理键值相同的情况。

4、删除操作

  删除的前两种的操作跟二叉树是一致的,但是对于第三种情况,由于要保证删除后的树还是二叉查找树,因此需要查找右子树中键值最小的节点或者左子树中键值最大的节点作为替换节点,代码如下:

void BSTree::remove(int key, BTreeNode* &node)
{
    if (node == NULL)
    {
        return;
    }

    if (key == node->data)
    {
        if (node->leftChild != NULL && node->rightChild != NULL)
        {
            //替换键值
            BTreeNode * temp = findMin(node->rightChild);
            node->data = temp->data;
            //递归删除
            remove(temp->data,node->rightChild);
        } 
        else
        {
            BTreeNode * temp = node;
            node = (node->leftChild != NULL)?node->leftChild:node->rightChild;
            delete temp;
        }
    }
    else if (key < node->data)
    {
        remove(key,node->leftChild);
    }
    else
    {
        remove(key,node->rightChild);
    }
}

5、清除操作

  二叉查找树的清除操作与二叉树的清除操作并没有特殊需要处理的,我们直接复用二叉树的清除操作即可。

6、综合结果

  这里我们对之前的算法进行简单的测试,结果如下:

BSTree* bsTree = new BSTree();
bsTree->insert(5);
bsTree->insert(7);
bsTree->insert(3);
bsTree->insert(1);
bsTree->insert(9);
bsTree->insert(8);
bsTree->insert(2);
bsTree->insert(4);
bsTree->insert(6);

cout<<"contains 5:"<<bsTree->contains(5)<<endl; //contains 5:1
cout<<"contains 10:"<<bsTree->contains(10)<<endl; //contains 10:0

bsTree->breadthFirstTravel();  //bft:5 3 7 1 4 6 9 2 8
bsTree->depthFirstTravel_DLR(); //depthFirstTravel_DLR:5 3 1 2 4 7 6 9 8
bsTree->depthFirstTravel_LDR(); //depthFirstTravel_LDR:1 2 3 4 5 6 7 8 9
bsTree->depthFirstTravel_LRD(); //depthFirstTravel_LRD:2 1 4 3 6 8 9 7 5

bsTree->remove(7);
bsTree->breadthFirstTravel();  //bft:5 3 8 1 4 6 9 2
bsTree->depthFirstTravel_DLR(); //depthFirstTravel_DLR:5 3 1 2 4 8 6 9
bsTree->depthFirstTravel_LDR(); //depthFirstTravel_LDR:1 2 3 4 5 6 8 9
bsTree->depthFirstTravel_LRD(); //depthFirstTravel_LRD:2 1 4 3 6 9 8 5

bsTree->clear();
bsTree->breadthFirstTravel();  //bft:

7、效率分析

  相比于二叉树,二叉查询树通过键值的比较,可以很好地剔除掉节点的其中一个子树,因而基本操作的算法复杂度为O(logn)。但是,如果二叉树不平衡,形成链表式的结构,就会达到最差的算法复杂度O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值