【查找二叉树】清空、查找、插入、删除

查找二叉树:也叫排序二叉树,搜索二叉树。具有以下特点(百度百科)

二叉排序树或者是一棵空树,或者是具有下列性质的
二叉树: (1)若左子树不空,则左子树上所有结点的值均小于或等于它的
根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值; (3)左、右子树也分别为二叉排序树;

查找二叉树的创建和基本二叉树的创建无差异

二叉树的清空,实际上就是后序遍历删除

// 想要改变指针的值还是需要将他作为返回值,不然就是传入二级指针
static SearchTree MakeEmpty(SearchTree tree)
{
    if(tree){
        MakeEmpty(tree->LeftNode);
        MakeEmpty(tree->RightNode);
        free(tree);
        tree = NULL;
    }
    return tree;
}

查找二叉树的查找

1、基本二叉树的查找方法

// 实际上这样会将所有的节点都遍历一遍而忽略了查找二叉树的特点
// 以root为界限开始区分两者
static SearchTree FindNode(TreeElement element, SearchTree tree)
{
    SearchTree ret_tree = NULL;
    if (tree){
        if(element==tree->element){
            ret_tree = tree;
            return ret_tree;
        }
        
        ret_tree = FindNode(element, tree->LeftNode);
        ret_tree = FindNode(element, tree->RightNode);
    }
    return ret_tree;
}

2、二叉树的特点使用尾递归(递归在函数的尾部)

// 抓住了查找二叉树的特点,可以更加精确的进行查找
static SearchTree Find(TreeElement element, SearchTree tree)
{
    if(tree){
        if(tree->element==element){
            return tree;
        }else if(tree->element>element){
            return Find(element, tree->LeftNode);
        }else{
            return Find(element, tree->RightNode);
        }
    }
    return NULL;
}

3、将尾递归转换成赋值和goto语句

因为二叉树的平均深度是logN,所以使用的栈空间也只是logN,一般还是可以直接使用方法2,以下供参考

// 将尾递归转换成赋值和goto语句
static SearchTree FindNoLoop(TreeElement element, SearchTree tree)
{
next:
    if(tree){
        if(tree->element==element){
            return tree;
        }else{
            if(tree->element>element)
                tree = tree->LeftNode;
            else
                tree = tree->RightNode;
            goto next;
        }
    }
    return NULL;	
}

查找二叉树查找最大、最小值

static SearchTree FindMax(SearchTree tree)
{
next:
    if(tree){
        if(tree->RightNode == NULL)
            return tree;
        tree = tree->RightNode;
        goto next;
    }
    return tree;
}

static SearchTree FindMin(SearchTree tree)
{
    if(tree){
        if(tree->LeftNode == NULL)
            return tree;
        return FindMin(tree->LeftNode);
    }
    return NULL;
}

往二叉树中插入元素

如果插入的元素已经在二叉树中存在,则只是更新二叉树中记录发生频率的域(这里什么都不做)。否则插入到查找二叉树的尾部。

static SearchTree CreateTreeCell(TreeElement element)
{
    SearchTree tree = NULL;
    tree = (SearchTree)malloc(sizeof(*tree));
    if(tree==NULL){
        fprintf(stderr,"there is no space\n");
        return NULL;
    }
    tree->element= element;
    tree->RightNode = NULL;
    tree->LeftNode = NULL;
    return tree;
}
static SearchTree Insert(TreeElement element, SearchTree tree)
{
    if(tree){
        if(element>tree->element){
            if(tree->RightNode==NULL){
                tree->RightNode = CreateTreeCell(element);
            }else{
                Insert(element, tree->RightNode);
            }
        }else{
            if(tree->LeftNode==NULL){
                tree->LeftNode = CreateTreeCell(element);
            }else{
                Insert(element, tree->LeftNode);
            }
        }
        return tree;
    }
    return NULL;
}

这是书上的解法,比我的思路好。

static SearchTree InsertNode(TreeElement element, SearchTree tree)
{
    if(tree==NULL){
        
        tree = (SearchTree)malloc(sizeof(*tree));
        if(tree==NULL){
            fprintf(stderr,"there is no space\n");
            return NULL;
        }
        tree->element= element;
        printf("tree->element is %d\n", tree->element);
        tree->RightNode = NULL;
        tree->LeftNode = NULL;
    }else if(element>tree->element){
        //需要将返回值指向tree->RightNode
        tree->RightNode = InsertNode(element, tree->RightNode);
    }else{
        // 需要将返回值指向tree->LeftNode
        tree->LeftNode = InsertNode(element, tree->LeftNode);
    }
    return tree;
}

节点的删除

1)删除的节点为树叶

2)删除的节点包含一个子节点

3)删除的节点包含两个子节点(在该节点的右子树中寻找最小,特换为该节点元素,然后删除右子树元素最小的节点)

值得注意的:当两个指针同时指向同一块内存,free掉一个指针会导致另外一个指针成为野指针,所以也需要将其置为NULL

static SearchTree Delete(TreeElement element, SearchTree tree)
{
    if(tree){
        if(element>tree->element){
            // 无论是插入还是删除都需要建立指针的指向关系
            tree->RightNode = Delete(element, tree->RightNode);
        }else if(element<tree->element){
            tree->LeftNode = Delete(element, tree->LeftNode);
        }else{

            if(tree->RightNode!=NULL&&tree->LeftNode!=NULL){
                SearchTree tree_min = FindMin(tree->RightNode);
                if(tree_min){
                    printf("tree->element is %d\n", tree->element);
                    tree->element = tree_min->element;
                    tree->RightNode = Delete(tree_min->element, tree->RightNode);
                }
            }else{
                SearchTree tree_temp = tree;
                if(tree->RightNode){
                    tree = tree->RightNode;
                }else if(tree->LeftNode){
                    tree = tree->LeftNode;
                }
                if(tree==tree_temp){//两个指针同时指向同一块内存,需要将其置为NULL
                    tree = NULL;
                }
                free(tree_temp);
                tree_temp = NULL;
            }
        }
        return tree;
    }
}

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/feifei_csdn/article/details/80188288
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