【数据结构】搜索二叉树

手写实现搜索二叉树:


  • 树的节点定义:
class TreeNode
{
public:
    TreeNode(int v) :value(v){};

    TreeNode* left_son = NULL;
    TreeNode* right_son = NULL;
    TreeNode* p = NULL;         //一定保存双亲的指针
    int value = 0;
};

  • 节点插入:
bool TreeInsert(TreeNode*& pRoot,int value)
{
    TreeNode* pNew = new TreeNode(value);//待插入的节点
    TreeNode* pParent = NULL;//父节点
    TreeNode* pCur = pRoot;//子节点
    while (pCur != NULL)
    {
        pParent = pCur;
        if (pCur->value < value)
        {
            pCur = pCur->right_son;
        }
        else if (pCur->value>value)
        {
            pCur = pCur->left_son;
        }
        else
        {
            return false;
        }
    }
    if (pParent == NULL)//空树
    {
        pRoot = pNew;
    }
    else if ( pParent->value<value )//插右边
    {
        pParent->right_son = pNew;
        pNew->p = pParent;
    }
    else//插左边
    {
        pParent->left_son = pNew;
        pNew->p = pParent;
    }
    return true;
}

  • 最大值,最小值函数
TreeNode* TreeMax(TreeNode* pRoot)
{
    while (pRoot!=NULL&&pRoot->right_son!=NULL)
    {
        pRoot = pRoot->right_son;
    }
    return pRoot;
}

TreeNode* TreeMin(TreeNode* pRoot)
{
    while (pRoot!=NULL&&pRoot->left_son!=NULL)
    {
        pRoot = pRoot->left_son;
    }
    return pRoot;
}

  • 前驱、后继函数
TreeNode* Successor(TreeNode* pRoot)
{
    /*
    寻找节点的后继节点
    方法一:中序遍历,后继即 该节点输出的后一个节点
    方法二:若当前节点有右孩子,则后继为右孩子子树的最小节点
            若当前节点无右孩子,则后继为其最底层的祖先,条件是该结点位于此祖先的左子树
    */
    if (pRoot==NULL)
    {
        return pRoot;
    }
    if (pRoot->right_son != NULL)// 当前节点有右孩子
    {
        return TreeMin(pRoot->right_son);
    }

    TreeNode* pChild = pRoot;
    TreeNode* pParent = pChild->p;

    while (pParent != NULL&&pParent->right_son == pChild)//当前节点无右孩子,寻找满足要求的最底层祖先
    {
        pChild = pParent;
        pParent = pParent->p;
    }
    return pParent;
}

TreeNode* Processor(TreeNode* pRoot)
{
    /*
    寻找节点的前驱节点
    若当前节点有左孩子,则前驱为左孩子子树的最大节点
    若当前节点无左孩子,则后继为其最底层的祖先,条件是该结点位于此祖先的右子树
    */
    if (pRoot == NULL)
    {
        return pRoot;
    }
    if (pRoot->left_son != NULL)//有左孩子
    {
        return TreeMax(pRoot->left_son);
    }

    TreeNode* pChild = pRoot;
    TreeNode* pParent = pChild->p;

    while (pParent != NULL&&pParent->left_son == pChild)//无左孩子,寻找满足要求的最底层祖先
    {
        pChild = pParent;
        pParent = pParent->p;
    }
    return pParent;
}

  • 替换函数,使用一棵树接管另一棵树的双亲
bool TransPlant(TreeNode *& pRoot, TreeNode* pOld, TreeNode* pNew)
{
    /*
    使用一棵树接管另一棵树的双亲
    */
    if (pRoot == NULL||pOld == NULL)//旧子树为空
    {
        return false;
    }

    //调整父节点的指针
    if (pOld->p == NULL)//父节点为空:替换了根节点
    {
        pRoot = pNew;
    }
    else
    {
        if (pOld == pOld->p->left_son)
        {
            pOld->p->left_son = pNew;
        }
        else
        {
            pOld->p->right_son = pNew;
        }
    }
    //调整指向父节点的指针
    if (pNew != NULL)//新子树不为空
    {
        pNew->p = pOld->p;
    }
    return true;
}
  • 删除节点
void TreeDelete(TreeNode*& pRoot, TreeNode* pDelete)
{
    /*
    删除指定节点
    */
    if (pRoot == NULL || pDelete == NULL)
        return;

    if (pDelete->left_son == NULL)//没有孩子或者只有一个孩子,直接将孩子提上来
    {
        TransPlant(pRoot,pDelete, pDelete->right_son);
    }
    else if (pDelete->right_son == NULL)
    {
        TransPlant(pRoot,pDelete, pDelete->left_son);
    }
    else//同时有两个孩子时
    {
        TreeNode* successor = TreeMin(pDelete->right_son);//寻找后继,后继一定没有左孩子节点

        if (successor->p != pDelete)//后继不是被删除节点的右孩子节点
        {
            TransPlant(pRoot,successor, successor->right_son);//删除后继节点
            successor->right_son = pDelete->right_son;//将后继提到被删除节点右孩子位置上:接管被删除节点的右孩子
            successor->right_son->p = successor;
        }

        TransPlant(pRoot,pDelete, successor);//后继接管被删节点的双亲
        successor->left_son = pDelete->left_son;//后继接管被删节点的左孩子
        successor->left_son->p = successor;
    }
}

  • 中序打印函数
  • 测试主函数
void TreePrint(TreeNode* pRoot)
{
    if (pRoot == NULL)
    {
        return;
    }
    TreePrint(pRoot->left_son);
    cout << pRoot->value << " ";
    TreePrint(pRoot->right_son);
}

int main()
{
    TreeNode* pRoot(NULL);
    TreeInsert(pRoot, 4);
    TreeInsert(pRoot, 1);
    TreeInsert(pRoot, 9);
    TreeInsert(pRoot, 2);
    TreeInsert(pRoot, 8);
    TreeInsert(pRoot, 3);
    TreeInsert(pRoot, 6);

    TreePrint(pRoot);
    cout << endl;
    TreeDelete(pRoot,pRoot);
    TreePrint(pRoot);

    return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值