树的定义
树是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中:
1.有且仅有一个特定的称为根(Root)的结点
2.当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每一个集合本身又是一颗树,并且称为根的子树
结点的分类
树的结点包含一个数据元素及若干指向其子树的分支。
结点拥有的子树称为结点的度(Degree)。度为0的结点称为叶结点(Leaf)或终端结点;度不为0的结点称为非终端结点或分支结点。除根节点之外,分支结点也称为内部结点。树的度是树内各结点的度的最大值
结点间的关系
结点的子树的根称为该结点的孩子,相应地,该结点称为孩子的双亲(Parent)。
同一个双亲的孩子之间互称兄弟
结点的祖先是从根到该结点所经分支上的所有结点
以某一结点为根的子树中的任一结点都称为该结点的子孙
树的其他相关概念
结点的层次从根开始定义起,根为第一层,根的孩子为第二层
双亲在同一层的结点互为堂兄弟
树中结点的最大层次称为树的深度(Depth)或高度
如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树
森林(Forest)是m(m>=0)棵互不相交的树的集合
对比线性表与树的结构
线性结构 树结构
第一个数据元素:无前驱 根结点:无双亲,唯一
最后一个数据元素:无后继 叶节点:无孩子,可以多个
中间元素:一个前驱一个后继 中间结点:一个双亲多个孩子
二叉树(Binary Tree)
二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两颗互不相交的,分别称为根结点的左子树和右子树的二叉树组成。
二叉树的特点
  • 每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点,没有子树或者有一颗子树是可以的
  • 左子树和右子树是有顺序的,次序不能颠倒
  • 即使树中某结点只有一颗子树,也要区分它是左子树还是右子树

二叉树具有以下五种基本形态

  • 空二叉树
  • 只有一个根结点
  • 根节点只有左子树
  • 根结点只有右子树
  • 根节点既有左子树又有右子树

特殊二叉树

1.斜树

所有的结点都只有左子树的二叉树叫左斜树,所有结点都只有右子树的二叉树叫右斜树

2.满二叉树

在一颗二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树

  • 叶子只能出现在最下一层。出现在其他层就不可能达到平衡
  • 非叶子结点的度一定是2.
  • 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多
 3.完全二叉树
对一颗具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这课二叉树称为完全二叉树

完全二叉树的特点

  • 叶子结点只能出现在最下两层
  • 最下层的叶子一定集中在左部连续位置
  • 倒数第两层,若有叶子结点,一定都在右部连续位置
  • 如果结点度为1,则该结点只有左子树,即不存在只有右子树的情况
  • 同样结点数的二叉树,完全二叉树的深度最小
 判断是否完全二叉树方法:给每个二叉树结点按照满二叉树的结构逐层顺序编号,如果编号出现空档,就说明不是完全二叉树。
二叉树的性质
  1. 在二叉树的第i层至多有2i-1个结点(i>=1)
  2. 深度为k的二叉树至多有2k-1个结点(k>=1)
  3. 对任何一颗二叉树T,如果其终端结点数n0,度为2的结点数为n2,则n0=n2+1
  4. 具有n个结点的完全二叉树的深度为log2n+1
  5. 如果对一棵有n个结点的完全二叉树的结点按层序编号,对任一结点i(1<=i<=n)有:
    • 如果i=1,则结点j是二叉树的根,无双亲;如果i>1,则其双亲是结点i/2
    • 如果2i>n,则结点无左孩子,否则左孩子为2i
    • 如果2i+1>n,则结点无右孩子,否则其右孩子是结点2i+1

二叉树的建立

BTree CreateBTree()
{
    BTree bt = NULL;
    char ch;
    scanf("%c", &ch);
    if (ch != '#')
    {
        bt = new BTNode;
        bt->data = ch;
        bt->lChild = CreateBTree();
        bt->rChild = CreateBTree();
    }
    return bt;
}

二叉树的遍历

/*二叉树的前序遍历递归算法*/
void PreOrderTraverse(BiTree T)
{
    if(T==NULL)
    return;
    printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
    PreOrderTraverse(T->lchild);    /*再先序遍历左子树*/
    PreOrderTraverse(T->rchild);    /*最后先序遍历右子树*/
}


/*二叉树的中序遍历递归算法*/
void InOrderTraverse(BiTree T)
{
    if(T==NULL)
    return;
    InOrderTraverse(T->lchild); /*中序遍历左子树*/
    printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
    InOrderTraverse(T->rchild); /*最后中序遍历右子树*/
}


/*二叉树的后序遍历递归算法*/
void PostOrderTraverse(BiTree T)
{
    if(T==NULL)
    return;
    PostOrderTraverse(T->lchild);   /*先后序遍历左子树*/
    PostOrderTraverse(T->rchild);   /*再后续遍历右子树*/
    printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
}
posted @ 2022-02-27 21:56  夜灯长明  阅读(75)  评论(0)    收藏  举报