二叉树学习

 

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

回归正题:

二叉树的概念

二叉树是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;
        }

}

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

 

posted @ 2013-03-10 12:33  onlycxue  阅读(1313)  评论(0编辑  收藏  举报