二叉树搜索树基本操作——详解

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

算法实现分为递归和非递归:

1.插入节点

2.寻找节点

3.删除节点


//创建结构
#pragma once
#include<stdio.h>
#include<Windows.h>
#include<assert.h>

typedef int DataType;

typedef struct BSTreeNode
{
    struct BSTreeNode* _left;
    struct BSTreeNode* _right;
    DataType _data;
}BSTreeNode;


// 非递归 
BSTreeNode* BuyBSTreeNode(DataType x)
{
    BSTreeNode* newnode = (BSTreeNode*)malloc(sizeof(BSTreeNode));
    assert(newnode);
    newnode->_data = x;
    newnode->_left = NULL;
    newnode ->_right = NULL;
    return newnode;
}





//向二叉搜索树中插入一个节点
int BSTreeInsert(BSTreeNode** tree, DataType x)
{
    //如果该树为空树,则直接把该节点作为根节点
    //如果该树不是空树,则寻找该节点的位置,如果发现该节点已经存在于树中,则插入失败,返回0,插入成功返回1

   //遍历各个节点找到x所插入节点cur,并定义一个parent找到cur的父母
   //根据cur和parent的大小判断cur链左还是右

    assert(tree);
    BSTreeNode *cur = *tree;
    BSTreeNode *parent = *tree;
    if (*tree == NULL)
    {
        *tree = BuyBSTreeNode(x);
        return 1;
    }
    else
    {
        while (cur)
        {
            if (cur->_data > x)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (cur->_data < x)
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                printf("该二叉搜索树中已经存在该值的节点\n");
                return 0;
            }

        }
        //运行到此处说明已经找到了要插入的位置及他的父亲节点
        cur = BuyBSTreeNode(x);
        if (parent->_data > x)//需要确定cur是链在parent左还是parent右
        {
            parent->_left = cur;
        }
        else
        {
            parent->_right = cur;
        }
        return 1;
    }
}




const BSTreeNode* BSTreeFind(BSTreeNode* tree, DataType x)
{
    assert(tree);
    const BSTreeNode* cur = tree;
    if (tree == NULL)
    {
        return NULL;
    }
    else
    {
        while (cur != NULL)
        {
            if (x < cur->_data)
            {
                cur = cur->_left;
            }
            else if (x > cur->_data)
            {
                cur = cur->_right;
            }
            else
            {
                return cur;
            }
        }
    }
    return NULL;
}





int BSTreeRemove(BSTreeNode** tree, DataType x)
{
    assert(*tree);
    BSTreeNode* cur = *tree;
    BSTreeNode*parent = NULL;       //存在只有一个节点情况
    if (*tree == NULL)
    {
        return -1;
    }
    else
    {
        while (cur != NULL)
        {
            if ( x < cur->_data)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (x > cur->_data)
            {
                parent = cur;
                cur = cur->_right;
            }

             // 这时已找到删除节点cur
            //删除位置:  1.叶子节点  2.无左孩子或右孩子  3.左右都有孩子
            else if(cur->_data==x)  //此时找到要删除节点
            {
                if (cur->_left == NULL)     //左为空
                {
                    if (parent == NULL)// 一个节点的情况
                    {
                        *tree = (*tree)->_right;
                        return 1;
                    }

                    if (parent->_left == cur)//cur时parent的左
                    {
                        parent->_left = cur->_right;
                        return 1;
                    }

                    if (parent->_right == cur)//cur时parent的右
                    {
                        parent->_right = cur->_right;
                        return 1;
                    }
                }

                if (cur->_right == NULL)        //右为空,和上面情况相同
                {
                    if (parent == NULL)
                    {
                        *tree = (*tree)->_left;
                        return 1;
                    }

                    if (parent->_left == cur)
                    {
                        parent->_left = cur->_left;
                        return 1;
                    }

                    if (parent->_right == cur)
                    {
                        parent->_right = cur->_left;
                        return 1;
                    }
                }

                    else  //删除节点有左右孩子 
                    //思路: 
                        //首先我们需要找到待删除节点cur的左子树上的最大值节点,或右子树的最小节点SubLeft
                        //交换cur和SubLeft的值   然后处理特殊情况,见下图    

                    {
                        BSTreeNode* SubLeft = cur->_left;
                        BSTreeNode*parent = cur;
                        while (SubLeft->_right)     //找到最左节点和和他的父亲
                        {
                            parent = SubLeft;
                            SubLeft = SubLeft->_right;
                        }

                        cur->_data = SubLeft->_data;

                        if (parent->_left == SubLeft)
                        {
                            parent->_left = SubLeft->_right;
                            free(SubLeft);
                            return 1;
                        }
                        else
                        {
                            free(SubLeft);
                            parent->_right = SubLeft->_right;
                            return 1;
                        }
                    }   
                }
            }
        }
        return -1;
}

