二叉树

内容简介

  • 二叉树
  • 完全二叉树
  • 二叉树的性质
  • 二叉树的抽象数据类型
  • 二叉树的顺序存储结构
  • 二叉树顺序存储结构基本操作
  • 二叉树的链式存储结构
  • 二叉树链式存储结构的基本操作
  • 遍历二叉树
  • 前序二叉树
  • 中序二叉树
  • 后序二叉树
  • 层序二叉树
  • DOS命令查看文件夹目录树

  • 逻辑结构
    在这里插入图片描述

  • 树的定义:
    在这里插入图片描述
    树是n个结点的有限集
    结点个数为零的树为空树
    结点个数大于零的树为非空树

    • 非空树中:

      有且仅有一个特定的结点称为根结点
      非根的结点可分为互不相交的有限集,每个集合本身又是一棵树,这些树称为根的树

  • 结点分类
    在这里插入图片描述
    根节点: 没有前驱结点只有后继结点
    叶结点: 只有前驱结点没有后继结点
    分支结点:结点的度不为零的结点
    度: 结点下方挂接结点的个数
    树的度:所有结点中最大的度
    树的深度:树的最大层数

  • 有序树
    在这里插入图片描述

  • 无序树
    在这里插入图片描述

二叉树

  • 二叉树的定义:

    • 二叉树(Binary Tree)是n(n>=0)个节点所构成的集合,
    • 它或为空树(n=0),
    • 或为非空树(n >= 0),
      在这里插入图片描述
      对于非空树T:
      • 有且仅有一个称之为根的结点
      • 除根以外的其余结点分为两个互不相交的子集T1和T2,分别称为T的左子树和右子树,且T1和T2本身又都是二叉树

    二叉树的特点及树的异同
    在这里插入图片描述
    为何要重点研究二叉树?

    • 二叉树的结构最简单,规律性最强
    • 可以证明,所有树都能转为唯一对应的二叉树,不失一般性
  • 二叉树的各种形态
    在这里插入图片描述
    三节点二叉树的五种形态
    在这里插入图片描述

完全二叉树

  • 满二叉树和完全二叉树
    在这里插入图片描述
    将右边的完全二叉树移到左边满二叉树上,观察
    在这里插入图片描述
    示例:判断完全二叉树
    在这里插入图片描述
  • 完全二叉树的特点
    在这里插入图片描述

二叉树的性质

  • 性质1:在二叉树的第i层上至多有2(i-1)个节点
    在这里插入图片描述

  • 性质2:深度为k的二叉树至多有2(k-1)个结点
    在这里插入图片描述

  • 性质3:对于任何一棵二叉树,若2度的结点数有n2个,则叶子结点数n0必定为n2+1个,即n0=n2+1

    证明:
    在这里插入图片描述在这里插入图片描述

  • 性质4:具有n个结点的完全二叉树的深度必为[log2n]+1([ ]表示取整)
    在这里插入图片描述

  • 性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i的结点,其左支树编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为[i/2]。
    在这里插入图片描述

  • 性质小结:
    性质1:在二叉树的第i层上至多有2i-1个结点
    性质2:深度为k的二叉树至多有2k-1个结点
    性质3:任何一颗二叉树,若2度的结点数有n2个,则椰子树n0必定为n2+1个(即n0=n2+1)
    性质4:具有n个结点的完全二叉树的深度为[log2n]+1
    性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i的结点,其左孩子编号为2i,其右孩子编号为2i+1;其双亲的编号必为[i/2]

二叉树的抽象数据类型

  • 抽象数据类型

     ADT BinaryTree
    Data D是具有相同特性的数据元素的集合
    Relative
        若D =(空集),则R = ⊙;
        若D ≠ ⊙,则R={H};   
        //存在二元关系:
        1.root 唯一       //关于根的说明
        2.Dj ∩ Dk =//关于子树不相交的说明
        3. ......         //关于数据元素的说明
        4. ......         //关于左子树和右子树的说明
    Operation
        createBiTree(&T,defination);    //构建二叉树
        preOrderTraverse(T);            //先序遍历
        inOrderTraverse(T);             //中序遍历
        postOrderTraverse(T);           //后序遍历
        levelOrderTraverse(T);          //层序遍历
         ......                         //其他操作
    endADT
    

二叉树的顺序存储结构

  • 顺序存储结构示意图
    在这里插入图片描述
    特点:
    1.结点间关系蕴含在其存储位置中
    2.浪费空间,适于存满二叉树和完全二叉树
    • 最坏的情况,一个深度为k且只有k个结点的单支树(不存在度为2的结点)却需要2k-1长度的一维数组
      在这里插入图片描述
  • 创建顺序二叉树
    在这里插入图片描述

二叉树顺序存储结构基本操作

/** 初始化空二叉树 */
void InitSeqTree(SeqTree tree)
{
    //将字符数组中的每个元素都设置为空字符
    for(int i = 0; i < MAX_SIZE; i++)
    {
        tree[i] = '\0';
    }
}

/** 创建完全二叉树,i为数组中的下标 */
void CreateSeqTree(SeqTree tree, int i)
{
    char ch;
    ch = getchar();
    fflush(stdin);
    if(ch == '^')   //输入^符号表示结束当前结点的输入
    {
        tree[i] = '\0';
        return;
    }
    tree[i] = ch;   //如果没有执行return
    //某个结点输入完毕后,还需要让用户输入左支树结点和右支树结点
    printf("左支树结点:");
    CreateSeqTree(tree, 2 * i + 1);     //递归调用
    printf("右支树结点:");
    CreateSeqTree(tree, 2 *(i + 1));
}

