数据结构与算法——树和二叉树简介

树和二叉树

基本术语

结点:树的数据元素;

结点的度:结点上分支出的子树个数;一个树中最大的结点的度称为树的度。

叶子:度为0的结点,又称为终端结点

孩子:结点的子树的根,称为该结点的孩子

双亲:对应于孩子结点的上层结点称为这个结点的双亲

兄弟:同一双亲的孩子之间互称为兄弟

结点的层次:从根结点算起,根为第一层,其他结点的层次等于它的双亲的层次加1

深度:或称为高度,是树中结点的最大层次,

森林:是n(大于等于0)棵互不相交的树的集合。

树(Tree)是一种由多个节点组成的有限集合T,有且仅有一个节点称为根(root),其余结点分为m(大于等于0)个互不相交的有限集合T1,T2,T3...;每个集合本身又是棵树,被称为这个根的子树

在树的定义中规定了树含有结点数必须大于0,这表明空集不可以称为树;他又规定结点可以为1,该结点就是根节点。

树的存储结构

1. 结点异构型

根据结点的子树数设置相应的指针域,同时在结点的数据中再增加一个表示结点的度的域,以了解这个结点具有的指针域。

2. 结点同构型

以这棵树的度作为结点的指针域数目,每个结点的长度一样,但是树中很多结点的度小于树的度,导致存储浪费。

二叉树

二叉树是n(大于等于0)个结点的有限集合,它或是空树,或是有一个根节点,以及两棵互不相交的,分别称为左子树和右子树的二叉树组成。

满二叉树

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

  • 叶子只能出现在最下一层。出现在其它层就不可能达成平衡。
  • 非叶子结点的度一定是2。
  • 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多

完全二叉树

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

二叉树的基本性质

1. 二叉树的第i层至多有2^(n-1)个结点;

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

3. 对任意一颗二叉树,若2度结点数为N2 ,则叶子数为 N0 = N2 + 1;

完全二叉树的重要性质:

4. 在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[x]是向下取整。

5. 若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点有如下特性:

(1) 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 [i/2] 的结点为其双亲结点;
(2) 若 2i>n,则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;
(3) 若 2i+1>n,则该结点无右孩子结点, 否则,编号为2i+1 的结点为其右孩子结点。

二叉树和树的区别

二叉树不是树的特殊情况,尽管树和二叉树之间有许多关系,但是他们是两个概念,区别如下:

  1. 不包含任何结点的空树也是一颗二叉树,和树的定义不一样,树的结点必须大于0
  2. 二叉树的子树是有序的,他有左子树和右子树之分,且不能随意颠倒
  3. 二叉树至多有两个孩子
  4. 二叉树中某结点即使只有一棵子树,也要区分它是左子树还是右子树

二叉树的存储结构

1. 顺序存储结构

二叉树的顺序存储结构就是使用一维数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标索引。

a. 完全二叉树的顺序存储

b. 非完全二叉树的顺序存储

2. 链式存储结构

常用的链式存储为二叉链表,链表中的每个结点为:

二叉链表的示意图:

 

二叉树的遍历

typedef struct node{
              int data;
              stuct node* lchild;
              stuct node* rchild;
       }NODE;

1. 先序遍历

先访问根节点,后先序左子树,再先序右子树

上图的输出:A  ---->  B   ---->  D ------> E -------> C

算法:

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

2. 中序遍历

       先中序遍历左子树,后访问根节点,再中序遍历右子树

       上图的输出:D  ---->  B   ---->  E ------> A -------> C

       算法:     

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

3. 后序遍历

      先后序遍历左子树,然后后序遍历右子树,再访问根节点

      上图输出:D  ---->  E   ---->  B ------> C -------> A

      算法:

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

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值