树与二叉树

                          树

1.基本概念:

  ①树是n(n>=0)个节点的集合T,当n==0时,称为空树;当n>0时,该集合满足以下条件

  ②必有个根节点,他没有直接前驱,有零个或多个后继。

  ③其余n-1个结点划分成m(m>=0)个互不相交的有限集。每一个称为根的子树,每个子树的根节点有且仅有一个直接前驱,但有零个或多个直接后继。

2.树的相关术语:

  1. 结点:包括一个数据元素及若干指向其结点的分支信息
  2. 结点的度:一个节点的子树个数(说白了就是节点拥有的子分支数)
  3. 叶节点度为0的结点,即无后继的结点,也称终端结点
  4. 分支结点:度不为零的结点,也称非终端结点
  5. 结点的层次:从根节点开始定义,根节点的层次为1,根的直接后继的层次为2,以此类推
  6. 节点的层序编号:将数中的结点按从上层到下层,同层从左到右的次序排成一个线性序列,把他们编成连续的自然数
  7. 树的度:树中所有结点的度的最大值
  8. 树的高度(深度):数中所有结点的层次的最大值
  9. 有序树:在树T中,如果个子树之间有先后次序的,则称为有序树
  10. 森林:m(m>=0)个互不相见交的树的集合,将一颗非空树的根节点删去,树就变成一个森林;繁殖给森林增加一个统一的根结点,森林就变成一棵树
  11. 同构:对两棵树,通过对结点是当地重命名,就可以使两棵树完全相等,(对应结点相等,对应结点的相关关系也相等),则称为两棵树的同构
  12. 孩子结点:一个结点的直接后继称为该结点的孩子结点
  13. 双亲结点:一个结点的直接前驱称为该结点的双亲结点
  14. 兄弟结点:同一双亲结点的孩子结点间互称兄弟结点
  15. 堂兄结点:父亲是兄弟关系或堂兄弟关系的陈伟堂兄弟结点
  16. 祖先结点:一个结点的祖先结点是指从根结点到该结点的路径上的所有结点
  17. 子孙结点:一个结点的直接后继和间接后继称为该节点的子孙结点
  18. 前辈:层号比该结点小的结点
  19. 后辈:层号比该结点大的结点

                          二叉树

定义:

  1. 每个结点的度都不大于二
  2. 每个结点的孩子节点的次序不能任意颠倒

性质1:

  二叉树的第i层上至多有2^i-1个结点

性质2:

  深度为k的二叉树至多有2^k-1个结点

性质3:

  对任意一棵二叉树T,若终端结点数为n,其度为2的结点数是N,则n=N+1

  树中的结点数等于树的边数加1,也等于所有结点的度数之和加1。

满二叉树

  深度为k且有2^k-1个结点的二叉树

  叶子必须位于最后一层,并且其他节点度为2

满二叉树的顺序表示:

  按从上层到下层,同层从左到右的的顺序逐层进行编号

扩充二叉树:

  除叶子节点外,其他节点度为2
  1,扩充二叉树的最大特点在于他的外路径长度=内路径的长度+2*非叶节点的数目
  2,典型应用就是哈弗曼编码

完全二叉树:

  深度为k,结点数为n的二叉树,如果结点1~n的位置序号分别于等高的满二叉树结点1~n的位置序号一一对应,则为完全二叉树

  将整个完全二叉树依照从左到右,从上到下的进行0-->n进行编号,若子节点序号为i,则父节点为(i-1)/2

  典型的应用大小堆的实现。

  满二叉树必为完全二叉树,完全二叉树不一定是满二叉树

性质4:

  具有n个结点的完全二叉树深度为(int)floor(log2n)+1

性质5:

  对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对二叉树的所有结点从1开始编号,则对于任意的序号i的结点有:

    ①如i==1,则序号为i的结点是根结点,无双亲结点;如i>1,则序号为i的节点的双亲结点序号为(int)floor(i/2)

    ②如2*i>n,则序号为i的结点无左孩子;2*1<=n,则序号为i的节点的左孩子的结点序号为2*i

    ③如2*i+1>n,则序号为i的结点无右孩子;2*i+1<=n,则序号为i的节点的右孩子的结点序号为2*i+1

 二叉树的创建,先序,中序,后序遍历,及各种操作代码如下:

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;//数据 
    struct Node *LChild;//左孩子 
    struct Node *RChild;//右孩子 
}BiTNode,*BiTree;
// 叶子数目  数的高度  层次 
int Leaf_Count=0,depth,nLayer;

