zoukankan      html  css  js  c++  java
  • 二叉树操作复习

    2017-08-29 11:46:37

    writer:pprp

    已经写了二叉树好几次了,但是还是有很多细节没有考虑完全

    还有好多东西都没有考虑到,以后还是要写这个代码,把应该考虑的细节都考虑清楚

    在写有关树的函数的时候都要小心地处理空树的这种退化情况

    代码及讲解如下:(都测试过了,应该没问题,如果有问题请留言)

    /*
    @theme:树的建立和遍历
    @writer:pprp
    @start:10:00
    @end:11:47
    @declare:我建立的这个树好像跟教科书上的树方向反了一下,
    但是不影响理解,教科书上的是大的在右边,小的在左边,我的恰好反了过来
    @date:2017/8/28
    */
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct tree
    {
        int val;
        tree * l;
        tree * r;
    };
    
    //function 1 insert
    //插入操作,比根节点大的要在左子树,比根节点小的要放在右子树
    //test:ok
    tree * Insert(tree *root, int val)
    {
        tree * parent;
        tree * current;
    
        tree * newVal = new tree();
    
        newVal->val = val;
        newVal->r = NULL;
        newVal->l = NULL;
    
        if(root == NULL)
        {
            root = newVal;
        }
        else
        {
            current = root;
            while(current != NULL)
            {
                parent = current;
                if(current->val < val)//这里的符号要与下边的符号一致
                {
                    current = current->l;
                }
                else
                {
                    current = current->r;
                }
            }
    
            if(parent->val < val) //这里的符号要跟上边的符号一致
            {
                parent->l = newVal;
            }
            else
            {
                parent->r = newVal;
            }
        }
        return root;
    }
    
    //function 2: MakeEmpty
    //test: ok
    tree* MakeEmpty(tree * root)
    {
        if(root != NULL)
        {
            MakeEmpty(root->r);
            MakeEmpty(root->l);
            delete root;
            root = NULL;
        }
        return NULL;
    }
    
    //function 3: Find value
    //test:ok
    //@param:返回一个指针,代表找到该节点的指针,否则返回NULL
    tree* FindValue(tree * root,int val)
    {
        if(root == NULL)
            return NULL;
        if(val < root->val)
            return FindValue(root->r,val);
        else if(val > root->val)
            return FindValue(root->l,val);
        else
            return root;
    }
    
    //function 4:Find Min
    //由于树的构造是有大小之分的所以找小的直接向有子树找就好
    //test:ok
    tree* FindMin(tree * root)
    {
        if(root == NULL)
            return NULL;
        else if(root->r == NULL)
            return root;
        else
            return FindMin(root->r);
    }
    
    //function 5: Find Max
    //直接向右子树查找就好了
    //test:ok
    tree * FindMax(tree * root)
    {
        if(root == NULL)
            return NULL;
        else if(root->l == NULL)
            return root;
        else
            return FindMax(root->l);
    }
    
    ////function 6: delete
    ////test:error
    ////错误原因:思路不大对,如果只有一个子节点的情况,还需要判断这个本身是左边子节点还是右边子节点
    //tree * Delete(tree * root, int val)
    //{
    //    tree * current = FindValue(root, val);
    //    tree * tmp = NULL;
    //    if(current->l == NULL && current->r == NULL)  //如果两个孩子都没有就可以直接删除掉
    //    {
    //        delete(current);
    //    }
    //    else if(current != NULL) //只有左孩子,将左孩子中最小的值变成原先节点
    //    {
    //        tmp = FindMin(current);
    //        current->val = tmp->val;
    //        delete(tmp);
    //        tmp = NULL;
    //    }
    //    else if(current->r != NULL) //只有右孩子
    //    {
    //        tmp = FindMax(current);
    //        current->val = tmp->val;
    //        delete(tmp);
    //        tmp = NULL;
    //    }
    //    else        //两个孩子都有
    //    {
    //        tmp = FindMin(current);
    //        current->val = tmp->val;
    //        delete(tmp);
    //        tmp = NULL;
    //    }
    //}
    
    //function 6: delete
    //test:ok
    //要删除的节点值为val,最后返回已经修改过的头结点
    tree * Delete(tree * root, int val)
    {
        tree * par;
        tree * kid;
        //第一部分找到该节点并找到该节点的父亲节点
        kid = root;
        while(kid != NULL)
        {
    
            if(kid->val > val)
            {
                par = kid;
                kid = kid->r;
            }
            else if(kid->val < val)
            {
                par = kid;
                kid = kid->l;
            }
            else if(kid->val == val)
            {
                break;  //这时候kid指向的是要找的节点 par记录的是要找的节点的父亲节点
            }
        }
    
        //没有找到的情况
        if(kid == NULL)
        {
            cout << "not find! " << endl;
            return NULL;
        }
        //现在开始判断是那种情况
        //1、如果是都是为空的情况
        if(kid->l == NULL && kid->r == NULL)
        {
            if(kid == root) //没有想到,如果是根节点,那么就直接赋值根节点为空
                root = NULL;
            if(par->l == kid)
                par->l = NULL;
            if(par->r == kid)
                par->r = NULL;
            delete(kid);
        }//2、只有一个节点的情况
        else if(kid->l == NULL || kid->r == NULL)
        {
            if(kid == root)
            {
                if(kid->r == NULL)
                    root = kid->l;
                else
                    root = kid->r;
                delete(root);
            }
            else  //分情况讨论 
            {
                  if(par->r == kid && kid->l)
                  {
                        par->r = kid->l;
                  }
                  else if(par->r == kid && kid->r)
                  {
                        par->r =  kid->r;
                  }
                  else if(par->l == kid && kid->l)
                  {
                         par->l = kid->l;
                  }
                  else if(par->l == kid && kid->r)
                  {
                         par->l = kid->r;
                  }
                  delete(kid);
            }
        } //3、有两个子节点的情况,这里采用将左边最小的替换找到节点的方案
        else
        {
               tree * tmp = FindMin(kid);
               kid->val = tmp->val;
               delete(tmp);
        }
        return root;
    }
    
    //前序遍历输出 -- ok
    void preOut(tree * root)
    {
        if(root != NULL)
        {
            cout << root->val <<" ";
            preOut(root->l);
            preOut(root->r);
        }
    }
    
    //中序遍历输出--ok
    void midOut(tree * root)
    {
        if(root != NULL)
        {
            midOut(root->l);
            cout << root->val << " ";
            midOut(root->r);
        }
    }
    
    //后序遍历输出--ok
    void backOut(tree * root)
    {
        if(root != NULL)
        {
            backOut(root->l);
            backOut(root->r);
            cout << root->val << " ";
        }
    }
    
    int main()
    {
        int n;
        cin >> n;
        int a[100];
    
        tree * root = NULL;
    
        for(int i = 0 ; i < n ; i++)
        {
            srand((int)time(NULL)+i);
            a[i] = rand()%100;
        }
    
        for(int i = 0 ; i < n ; i++)
            cout << a[i] <<" ";
        cout << endl;
    
        //create a tree
        for(int i = 0 ; i < n ; i++)
        {
            root = Insert(root, a[i]);
        }
    
        cout << "preOut:" << endl;
        preOut(root);
        cout << endl;
    
    //    root = MakeEmpty(root);
    //    cout << "preOut:" << endl;
    //    backOut(root);
    //    cout << endl;
    
    //    int val;
    //    cin >> val;
    //    tree * tmp = FindValue(root,val);
    //    if(tmp != NULL)
    //      cout << tmp->val << endl;
    
        tree * tmp = FindMax(root);
        if(tmp != NULL)
            cout << tmp->val << endl;
    
        tmp = FindMin(root);
        if(tmp != NULL)
            cout << tmp->val << endl;
    
        cout << "-----" << endl;
    
        int val;
        cin >> val;
        root = Delete(root,val);
    
        cout << "preOut:" << endl;
        preOut(root);
        cout << endl;
    
        return 0;
    }
  • 相关阅读:
    黑马程序员——JAVA基础之主函数main和静态static,静态代码块
    黑马程序员——JAVA基础之final this.和super.的区别
    黑马程序员——JAVA基础之构造函数,构造代码块
    黑马程序员——JAVA基础之简述 类的封装
    黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象
    NBU Rman异机恢复Oracle
    Oracle的Rman差异增量备份
    rman备份出现ORA-19625
    查询rman备份信息常用指令
    RMAN-06172: no AUTOBACKUP found or specified handle is not a valid copy or piece
  • 原文地址:https://www.cnblogs.com/pprp/p/7447579.html
Copyright © 2011-2022 走看看