这里写图片描述


递归版:

int BSTreeInsertR(BSTreeNode** tree, DataType x)
{
    if (*tree == NULL)
    {
        *tree = BuyBSTreeNode(x);
        return 1;
    }
    if ((*tree)->_data < x)
    {
        return BSTreeInsertR(&(*tree)->_right, x);
    }

    if ((*tree)->_data > x)
    {
        return BSTreeInsertR(&(*tree)->_left, x);
    }
    else
    {
        return -1;
    }
}




const BSTreeNode* BSTreeFindR(BSTreeNode* tree, DataType x)
{
    if (tree == NULL)
    {
        return NULL;
    }

    if (x < tree->_data)
    {
        return  BSTreeFindR(tree->_left, x);
    }
    if (x > tree->_data)
    {
        return   BSTreeFindR(tree->_right, x);
    }
    else if (x == tree->_data)
    {
        return tree;
    }
    return NULL;
}




int BSTreeRemoveR(BSTreeNode** tree, DataType x)
{
    if (*tree == NULL)      //此时树为空或找到根的NULL
    {
        return -1;
    }

    if (x < (*tree)->_data)
    {
        return BSTreeRemoveR(&(*tree)->_left, x);
    }

    if (x > (*tree)->_data)
    {
        return BSTreeRemoveR(&(*tree)->_right, x);
    }

    else          //已找到删除节点
    {
        if ((*tree)->_left == NULL)
        {
            *tree = (*tree)->_right;
        }

        else if ((*tree)->_right == NULL)
        {
            *tree = (*tree)->_left;
        }

        else
        {
            BSTreeNode *subright = (*tree)->_left;
            while (subright->_right)
            {
                subright = subright->_right;
            }
            (*tree)->_data = subright->_data;
            return BSTreeRemoveR(&(*tree)->_left, subright->_data);
        }
    }

    return 1;

}

完整代码:
BST.h :

#pragma once
#include<stdio.h>
#include<Windows.h>
#include<assert.h>

typedef int DataType;

typedef struct BSTreeNode
{
    struct BSTreeNode* _left;
    struct BSTreeNode* _right;
    DataType _data;
}BSTreeNode;




int BSTreeInsert(BSTreeNode** tree, DataType x);
const BSTreeNode* BSTreeFind(BSTreeNode* tree, DataType x);
int BSTreeRemove(BSTreeNode** tree, DataType x);
void BSTreeDestory(BSTreeNode* tree);

// 非递归 
BSTreeNode* BuyBSTreeNode(DataType x)
{
    BSTreeNode* newnode = (BSTreeNode*)malloc(sizeof(BSTreeNode));
    assert(newnode);
    newnode->_data = x;
    newnode->_left = NULL;
    newnode ->_right = NULL;
    return newnode;
}





//向二叉搜索树中插入一个节点
int BSTreeInsert(BSTreeNode** tree, DataType x)
{
    //如果该树为空树,则直接把该节点作为根节点
    //如果该树不是空树,则寻找该节点的位置,如果发现该节点已经存在于树中,则插入失败,返回0
    //插入成功返回1

    assert(tree);
    BSTreeNode *cur = *tree;
    BSTreeNode *parent = *tree;
    if (*tree == NULL)
    {
        *tree = BuyBSTreeNode(x);
        return 1;
    }
    else
    {
        while (cur)
        {
            if (cur->_data > x)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (cur->_data < x)
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                return 0;
            }

        }
        //运行到此处说明已经找到了要插入的位置及他的父亲节点
        cur = BuyBSTreeNode(x);
        if (parent->_data > x)//需要确定cur是链在parent左还是parent右
        {
            parent->_left = cur;
        }
        else
        {
            parent->_right = cur;
        }
        return 1;
    }
}







const BSTreeNode* BSTreeFind(BSTreeNode* tree, DataType x)
{
    assert(tree);
    const BSTreeNode* cur = tree;
    if (tree == NULL)
    {
        return NULL;
    }
    else
    {
        while (cur != NULL)
        {
            if (x < cur->_data)
            {
                cur = cur->_left;
            }
            else if (x > cur->_data)
            {
                cur = cur->_right;
            }
            else
            {
                return cur;
            }
        }
    }
    return NULL;
}