/** 获取输的根节点元素 */
char GetSeqTreeRoot(SeqTree tree)
{
    return tree[0];
}

/** 获取树的结点总数 */
int GetSeqTreeLength(SeqTree tree)
{
    /*
     * 如果从头部开始遍历,中间会存在'\0'导致计算长度中断,算出的不是最终结果
     * 正确的方式应该是:从尾部找非'\0'的叶结点,排除尾部所有的'\0',剩下的就是二叉树顺序存储的总结点数
     */
     int len;
     for(len = MAX_SIZE; len >= 1; len--)
     {
        if(tree[len-1] != '\0')
            break;
     }
     return len;
}

/** 获取树的深度 */
int GetSeqTreeDepth(SeqTree tree)
{
    //性质2:深度为k的二叉树最多有2^k - 1个结点
    int depth = 0;
    int len = GetSeqTreeLength(tree);
    while((int)pow(2, depth) - 1 < len)
    {
        depth++;
    }
    return depth;
}

二叉树的链式存储结构

  • 二叉链表的存储结构示意图:
    在这里插入图片描述
    注意:在含有n个结点的二叉链表中有n+1个空链域,利用这些空链域可以存储其他有用信息,从而得到另一种链式存储结构——线索链表

  • 三叉链表的存储结构示意图:
    在这里插入图片描述

  • 创建链式二叉树
    在这里插入图片描述

二叉树链式存储结构的基本操作

#define NAME_SIZE   255
/** 数据元素 */
typedef struct
{
    int id;
    char name[NAME_SIZE];
}ElementType;
	
/** 树结点 */
typedef struct TreeNode
{
    ElementType data;           //树结点的数据域
    struct TreeNode * left;     //左子树
    struct TreeNode * right;    //右子树
}TreeNode;	

/** 二叉链表 */
typedef struct
{
    TreeNode * root;    //二叉链的根节点
    int length;         //二叉链表结点的总数
    int depth;          //二叉链表的深度
    int diameter;       //直径 - 从叶结点到叶结点的最长路径(某些考试会涉及)
}BinaryTree;

/** 初始化空二叉树 */
void InitBinaryTree(BinaryTree * tree)
{
    tree->root = NULL;
    tree->depth = 0;
    tree->diameter = 0;
    tree->length = 0;
}

/** 构造二叉树 - (外部需要事先对结点分配内存); 创建成功返回0,创建失败返回1 */
static int id = 0;  //用来实现结点id的自增长

int CreateBinaryTree(TreeNode * root)
{
    if(!root) return 0;   //根结点如果为空,就退出创建过程
    char inputName[NAME_SIZE];  //用户输入的结点名
    gets(inputName);    //用户输入回车表示结束当前子树的创建
    if(strcmp(inputName, "\0") == 0)  return 0;
    //创建当前结点
    root->data.id = ++id;
    strcpy(root->data.name, inputName);
    //为输入左右结点做准备 - 为左右结点指针分配内存
    root->left = (TreeNode *)malloc(sizeof(TreeNode));
    root->right = (TreeNode *)malloc(sizeof(TreeNode));
    //分别递归创建左子树和右子树
    printf("左结点:");
    if(CreateBinaryTree(root->left) == 0)
    {
        //不再创建这个结点则销毁刚分配的结点内存
        free(root->left);
        root->left = NULL;
    }
    printf("右结点:");
    if(CreateBinaryTree(root->right) == 0)
    {
        free(root->right);
        root->right = NULL;
    }
    return 1;
}

遍历二叉树

  • 遍历:按某条搜索路线遍访每个结点且不重复(又称周游)
  • 作用:
    是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核心
  • 遍历二叉树
    从根节点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点均被访问一次且仅被访问一次

前序遍历

特点:第一位一定是根节点
在这里插入图片描述

/** 前序遍历 -- 可以记作:根-左-右 */
void PreOrderTraverse(TreeNode * node)
{
    //先访问根结点,然后遍历左子树,最后遍历右子树
    if(node)
    {
        printf("[%d, %s]-", node->data.id, node->data.name);
        PreOrderTraverse(node->left);
        PreOrderTraverse(node->right);
    }
}

中序遍历

特点:根节点一定在中间
在这里插入图片描述

/** 中序遍历:左-根-右 */
void InOrderTraverse(TreeNode * node)
{
    if(node)
    {
        InOrderTraverse(node->left);
        printf("[%d, %s]-", node->data.id, node->data.name);
        InOrderTraverse(node->right);
    }
}

后序遍历

特点:最后一位一定是根节点
在这里插入图片描述

/** 后序遍历 */
void PostOrderTraverse(TreeNode * node)
{
    if(node)
    {
        PostOrderTraverse(node->left);
        PostOrderTraverse(node->right);
        printf("[%d, %s]-", node->data.id, node->data.name);
    }
}

层序遍历

特点:自上而下,从左往右
在这里插入图片描述
层序遍历的特点决定了它需要队列技术实现
在这里插入图片描述

文件夹目录树–DOS命令查看

文件资源管理器中输入cmd,然后回车
在这里插入图片描述
输入tree /f 回车(注意:只输入tree,只显示文件夹名字,不显示具体文件名)
在这里插入图片描述
输入 D:/info.txt 会在D盘下生成该文件目录树的 .txt文件
在这里插入图片描述
在这里插入图片描述
根文件目录树

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值