zoukankan      html  css  js  c++  java
  • 二叉树学习

    最近有了大把的时间,学习了数据结构,在大学的时候就接触过数据结构,在现在那时只不过是为了考一个二级证,那时的概念只是背,但是一直不理解解,还好,我打算重走这段历史。

    回归正题:

    二叉树的概念

    二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(成为空二叉树),或者由一个节点和两棵不互相交的,分别称为根节点的左子树和右子树的二叉树组成。

    二叉树的特点

    1. 每个结点最多有两棵子树
    2. 左右子树是有顺序的,不能颠倒的
    3. 即使子树只有一个结点,也要区分它是左子树还是右子树。

    特殊二叉树

    1. 斜树

        所有的结点都只有左子树的二叉树叫做左斜树。所有结点都只有右子树的二叉树叫做右斜树。这样二叉树的结点数与树的深度有关。

      2. 满二叉

        在一棵二叉树中,如果所有的分支结点都存在左子树和右子树,并且所有的叶子都在同一层上,这样的二叉树叫做满二叉。在同深度的二叉树中满二叉树的叶子结点个数最多,叶子树最多。

      3. 完全二叉树

        对一棵树具有n个节点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同深度的满二叉树编号为i的节点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。

      完全二叉树的特点:

        1)叶子结点只能出现在最下两层
        2)最下层的叶子一定集中在左部连续位置
        3)倒数二层,若有叶子节点,一定都在右部连续位置
        4)如果结点度为1,则该节点只有左子树,即不存在只有右子树的情况
        5)同样结点数的二叉树,完全二叉树的深度最小。

    二叉树的构建

    1. 两个类的声明:

        

    class BintreeNode
    {
    private:
        int data;
        BintreeNode *rightChild,*leftChild;
    public:
        BintreeNode(const int &item,BintreeNode *right=NULL,BintreeNode *left=NULL):data(item),rightChild(right),leftChild(left){};
        void setRightchild(BintreeNode* r)
        {
            rightChild=r;
        }
        BintreeNode* getRightchild()
        {
            return rightChild;
        }
        void setLeftchild(BintreeNode* r)
        {
            leftChild = r;
    
        }
    
        BintreeNode * getLeftchild()
        {
            return leftChild;
        }
        void setData(int data)
        {
            data = data;
        }
        int getData()
        {
            return data;
        }
    };
    
    class BinTree{
    
    private:
        BintreeNode *root;
    public:
        BinTree(BintreeNode *Item=NULL):root(Item){};
        ~BinTree()
        {
            delete root;
        };
        void setRoot(BintreeNode *item)
        {
            root = item;
        }
        BintreeNode *getRoot()
        {
            return root;
        }
        
        BintreeNode *creat_tree();
    
        void pre_order(BintreeNode *Item) const;
        void in_order(BintreeNode *Item) const;
        void post_order(BintreeNode *Item) const;
        void level_order(BintreeNode *Item)const;
        int get_leaf_num(BintreeNode *Item) const;
        int get_tree_height(BintreeNode *Item) const;
        void swap_left_right(BintreeNode *Item) const;
        //BintreeNode * get_near_common_father(BintreeNode *root,BintreeNode *r,BintreeNode *l) const;
        void print_rout(BintreeNode *Item,int sun) const;
        bool is_in_tree(BintreeNode *r,BintreeNode *Item) const;
    };

    2.二叉树的构建

    BintreeNode *BinTree::creat_tree()
    {
        char item;
        BintreeNode *t,t_r,t_l;
        cin>>item;
        if(item!='#')
        {
            BintreeNode *pNode = new BintreeNode(item-48);//由于0的ascii码是48,这样做是为了把字符转化为数字 
            t = pNode;
            t_l = creat_tree();      //先构建左子树后构建右子树
            t->setLeftchild(t_l);
            t_r = creat_tree();
            t->setRightchild(t_r);
            return t;
        }
        else
        {
            t = NULL;
            return t;
        }
    }

    二叉树的前序遍历

    void BinTree::pre_order(BintreeNode *Item) const
    {
            if(Item!=NULL)
            {
                cout<<Item->data<<endl;
                pre_order(Item->leftChild);   //先遍历二叉树的左子树->左子树上的右子树->在遍历二叉树的右子树->右子树上的左子树->右子树上的右子树
                pre_order(Item->rightChild);
            }
    }

    二叉树的中序遍历

    void BinTree::in_order(BintreeNode *Item) const
    {
            if(Item!=NULL)
            {
                in_order(Item->leftChild);
                cout<<Item->data<<endl;
                in_order(Item->rightChild);    
            }
    }

    二叉树的后续遍历

    void BinTree::post_order(BintreeNode *Item) const
    {
            if(Item!=NULL)
            {
                post_order(Item->leftChild);
                post_order(Item->rightChild);    
                cout<<Item->data<<endl;
            }        
    }

    得到二叉树的节点总数

    int BinTree::get_leaf_num(BintreeNode *Item) const
    {
            if (Item == NULL)
            {
                    return 0;
            }
            if(Item->getLeftchild() == NULL && Item->getRightchild() == NULL)
            {
                    return 1;
            }
            return (get_leaf_num(Item->getLeftchild())+get_leaf_num(Item->getRightchild()));
    
    }

    得到树的深度

    int get_tree_height(BintreeNode *Item) const
    {
        if (Item == NULL)
        {
            return 0;
        }
        
        if(Item->getLeftchild()==NULL && Item->getRightchild() == NULL)
        {
            return 1;
        }
        int l_tree = get_tree_height(Item->getLeftchild());
        int r_tree = get_tree_height(Item->getRightchild());
        return l_tree >=r_tree ? l_tree+1 : r_tree+1;
    
    }

    交互左子树与右子树

    void BinTree::swap_left_right(BintreeNode *Item)
    {
            if(Item == NULL)
            {
                return NULL;
            }
    
            BintreeNode *tmp = Item->getLeftchild();
            Item->setLeftchild(Item->getRightchild());
            Item->setRightchild(tmp);
            
            swap_left_right(Item->getLeftchild());
            swap_left_right(Item->getRightchild());
    }

    节点查看是否在根为r的二叉树中存在Item这个节点。

    bool BinTree::is_in_tree(BintreeNode *r,BintreeNode *Item) const
    {
            if(!r)
            {
                return NULL;
            }
            else if(r == Item)
            {
                return false;
            }
            else
            {
                bool has = false;
                if(r->getLeftchild() != NULL)
                {
                    has = is_in_tree(r->getLeftchild(),Item);
                }
                if(!has && r->getRightchild()!=NULL)
                {
                    has = is_in_tree(r->getRightchild(),Item)
                }
                return has;
            }
    
    }

    如何查找二叉树中两个结点最近的双亲结点?稍后讨论

  • 相关阅读:
    log4j(七)——log4j.xml简单配置样例说明
    log4j(六)——log4j.properties简单配置样例说明
    三元运算符注意事项
    单精度浮点数操作
    反转链表算法Java实现
    VBS计时器2
    肖申克的救赎影评
    计算机中K到底是1000还是1024?
    二进制补码除法——计算机底层整数除法模拟之Java实现
    VBS计时器
  • 原文地址:https://www.cnblogs.com/onlycxue/p/2952574.html
Copyright © 2011-2022 走看看