int BSTreeRemove(BSTreeNode** tree, DataType x)
{
    assert(*tree);
    BSTreeNode* cur = *tree;
    BSTreeNode*parent = NULL;       //存在只有一个节点情况
    if (*tree == NULL)
    {
        return -1;
    }
    else
    {
        while (cur != NULL)
        {
            if ( x < cur->_data)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (x > cur->_data)
            {
                parent = cur;
                cur = cur->_right;
            }


            //删除位置:  1.叶子节点  2.无左孩子或右孩子  3.左右都有孩子
            else if(cur->_data==x)  //此时找到要删除节点
            {
                if (cur->_left == NULL)     //左为空
                {
                    if (parent == NULL)
                    {
                        *tree = (*tree)->_right;
                        return 1;
                    }

                    if (parent->_left == cur)
                    {
                        parent->_left = cur->_right;
                        return 1;
                    }

                    if (parent->_right == cur)
                    {
                        parent->_right = cur->_right;
                        return 1;
                    }
                }

                if (cur->_right == NULL)        //右为空
                {
                    if (parent == NULL)
                    {
                        *tree = (*tree)->_left;
                        return 1;
                    }

                    if (parent->_left == cur)
                    {
                        parent->_left = cur->_left;
                        return 1;
                    }

                    if (parent->_right == cur)
                    {
                        parent->_right = cur->_left;
                        return 1;
                    }
                }

                    else  //删除节点右左右孩子  
                        //首先我们需要找到待删除节点的左子树上的最大值节点,
                        //或者右子树上的最小值节点,然后将该节点的参数值与待删除的节点参数值进行交换,
                        //最后删除该节点,
                    {
                        BSTreeNode* SubLeft = cur->_left;
                        BSTreeNode*parent = cur;
                        while (SubLeft->_right)     //找到最左子树最大节点和他的父亲
                        {
                            parent = SubLeft;
                            SubLeft = SubLeft->_right;
                        }

                        cur->_data = SubLeft->_data;

                        if (parent->_left == SubLeft)
                        {
                            parent->_left = SubLeft->_right;
                            free(SubLeft);
                            return 1;
                        }
                        else
                        {
                            parent->_right = SubLeft->_left;
                            free(SubLeft);
                            return 1;
                        }
                    }       
                }
            }
        }
        return -1;
}


//////////////////////////////////
//递归
//向二叉搜索树中插入一个节点
int BSTreeInsertR(BSTreeNode** tree, DataType x)
{
    if (*tree == NULL)
    {
        *tree = BuyBSTreeNode(x);
        return 1;
    }
    if ((*tree)->_data < x)
    {
        return BSTreeInsertR(&(*tree)->_right, x);
    }

    if ((*tree)->_data > x)
    {
        return BSTreeInsertR(&(*tree)->_left, x);
    }
    else
    {
        return -1;
    }
}


const BSTreeNode* BSTreeFindR(BSTreeNode* tree, DataType x)
{
    if (tree == NULL)
    {
        return NULL;
    }

    if (x < tree->_data)
    {
        return  BSTreeFindR(tree->_left, x);
    }
    if (x > tree->_data)
    {
        return   BSTreeFindR(tree->_right, x);
    }
    else if (x == tree->_data)
    {
        return tree;
    }
    return NULL;
}



int BSTreeRemoveR(BSTreeNode** tree, DataType x)
{
    if (*tree == NULL)      //此时树为空或找到根的NULL
    {
        return -1;
    }

    if (x < (*tree)->_data)
    {
        return BSTreeRemoveR(&(*tree)->_left, x);
    }

    if (x > (*tree)->_data)
    {
        return BSTreeRemoveR(&(*tree)->_right, x);
    }

    else          //已找到删除节点
    {
        if ((*tree)->_left == NULL)
        {
            *tree = (*tree)->_right;
        }

        else if ((*tree)->_right == NULL)
        {
            *tree = (*tree)->_left;
        }

        else
        {
            BSTreeNode *subright = (*tree)->_left;
            while (subright->_right)
            {
                subright = subright->_right;
            }
            (*tree)->_data = subright->_data;
            return BSTreeRemoveR(&(*tree)->_left, subright->_data);
        }
    }
    return 1;
}



void test()
{
    BSTreeNode* BST;
    BST = NULL;
    BSTreeInsertR(&BST, 5);
    BSTreeInsertR(&BST, 3);
    BSTreeInsertR(&BST, 7);
    BSTreeInsertR(&BST, 1);
    BSTreeInsertR(&BST, 4);
    BSTreeInsertR(&BST, 6);
    BSTreeInsertR(&BST, 8);
    BSTreeInsertR(&BST, 0);
    BSTreeInsertR(&BST, 2);
    BSTreeInsertR(&BST, 9);
    const BSTreeNode* ret = BSTreeFindR(BST, 1);
    BSTreeRemove(&BST, 3);






}

猜你喜欢

转载自blog.csdn.net/yc1515707718/article/details/80300873