• 简单的树的递归、非递归创建,前序中序后序遍历


    扩展问题

    问题1.给定前序遍历结果和中序遍历结果,重建二叉树

    递归构造就可以了。

    Tree* create_by_order(int* pre,int* in,int size){
        if(size<=0||pre==NULL||in==NULL){
            return NULL;
        }
        int i=0;
        Tree* rt = malloc(sizeof(Tree));    
        rt->value = pre[0];
    //在中序中查找根节点位置
    while(i<size){ if(pre[0]==in[i]){ break; }else{ i++; } } rt->left = create_by_order(pre+1,in,i); rt->right = create_by_order(pre+1+i,in+i+1,size-i-1); return rt; }

    问题2.二叉树镜像

    Tree* mirror(Tree* rt){
        if(rt!=NULL){
            //交换左右子树的指针 
            Tree* temp;
            temp = rt->right;
            rt->right = rt->left;
            rt->left = temp;
            
            rt->left = mirror(rt->left);
            rt->right = mirror(rt->right);    
        }
        return rt;
    }

    问题3.求二叉树节点最大距离

    分三种情况

    情况1.如第一个图所示,左深度加上右深度

    情况2.如第二个图所示,左子树中节点的最大距离

    情况3.将图二镜像一下,右子树中节点的最大距离

    最后结果就是求这三个中较大的。

    int depth(Tree* rt){
        if(rt!=NULL){
            int l_depth = depth(rt->left)+1;
            int r_depth = depth(rt->right)+1;
            return l_depth>r_depth ? l_depth:r_depth;    
        }
        return 0;
    }
    
    int max(int a,int b,int c){
        if(a>b&&a>c){
            return a;
        }
        if(b>a&&b>c){
            return b;
        }
        if(c>a&&c>a){
            return c;
        }
      return a; }
    int max_distance(Tree* rt){ if(rt!=NULL){ int l_distance = max_distance(rt->left); int r_distance = max_distance(rt->right); int l_depth = depth(rt->left)+1; int r_depth = depth(rt->right)+1; return max(l_distance,r_distance,l_depth+r_depth); } return 0; }

     问题4.求两个节点的最近公共父节点(没有指向父节点指针,树为一般二叉树)

    分三种情况

    1.如果p1,p2节点分别在root->left,root->right,那么root为p1,p2的祖先

    2.如果p1,p2都在root->left,那边将root=root->left 转换为子问题

    3.如果p1,p2都在root->right, 那么将root=root->right 转换为字问题

    /**
    *** 查找树中包含某个节点 
    **/
    int contains(Tree* rt,const Tree* p){
        if( rt==p ){
            return 1;
        }
        if(rt==NULL){
            return 0;
        }
        return contains(rt->left,p)||contains(rt->right,p);
    }
    
    /**
    ***  查找P1和P2的最近公共父节点 
    **/
    Tree* get_same_parent(Tree* rt,const Tree* p1,const Tree* p2){
        if(rt==NULL){
            return NULL;
        }
        if(p1!=NULL&&p2!=NULL){
            int left_contains_p1 = contains(rt->left,p1);
            int left_contains_p2 = contains(rt->left,p2);
            int right_contains_p1 = contains(rt->right,p1);
            int right_contains_p2 = contains(rt->right,p2);
            if( left_contains_p1 && left_contains_p2 ){
                return get_same_parent(rt->left,p1,p2);
            }
            if( right_contains_p1 && right_contains_p2 ){
                return get_same_parent(rt->right,p1,p2);
            }    
            return rt;
        }        
    }

     扩展,如果树是搜索树时

    1.p1,p2小于root,root=root->left

    2.p1,p2大于root, root=root->right

    3.p1,p2在root两边,root为p1,p2的最近公共父节点

    STree* get_same_parent(STree* rt,STree* p1,STree* p2){
        if(rt==NULL){
            return NULL;
        }
        if( rt->value > p1->value && rt->value > p2->value ){
            return get_same_parent(rt->left,p1,p2);
        }
        if( rt->value < p1->value && rt->value < p2->value ){
            return get_same_parent(rt->right,p1,p2);
        }
        return rt;
    }

    扩展,一般树

    方法1.

    用两个链表保存从根节点到p1,p2的路径。然后将问题转换为两个链表求交集问题。

    方法2.

     转自:http://www.cppblog.com/qingbizhu/archive/2012/04/05/170213.html

    问题5.二叉查找树的删除

    待删除节点是叶子节点,直接删除

    待删除节点只有左子树或者只有右子树 ,将左(右)子树节点位置替换到待删除节点位置

    待删除节点既有左子树又有右子树,遍历到待删除节点的最左下节点位置,也就是找到一个比待删除节点小,但是小得最少的,然后将这个节点替换到待删除节点位置

    c语言写着还挺带感

    #include<stdlib.h>
    #define null 0
    struct tree{
        struct tree* left;
        int value;
        struct tree* right;
    };
    
    typedef struct tree Tree;
    Tree* root;
    
    Tree* insert_rcs(Tree* root, int value){            
        //只在叶节点位置插入 
        if(root == null){    
            root = malloc(sizeof(Tree));
            root->value = value;
            root->left = null;
            root->right = null;    
            //返回新增的叶节点 
            return root;
        }
        
        if(root->value > value){
            root->left = insert_rcs(root->left, value);
        }else{
            root->right = insert_rcs(root->right, value);
        }
        return root;
    }
    
    Tree* insert_no_rcs(Tree* root, int value){
        Tree* newnode = malloc(sizeof(Tree));
        newnode->value = value;
        newnode->left = null;
        newnode->right = null;
        if(root == null){
            root = newnode;
            return root;
        }
        //p为工作指针 
        Tree* p = root;
        //p节点是插入节点,pre节点时插入节点的父节点 
        Tree* pre;
        while(p){
            pre = p;
            if(p->value > value){
                p = p->left;
            }else{
                p = p->right;
            }    
        }
        if(pre->value > newnode->value){
            pre->left = newnode;
        }else{
            pre->right = newnode;
        }
        return root;    
    }
    
    //前序遍历 
    void pre_print_rcs(Tree* root){
        if(root != null){
            printf("value: %d \t",root->value);
            pre_print_rcs(root->left);
            pre_print_rcs(root->right);
        }
    }
    
    Tree* Stack[20];
    int top = -1;
    
    //前序遍历 非递归 
    void pre_print_no_rcs(Tree* root){
        //top != -1 这个条件一定要加上,这是处理单枝情况 
        while(root != null || top != -1){
            if(root != null){
                printf("%d \t",root->value);
                if(top+1 != 20){
                    Stack[++top] = root;
                    root = root->left;
                }
            }else{
                root = Stack[top--]->right;
            }    
        }
    }
    
    //中序遍历
    void in_print_rcs(Tree* root){
        if(root != null){
            in_print_rcs(root->left);
            printf("value: %d \t",root->value);
            in_print_rcs(root->right);
        }
    }
    
    //中序遍历 非递归 
    void in_print_no_rcs(Tree* root){
        //top != -1 这个条件一定要加上,这是处理单枝情况 
        while(root != null || top != -1){
            if(root != null){
                if(top+1 != 20){
                    Stack[++top] = root;
                    root = root->left;
                }
            }else{
                root = Stack[top--];
                printf("%d \t",root->value);
                root = root->right;
            }    
        }    
    }
    
    //后序遍历
    void post_print_rcs(Tree* root){
        if(root != null){
            post_print_rcs(root->left);
            post_print_rcs(root->right);
            printf("value: %d \t",root->value);
        }
    }
    
    Tree* Q[20];
    int front;
    int rear;
    //层序遍历 
    //输出队头元素,并将左右子树如队列 
    void level_print(Tree* root){
        front = rear = 0;
        if(root != null){
            Q[++rear] = root;
            while(rear != front){
                Tree* p = Q[++front];
                printf("%d \t",p->value);
                if(p->left != null){
                    Q[++rear] = p->left;
                }
                if(p->right != null){
                    Q[++rear] = p->right;
                }
            }
        }
    }
    
    Tree* create_no_rcs(int* list, int n){
        int i;
        for(i=0; i<n; i++){
            root = insert_no_rcs(root, list[i]);
        }
        return root;
    }
    
    Tree* create_rcs(int* list, int n){
        int i;
        for(i=0; i<n; i++){
            root = insert_rcs(root, list[i]);
        }
        return root;
    }
    
    int main(){
        int list[10] = {
            6,9,7,4,5,2,1,8,12,0
        };
        //root = create_no_rcs(list, 10);
         root = create_rcs(list, 10);
        
        //pre_print_rcs(root);
        //pre_print_no_rcs(root);
        in_print_rcs(root);
        in_print_no_rcs(root);
        //post_print_rcs(root);
        
        //level_print(root);
        
        return 0;
    }
  • 相关阅读:
    x64汇编第三讲,64位调用约定与函数传参.
    【Unity】6.7 向量和Vector3类
    【Unity】6.6 Random类
    【Unity】6.5 Time类、Mathf类、Coroutine类
    【Unity】6.4 Transform--移动、旋转和缩放游戏对象
    【Unity】6.3 通过 C# 脚本创建和访问游戏对象
    【Unity】6.2 在VS2015中调试 C# 脚本
    【Unity】6.1 Unity中的C#脚本基础知识
    【Unity】第6章 Unity脚本开发基础
    【Unity】4.7 摄像机
  • 原文地址:https://www.cnblogs.com/23lalala/p/2703646.html
Copyright © 2020-2023  润新知