• 二叉树查找、删除、遍历、销毁、结点的统计、深度计算、广度优先遍历、非递归先、中、后序遍历


    二叉树结点的查找跟遍历是很容易实现的,但是要想实现二叉树结点的删除,确实是一项很费事的工作

    下面我只介绍二叉树结点的删除。删除二叉树的结点,会遇到三种情况

    被删除的结点没有子树。这种情况最容易操作,直接找到该结点,然后让它的父结点指向它的指针为空,然后释放该结点即可

    被删除的结点只有一个子树。找到该结点,让其父结点指向它的子树,然后释放该结点

    被删除的结点同时拥有左右子树。此处我拿顺序二叉树为例,找到该结点,然后找到该结点右子树的最左的子结点,让该子结点的父结点指向空,再让该结点的父结点指向该子结点,然后释放该结点(此处我提供一个小技巧,我们可以将该子结点复制给该结点,然后让该子结点的父结点指向空,然后释放该子结点)!如果该子结点还有右子树,那么直接将该子结点的父结点的左子树指向该子结点的右子树。

    说的有点绕口,慢慢理解吧

    #include<stdio.h>
    #include<stdlib.h>
    
    //二叉树结点的结构体定义
    
    typedef struct tree
    {
        int num;
        struct tree *prve;//此处为前驱指针,该指针的目的是为了方便找到父结点
        struct tree *left;
        struct tree *right;
    }Tree;
    
    //初始化二叉树
    
    void Init_Tree(Tree *Root)
    {
        Root->prve = NULL;
        Root->left = NULL;
        Root->right = NULL;
    }
    
    //插入结点
    
    void Insert_Node(Tree *Root, int key)
    {
        if(Root->num >= key){
            if(Root->left == NULL){
                Tree *node = (Tree *)malloc(sizeof(Tree));
                node->prve = node->left = node->right = NULL;
                node->num = key;
                Root->left = node;
                node->prve = Root;
            }
            else Insert_Node(Root->left,key);
        }
        else{
            if(Root->right == NULL){
                Tree *node = (Tree *)malloc(sizeof(Tree));
                node->prve = node->left = node->right = NULL;
                node->num = key;
                Root->right = node;
                node->prve = Root;
            }
            else Insert_Node(Root->right,key);
    
        }
    }
    
    //查找结点
    
    Tree *Search_Node(Tree *Root,int key)
    {
        if(Root == NULL) return NULL;
        if(Root->num == key)
            return Root;
        else if(Search_Node(Root->left,key) != NULL)
            return Search_Node(Root->left,key);
        else if(Search_Node(Root->right,key) != NULL)
            return Search_Node(Root->right,key);
        else return NULL;
    }
    
    //查找结点版本2
    Tree *Search_Node2(Tree *Root, int key)
    {
        if(Root == NULL)return NULL;
        if(Root->num == key)
            return Root;
        if(Root->num > key) return Search_Node2(Root->left,key);
        else return Search_Node2(Root->right,key);
    }
    
    
    //删除结点
    
    void Del_Node(Tree *Root)
    {
        if(Root->left == NULL && Root->right == NULL)
        {
            if(Root->prve->left == Root)
                Root->prve->left = NULL;
            else Root->prve->right = NULL;
            free(Root);
        }
        else if(Root->left == NULL)
        {
            if(Root->prve->left == Root)
                Root->prve->left = Root->right;
            else Root->prve->right = Root->right;
            free(Root);
        }
        else if(Root->right == NULL)
        {
            if(Root->prve->left == Root)
                Root->prve->left = Root->left;
            else Root->prve->right = Root->left;
            free(Root);
        }
        else{
            Tree *temp = Root->right;
            while(temp->left){
                temp = temp->left;
            }
            if(temp->right == NULL){
                temp->prve->left = NULL;
                *Root = *temp;
                free(temp);
            }
            else {
                temp->prve->left = temp->right;
                *Root = *temp;
                free(temp);
            }
        }
    }
    
    //中序遍历二叉树
    
    void Travel_Tree(Tree *Root)
    {
        if(Root == NULL) return ;
        Travel_Tree(Root->left);
        printf("point:%d  
     ",Root->num);
        Travel_Tree(Root->right);
    }
    
    // 广度优先搜索
    
    void Level_Tree(Tree *Root)
    {
        Tree *flag[100];
        int top = 0, down = 0;
        flag[top++] = Root;
        while(top-down)
        {
            printf("point: %d
    ",flag[down++]->num);
            if(flag[down-1]->left)
                flag[top++] = flag[down-1]->left;
            if(flag[down-1]->right)
                flag[top++] = flag[down-1]->right;
        }
    }
    
    //非递归先序遍历二叉树
    
    void First_Tree(Tree *Root)
    {
        Tree *flag[100], *temp;
        int top = 0;
        flag[top++] = Root;
        while(top)
        {
            temp = flag[top-1];
            printf("point: %d
    ",flag[--top]->num);
            if(temp->right) flag[top++] = temp->right;
            if(temp->left) flag[top++] = temp->left;
        }
    }
    
    //非递归中序遍历二叉树
    
    void Mid_Tree(Tree *Root)
    {
        Tree *flag[100], *temp;
        int top = 0;
        temp = Root;
        while(top || temp)
        {
            if(temp){
                flag[top++] = temp;
                temp = temp->left;
            }else {
                temp = flag[--top];
                printf("point: %d
    ",temp->num);
                temp = temp->right;
            }
        }
    }
    
    //非递归后序遍历二叉树
    
    void Last_Tree(Tree *Root)
    {
        Tree *flag[100], *p, *q;
        int top = 0;
        p = Root->left; q = NULL;
        flag[top++] = Root;
        while(top)
        {
            if(p){
                flag[top++] = p;
                p = p->left;
            } else{
                p = flag[top-1];
                if(p->right == NULL || p->right == q){
                    printf("point: %d
    ",p->num);
                    top--;
                    q = p;
                    p = NULL;
                } else p = p->right;
            }
        }
    }
    
    //销毁二叉树
    
    void Destory_Tree(Tree *Root)
    {
        if(Root == NULL) return;
    
        Destory_Tree(Root->right);
        Destory_Tree(Root->left);
    
        printf("%d over!
    ", Root->num);
        free(Root);
        return ;
    }
    
    //求树的深度
    
    int Deep_Tree(Tree *Root)
    {
        if(Root == NULL) return 0;
        
        return 1+(Deep_Tree(Root->left) > Deep_Tree(Root->right)?Deep_Tree(Root->left):Deep_Tree(Root->right));
    }
    
    //统计结点
    
    int Count_Tree(Tree *Root)
    {
        if(Root == NULL) return 0;
        return (1 + Deep_Tree(Root->left) + Deep_Tree(Root->right));
    }
    
    //删除的结点为根结点
    
    void Del_Root(Tree *Root)
    {
        if(Root->left == NULL && Root->right == NULL) Root = NULL;
        else if(Root->left == NULL) *Root = *(Root->right);
        else if(Root->right == NULL) *Root = *(Root->left);
        else{
            Tree *p = Root->right;
            while(p->left) p = p->left;
                if(p->prve == Root){
                    Tree *q = Root->left;
                    *Root = *p;
                    free(p);
                    Root->left = q;
                }
                else{
                    Tree *q1, *q2;
                    q1 = Root->left;
                    q2 = Root->right;
                    *Root = *p;
                    if(p->right)
                    p->prve = p->right;
                    else p->prve = NULL;
                    free(p);
                    Root->left = q1;
                    Root->right = q2;
                }
        }
    }
    int main()
    {
        int i, key;
        Tree *Root, *temp;
        Root = (Tree *)malloc(sizeof(Tree));
        Init_Tree(Root);
    
        scanf("%d",&Root->num);
    
        for(i = 1;i < 10; i++)
        {
            scanf("%d",&key);
            Insert_Node(Root,key);
        }
    
        Travel_Tree(Root);
    
    //    printf("
    深度为:%d
    总结点数:%d
    ",Deep_Tree(Root),Count_Tree(Root));
    
        printf("请输入您要删除的结点:
    ");
        scanf("%d",&key);
        temp = Search_Node(Root,key);
        if(temp != Root) Del_Node(temp);
        else Del_Root(Root); 
    
    //    Level_Tree(Root);
    
        Travel_Tree(Root);
        printf("
    ");
    /*
        First_Tree(Root);
    
        Mid_Tree(Root);
    
        Last_Tree(Root);
    
        Destory_Tree(Root);
    */
        return 0;
    }
    View Code
  • 相关阅读:
    (转)A*算法详解及习题
    BZOJ1444[Jsoi2009]有趣的游戏——AC自动机+概率DP+矩阵乘法
    交通——set+dsu on tree
    [Codeforces1132G]Greedy Subsequences——线段树+单调栈
    BZOJ4482[Jsoi2015]套娃——贪心+set
    BZOJ4477[Jsoi2015]字符串树——可持久化trie树
    BZOJ4475[Jsoi2015]子集选取——递推(结论题)
    [UOJ86]mx的组合数——NTT+数位DP+原根与指标+卢卡斯定理
    BZOJ2428[HAOI2006]均分数据——模拟退火
    BZOJ4712洪水——动态DP+树链剖分+线段树
  • 原文地址:https://www.cnblogs.com/SDUTYST/p/3867216.html
Copyright © 2020-2023  润新知