数据结构学习笔记吧(11)---基于树的查找

(1)二叉排序树定义:

该二叉树或者是一棵空树或者是一棵具有下列性质的树:
1. 若他的左子树非空,则左子树上所有节点的值均小于根节点的值
2. 若他的右子树非空,则右子树上所有节点的值均大于(等于)根节点的值
3. 他的左子树与与右子树也分别是二叉排序树

二叉排序树的插入

思路:
1. 首先判断二叉树是否为空,若为空则可以直接把当做根节点
2. 若非空,则key与根节点进行比较
a. 如果Key等于节点的值 则停止插入
b. 如果Key大于节点的值 则插入根节点右边
c. 如果Key小于节点的值 则插入根节点左边
代码实现:

void insertBST(PBSTNode *root,int key)
{

    if (*root == NULL)
    {
        PBSTNode pNew = new BSTNode;
        pNew->key = key;
        pNew->lchild = pNew->rchild = NULL;
        *root = pNew;
        return;
    }
    else
    {
        if (key > (*root)->key)
        {
            insertBST(&(*root)->rchild, key);
        }
        else 
        {
            insertBST(&(*root)->lchild, key);
        }
    }
}  
二叉排序树的创建
void CreatBST(PBSTNode * root)
{
    int key;
    cin >> key;
    while (-1 != key)
    {
        insertBST(root, key);
        cin >> key;
    }
}
二叉排序树的查找

思路:
1. 首先判断二叉树是否为空,若为空则不可查找
2. 若非空,则key与根节点进行比较
a. 如果Key等于节点的值 则查找成功
b. 如果Key大于节点的值 则根节点右边查找
c. 如果Key小于节点的值 则根节点左边查找

PBSTNode  BSTSearch(PBSTNode root,int key)
{
    if (NULL == root)
    {
        cout << "该查找树为空!" << endl;
        return NULL;
    }
    if (root->key == key)
    {
        return root;
    }
    else if (root ->key < key)
    {
        return BSTSearch(root->rchild, key);
    }
    else
    {
        return BSTSearch(root->lchild, key);
    }
}
二叉排序树的删除

在二叉排序树删去一个结点,分三种情况讨论:
1. 若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则可以直接删除此子结点。
2. 若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。
3. 若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:
A:其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树
B:其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)-即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。
代码如下:

PBSTNode delBST(PBSTNode root, int key)
{
    PBSTNode p,fa,s,q;
    fa = NULL;
    p = root;
    while (p)
    {
        if (p->key == key)
        {
            break;
        }
        else if (p->key > key)
        {
            fa = p;
            p = p->lchild;
        }
        else
        {
            fa= p;
            p = p->rchild;
        }
    }
    if (p ==  NULL)
    {
        cout << "没有查到该值!" << endl;
        return root;
    }
    if (p->lchild == NULL)
    {
        if (fa == NULL)
        {
            root = p->rchild;
        }
        else if (fa->lchild == p)
        {
            fa->lchild = p->rchild;
        }
        else
        {
            fa->rchild = p->rchild;
        }
        delete p;
    }
    else
    {
        s = p->lchild;
        q = p;
        while (s)
        {
            p = s;
            s = p->rchild;
        }
        if (p == q)
        {
            q->lchild = s->lchild;
        }
        else
        {
            q->rchild = s->lchild;
        }
        p->key = s->key;
        delete s;
    }
    return root;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值