二叉树的简单操作(递归)

什么是二叉树?!

二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

首先让我们了解一些树的术语吧!

树的结点(node)包含一个数据元素及若干指向子树的分支;
孩子结点(child node)结点的子树的根称为该结点的孩子;
双亲结点B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点从根到该结点的所经分支上的所有结点
子孙结点以某结点为根的子树中任一结点都称为该结点的子孙
结点层根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度树中最大的结点层
结点的度结点子树的个数
树的度树中最大的结点度。
叶子结点也叫终端结点,是度为 0 的结点;
分枝结点度不为0的结点;
有序树子树有序的树,如:家族树;
无序树不考虑子树的顺序;

(看吧,兄弟姐妹,子孙祖先,活像一个族谱,,,,这命名的也特别有意思)。。。

二叉树的七大性质:

1、 在非空二叉树中,第i层的结点总数不超过(2^i - 1),( i>=1);


2、深度为k的二叉树最多有(2^k - 1)个结点(k>=1),最少有k个结点;


3、对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则 N0=N2+1;(各位同学注意一下该公式的推导过程,可以对你理解二叉树有很大的帮助哦!)


( #这里插放一下完全二叉树和满二叉树的概念:
满二叉树:

深度为k且含有2^k-1个结点的二叉树。
其特点为:每一层上的结点数都是最大结点数,即每一层 i 的结点数都具有最大值2^k - 1.

完全二叉树:

深度为 k 的有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 k 的满二叉树中编号从 1 至 n 的结点一一对应时,称之为完全二叉树。

完全二叉树有两个特点:
(1)、叶子结点只可能在层次最大的两层出现。
(2)、对任一结点,若其右分支下的子孙的最大层次为 l ,则其左分支下的子孙最大层次必为 l 或 l+1.

4、 具有n个结点的完全二叉树的深度为在这里插入图片描述(注:[ ]表示向下取整)


5、有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:

(1)、若I为结点编号则 如果I>1,则其父结点的编号为I/2;
(2)、如果2I<=N,则其左孩子(即左子树的根结点)的编号为2I;若2I>N,则无左孩子;
(3)、如果2
I+1<=N,则其右孩子的结点编号为2I+1;若2I+1>N,则无右孩子。

6、给定N个节点,能构成h(N)种不同的二叉树。h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。


7、设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和 J=I+2i [2]


二叉树的链式存储

typedef  struct BiTnode
{
    int data;//当然,你这里可以放你想要的数据
    struct BiTnode *lchild, *rchild;
}BiTnode, *Bitree;

首先是遍历二叉树问题

遍历二叉树分为先序遍历、中序遍历和后序遍历(说白了,这个前中后是根据访问结点的顺序不同而命名的,其次就是遍历左子树位于遍历右子树之前,是不是很容易理解呢?!)

先序遍历:

(1)、访问根节点。
(2)、先序遍历左子树。
(3)、先序遍历右子树。

void first(Bitree T)
{
    if(T)
    {
        cout << T->data;//这里你可以选择保存数据,,,
        first(T->lchild);//递归先序遍历左子树
        first(T->rchild);//递归先序遍历右子树
    }
}

中序遍历:

(1)、中序遍历左子树。
(2)、访问根节点。
(3)、中序遍历右子树。

void middle(Bitree T)
{
    if(T)
    {    
        middle(T->lchild);
        cout << T->data;//这里你可以选择保存数据,,,
        middle(T->rchild);
    }
}

后序遍历:

(1)、后序遍历左子树。
(2)、后序遍历右子树。
(3)、访问根结点。
(那么,聪明的读者,后序遍历的代码你们已经知道了嘛?!)

下面是先序遍历创建二叉链表

void CreatBitree(Bitree &T)
{
    char ch;
    cin >> ch;
    if(ch == '#')//若ch为 # ,则二叉树为空树。
        T = NULL;
    else 
    {
        T = (BiTnode *)malloc(sizeof(BiTnode));
        T->data = ch; 
        CreatBitree(T->lchild);//递归先序创建左子树
        CreatBitree(T->rchild);//递归先序创建右子树
    }
}

(中序和后序请读者认真思考一下这么敲吧!这里就不给出来了)

此时输入“ABC##DE#G##F###” 即可得到一颗二叉树,图如下(自己画的,比较丑,,,,)

在这里插入图片描述


复制二叉树:

void Copy(Bitree T, Bitree &newT)//新树newT
{
    if(T == NULL)
    {
        newT = NULL;
        return ;
    }
    else
    {
        newT = (BiTnode *)malloc(sizeof(BiTnode));
        newT->data = T->data;
        Copy(T->lchild, newT->lchild);//复制左子树
        Copy(T->rchild, newT->rchild);//复制右子树
    }
}

计算二叉树的深度:

int depth(Bitree T)
{
    int m, n;
    if(T == NULL)
        return 0;
    else 
    {
        m = depth(T->lchild);//搜左子树
        n = depth(T->rchild);//搜右子树
        return m>n ? m+1 : n+1;//加上根结点
    }
}

统计二叉树中结点的个数:

int Nodecount(Bitree T)
{
    if(T == NULL)//如果是空树,则结点个数为0,递归结束
        return 0;
    else 
        return Nodecount(T->lchild)+Nodecount(T->rchild)+1;
    // 否则结点个数为左子树的结点个数+右子树的结点个数+1(根结点)
}

求叶子结点的个数:

int yezi(Bitree T)
{
    int x = Nodecount(T);//先找根结点,如果不止一个结点的话
    if(x > 1)
        if(T == NULL)
            return 0;
        else if(T->lchild == NULL && T->rchild == NULL)//左右为空,证明的叶子结点,返回1.
            return 1;
        else
            return yezi(T->lchild)+yezi(T->rchild);
    else			//否则它就是根节点,无叶子结点
        return 0;
}

好了,恶心的递归就到此结束了,但是,算法肯定不止一种,而且你考研也不会让你递归写树或者遍历,所以,有一种用栈(stack)来模拟的,这个嘛,,我下次写吧,先用着递归。,,,,,,,,,哦,还有线索树。。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值