//先序遍历创建二叉树,输入0结束的含义:比如输入:1(根结点)2(左子树)0(结束左子树的左子树输入)0(结束左子树的右子树输入)
void CreateBiTree(BiTree *bt)
{
    int ch;
    scanf("%d",&ch);
    if(ch==0)
        *bt=NULL;
    else
    {
        *bt=(BiTree)malloc(sizeof(BiTNode));
        (*bt)->data=ch;
        CreateBiTree(&((*bt)->LChild));
        CreateBiTree(&((*bt)->RChild));
    }
}
//先序打印二叉树 
void PreOrder(BiTree bt)
{
    if(bt)
    {
        printf("%d ",bt->data);
        PreOrder(bt->LChild);
        PreOrder(bt->RChild);
    }
}
//中序打印二叉树
void InOrder(BiTree bt) 
{
    if(bt)
    {
        InOrder(bt->LChild);
        printf("%d ",bt->data);
        InOrder(bt->RChild);
    }
}
//后序打印二叉树 
void PostOrder(BiTree bt)
{
    if(bt)
    {
        PostOrder(bt->LChild);
        PostOrder(bt->RChild);
        printf("%d ",bt->data);
    }
}
//先序输出二叉树的叶子结点
void Pre_Order(BiTree bt) 
{
    if(bt) 
    {
        if(bt->LChild==NULL&&bt->RChild==NULL)
            printf("%d ",bt->data);
        Pre_Order(bt->LChild);
        Pre_Order(bt->RChild);
    }
}
//输出叶子结点数目方法1.
void LeafCount(BiTree bt) 
{
    if(bt)
    {
        LeafCount(bt->LChild);
        LeafCount(bt->RChild);
        if(bt->LChild==NULL&&bt->RChild==NULL)
            Leaf_Count++;
    }
}
//输出叶子结点数目方法2.
int Leaf(BiTree bt) 
{
    int Leaf__Count;
    if(bt==NULL)//树为空, 
        Leaf__Count=0;
    //    return 0;
    else if(bt->LChild==NULL&&bt->RChild==NULL)//左孩子和右孩子都为空,则是叶子结点,若第一次遍历,则此节点为根节点 
        Leaf__Count=1;
        //return 1;
    else
        Leaf__Count=Leaf(bt->LChild)+Leaf(bt->RChild);
    return Leaf__Count;
}
//后序遍历二叉树的高度方法1. 
int PostTreeDepth(BiTree bt) 
{
    int hl,hr,max;
    if(bt)
    {
        hl=PostTreeDepth(bt->LChild);
        hr=PostTreeDepth(bt->RChild);
        max=hl>hr?hl:hr;
        return max+1;
    }
    else
        return 0;
}
//先序遍历二叉树的高度方法2. 
void PreTreeDepth(BiTree bt,int h)
{
    if(bt)
    {
        if(h>depth)
            depth=h;
        PreTreeDepth(bt->LChild,h+1);
        PreTreeDepth(bt->RChild,h+1);
    }
}
//树状竖向方向打印二叉树
void PrintTree(BiTree bt,int nLayer) 
{
    if(bt==NULL)
        return;
    PrintTree(bt->RChild,nLayer+1);
    for(int i=0;i<nLayer;i++)
        printf(" ");
    printf("%d\n",bt->data);
    PrintTree(bt->LChild,nLayer+1);
}

int main()
{
    BiTree bt;
//    int Leaf_Count=0;          局部变量与全局变量重名 
    printf("先序序创建二叉树输入零结束输入\n");
    CreateBiTree(&bt);
    
    printf("先序打印二叉树\n");
    PreOrder(bt);
    printf("\n");

    printf("中序打印二叉树\n");
    InOrder(bt);
    printf("\n");

    printf("中序打印二叉树\n");
    PostOrder(bt);
    printf("\n");
    
    printf("输出二叉树中的叶子结点\n");
    Pre_Order(bt);
    printf("\n");
    
    printf("后序遍历输出叶子结点数目方法1.\n");
    LeafCount(bt);
    printf("%d\n",::Leaf_Count);                //局部变量与全局变量重名是使用全局变量加:: 
    
    printf("后序遍历输出叶子结点数目方法2.\n");
    int num=Leaf(bt);
    printf("%d\n",num);
    
    printf("后序遍历二叉树的高度方法1.:\n");
    int height=PostTreeDepth(bt);
    printf("%d\n",height);
    
    printf("先序遍历二叉树的高度方法2.:\n");
    depth=0;                        //全局变量depth 
    int h=1;                        //h为bt指向节点所在的层次,初始值为1 
    PreTreeDepth(bt,h);
    printf("%d\n",depth);
    
    printf("树状竖向打印二叉树:\n");
    nLayer=0;
    PrintTree(bt,nLayer);
    printf("\n");
    
    free(bt);
    return 0;
}

转载于:https://www.cnblogs.com/tianzeng/p/9680838.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值