二叉搜索树的插入、查找、删除的非递归实现

二叉搜索树的非递归实现

之前写过递归版本的,这里的实现思想是相同的,具体见 二叉搜索树相关操作的递归实现,这里只写几个非递归实现的函数
1. 给定一个值,将该元素插入二叉搜索树
 
 
SearchNode* CreateSearchNode(SearchNodeType value)//创建一个结点
{
    SearchNode* new_node = (SearchNode*)malloc(sizeof(SearchNode));
    new_node->data = value;
    new_node->lchild = NULL;                                                                                                                                            
    new_node->rchild = NULL;
    return new_node;
}

void SearchTreeInsert(SearchNode** proot, SearchNodeType to_insert)//插入一个元素
{
    if(proot == NULL)//非法输入
        return;
    //1.空树->直接插入指针所指位置
    if(*proot == NULL)//空树,也是插入位置
    {
        SearchNode* new_node = CreateSearchNode(to_insert);
        *proot = new_node;
        return;
    }
    //2.非空树->寻找插入位置
    SearchNode* pre = NULL;//记录父结点
    SearchNode* cur = *proot;//记录当前结点
    while(1)
    {
        //当前结点为空,可插入
        if(cur == NULL)
            break;
        //向左子树寻找
        if(to_insert < cur->data)
        {
            pre = cur;
            cur = cur->lchild;
        }
        //向右子树寻找
        else if(to_insert > cur->data)
        {
            pre = cur;
            cur = cur->rchild;
        }
        //有相同元素,按照约定,直接返回,插入失败
        else
        {
            return;
        }
    }
    //3.当前cur所指即为可插入位置,下面插入元素
    //这里要注意当前可插入位置为父结点的左子树还是右子树
    SearchNode* new_node = CreateSearchNode(to_insert);
    //插入左子树
    if(to_insert < pre->data)
    {
        pre->lchild = new_node;
    }
    if(to_insert > pre->data)
    {
        pre->rchild = new_node;
    }
    return;
}
2 . 给定一个值,在二叉搜索树中查找对应结点
SearchNode* SearchTreeFind(SearchNode* root, SearchNodeType to_find)//查找指定值结点
{
    if(root == NULL)//空树
        return NULL;
    SearchNode* cur = root;
    while(1)
    {
        //没找到
        if(cur == NULL)
            break;
        if(to_find < cur->data)
        {
            cur = cur->lchild;
        }
        else if(to_find > cur->data)
        {
            cur = cur->rchild;
        }
        else
        {
            break;
        }
    }
    return cur;
}

3 . 给定一个值,在二叉搜索树中删除对应结点
void SearchTreeRemove(SearchNode** proot, SearchNodeType to_remove)//删除指定值结点
{
    if(proot == NULL)//非法输入
        return;
    if(*proot == NULL)//空树
        return;
    //1.查找要删除的结点
    SearchNode* root = *proot;
    SearchNode* pre = NULL;
    while(1)
    {
        //没找到
        if(root == NULL)
            return;
        if(to_remove < root->data)
        {
            pre = root;
            root = root->lchild;
        }
        else if(to_remove > root->data)
        {
            pre = root;
            root = root->rchild;
        }
        else
            break;
    }
    //2.当前root所指元素即为要删除的元素
    //(1)要删除的结点无左右子树
    if(root->lchild == NULL && root->rchild == NULL)
    {
        //要删除的元素为整个二叉搜索树的根节点
        if(root == *proot)
        {
            *proot = NULL;                                                                                                                                              
        }
        else
        {
            //删除结点为父结点的左子树
            if(to_remove <  pre->data)
                pre->lchild = NULL;
            else
                pre->rchild = NULL;
        } 
        SearchNodeDestroy(root);
    }
    //(2)要删除的结点仅有左子树
    if(root->lchild != NULL && root->rchild == NULL)
    {
        //要删除的元素为整个二叉搜索树的根节点
        if(root == *proot)
        {
            *proot = root->lchild;
        }
        else
        {
            //删除结点为父结点的左子树
            if(to_remove <  pre->data)
                pre->lchild = root->lchild;
            //要删除结点为父结点的右子树
            else
                pre->rchild = root->lchild;
        } 
        //统一释放
        SearchNodeDestroy(root);
    }
    //(3)要删除的结点仅有右子树
    if(root->lchild == NULL && root->rchild != NULL)
    {
        //要删除的元素为整个二叉搜索树的根节点
        if(root == *proot)
        {
            *proot = root->rchild;
        }
        else                                                                                                                                                            
        {
            //删除结点为父结点的左子树
            if(to_remove <  pre->data)
                pre->lchild = root->rchild;
            //要删除结点为父结点的右子树
            else
                pre->rchild = root->rchild;
        } 
        //统一释放
        SearchNodeDestroy(root);
    }
    //(4)要删除的结点左右子树均在
    if(root->lchild != NULL && root->rchild != NULL)
    {
        //查找要删除结点的右子树的最小值
        SearchNode* min = root->rchild;
        SearchNode* min_pre = root;
        while(min->lchild != NULL)
        {
            min_pre = min;
            min = min->lchild;
        }
        //用最小值覆盖要删除结点的值
        root->data = min->data;
        //删除释放
        //这里不管min所指结点的右子树是否为空,都将其指向它的右子树,因为走到这里,min不可能有左子树
        if(min->data < min_pre->data)
            min_pre->lchild = min->rchild;
        else
            min_pre->rchild = min->rchild;
        SearchNodeDestroy(min);
    }
}
        测试代码也与递归版本的测试代码相同。

猜你喜欢

转载自blog.csdn.net/lycorisradiata__/article/details/80367618