数据结构——树和二叉树

目录

引子:树

树的一些基本定义

树的重要类型——二叉树

 二叉树几种常见类型

二叉树的一些基本性质

二叉树的存储

利用数组存储

利用链表存储

二叉树的遍历

先序遍历(递归)

 中序遍历(递归)

 后序遍历(递归)

层序遍历(非递归)

 二叉树的遍历总结


 

引子:树

要讲二叉树,我们先来引进树的概念。

树类似于多分枝链表,由>=0个节点所组成。当只有0个节点时成为空树;有大于0个节点的称为非空树。

非空树的性质

  1. 树中有一个称为“根”的特殊节点,一般用r表示。
  2. 其余结点可以分为很多不相交的有限集,其中每个集合本身又可以被称为树,称为原来的子树。

树的一些基本定义

  1. 结点的度:结点的子树个数。
  2. 树的度°:树的所有节点中最大的度数。
  3. 叶结点:度°为0的结点。
  4. 父节点:有子树的结点时其子树的根结点的父结点。
  5. 兄弟结点:具有同一个父结点的彼此。
  6. 路径和路径长度:即结点与结点之间的连接处称为一个路径,边的个数即为路径长度。
  7. 祖先节点:沿着树根到某一结点路径上所有节点都是这个结点的祖先结点。
  8. 结点的层次:根节点在第一层,下面的节点所在层数都依次+1.
  9. 树的深度:树中所有结点中,最大层次的就是这颗树的深度。

树的重要类型——二叉树

二叉树就是所有结点最多连两个子结点的树。这里的一个结点包含三个内容:一个是结点所含内容,俩个是指向下一个结点的指针。

如图所示,这是二叉树的一个示例图。

8cfa61895acb4c66a41440a1f9c0e979.png

 二叉树几种常见类型

1. 斜二叉树:即只有左支或右支。(其实相当于一个链表)。

2. 完美二叉树(满二叉树):每个节点的子节点都满2。

3.完全二叉树:每一行从左往右没有空的,但是不一定是完美二叉树。

f8a66e1746574030b2e8cbe6857360f5.png

 该图中,第一张是完全二叉树,但不是完美二叉树。

二叉树的一些基本性质

  1. 一个二叉树第i层的最大结点数为:2^(i-1)。
  2. 深度为k的二叉树有最大节点总数为:(2^k)-1。
  3. 对于任何非空二叉树,如果a表示叶结点的个数,b表示度为非叶结点的个数,那么两者关系满足a=b+1。

二叉树的存储

主要方法有两种,一种是利用数组,一种是利用链表。

利用数组存储

完全二叉树可以利用数组存储 ,因为直接一排一排按照序号存储很方便。我们找规律可以发现,一个子节点,如果他的序号是奇数就-1除以二,如果是偶数就直接除以二,结果就是其父节点序号。

利用链表存储

可以很好的存储任何类型的二叉树。

二叉树的遍历

方法主要分为四类:先序遍历、中序遍历、后序遍历、层序遍历。其中前三个店铺使用递归的方法,层序遍历不适用递归。

先序遍历(递归)

  1. 访问根节点。
  2. 先序遍历左子树。
  3. 先序遍历右子树。
//这里的代码是c语言,你也可以认为是抽象代码
void preordertraversal(bintree BT)
{
    if(BT){
            printf("%d",BT->data);
            preordertraversal(BT->left);
            preordertraversal(BT->right);
          }
}

图解如下。这个数字就是访问的先后顺序。

58a00fbca77c41798d3bfeaaf26189c6.png

 中序遍历(递归)

  1. 左子树
  2. 右子树
//这里的代码是c语言,你也可以认为是抽象代码
void inordertraversal(bintree BT)
{
    if(BT){
        inordertraversal(BT->left);
        printf("%d",BT->data);
        inordertraversal(BT->right);
          }
}

图解如下

3c722946ebdd459f8bb2f9db7afd0ea8.png

 后序遍历(递归)

  1. 左子树
  2. 右子树
//这里的代码是c语言,你也可以认为是抽象代码
void preordertraversal(bintree BT)
{
    if(BT){
            preordertraversal(BT->left);
            preordertraversal(BT->right);
            printf("%d",BT->data);
          }
}

图解如下

88e0eaf4249e4d7b8f79da8b38227c01.png

层序遍历(非递归)

我们使用队列来实现层序遍历。

  1. 从队列中取出一个元素。
  2. 访问该元素所指的左右子结点。
  3. 如果这个元素所指结点的左右子结点非空,则将左右子结点的指针排序入队。
void levelordertraversal(bintree BT)
{
    queue q;
    bintree t;
    if(!BT) return;
    q=creatqueue(maxsize);
    addq(q,BT);
    while(!iseptyq(q))
    {
        t=delete(q);
        printf("%d",BT->data);
        if(t->left) addq(q,t->left);
        if(t->right) addq(q,t->right);
    }
}

 二叉树的遍历总结

6cdad89c1cb74dc6849dcfd5e0481b6b.png

 如图,以上是三种遍历方法的先后访问路径,×代表先序遍历路径,⭐代表中序遍历,▲代表后序遍历。(不包括层序遍历)。

 

本文中所有代码都可以看作抽象代码

以上内容如果有错误欢迎指正

就酱,拜拜

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值