数据结构初阶 —— 树(二叉树)

2023-05-16

目录

一,二叉树

特殊二叉树

二叉树的性质

二叉树的存储结构 

 二,二叉树链式结构

二叉树的遍历(四种)

二叉树接口

试题


一,二叉树

  • 由一个根节点,加上两颗左二叉树和右二叉树组成,可以为空;
  • 二叉树度不大于2;
  • 二叉树子树有左右之分,次序不可颠倒,因此二叉树是有序树;

特殊二叉树

  • 满二叉树,若每层节点数都达到最大值,如有k层,则节点总数为2^{k}-1
  • 完全二叉树,如有k层,k-1层为满,最后一层从左到右为连续的二叉树;完全二叉树是效率很高的数据结构,是由满二叉树引出来的,满二叉树是特殊的完全二叉树;

二叉树的性质

  • 若根节点为1层,则一颗非空二叉树第k层上最多2^{k-1}个节点;
  • 若根节点为1层,则深度为h的二叉树最多2^{h} - 1个节点;
  • 若根节点为1层,则具有n个节点的满二叉树,其深度为
  • 任何一个二叉树,叶节点个数比度为2的节点数多1个;
  • 对于具有n个节点的二叉树,如按从上到下、从左到右的数组顺序对所有节点从0编号,则对序号为i的节点,如下:

二叉树的存储结构 

  •  一般可使用两种结构存储,顺序结构或链式结构;

顺序存储

  • 顺序存储即为数组存储,一般只适用表示完全二叉树,不完全二叉树会有空间浪费;
  • 实际使用中,只有(一种二叉树)才会使用数组来存储;
  • 物理上为数组,逻辑上是一颗二叉树;

注:这里的堆和虚拟进制地址空间中的堆是两回事,一个是数据结构,一个是管理内存的一块区域分段;

 链式存储

  • 用链表来表示元素的逻辑关系,通常链表中每个节点有三个域组成(数据域、左右指针域);
  • 链式结构可分为二叉链和三叉链;

//二叉链
typedef int BTDataType;
struct BinaryTreeNode
{
	struct BinaryTreeNode* _pLeft; //指向左孩子节点
	struct BinaryTreeNode* _pReft; //指向右孩子节点
	BTDataType _data; //值域
}BinaryTreeNode;
//三叉链
typedef int BTDataType;
struct BinaryTreeNode
{
    struct BinaryTreeNode* _pParent; //指向父节点
	struct BinaryTreeNode* _pLeft; //指向左孩子节点
	struct BinaryTreeNode* _pReft; //指向右孩子节点
	BTDataType _data; //值域
}BinaryTreeNode;

 二,二叉树链式结构

  • 普通二叉树的增删查改,意义不大;
  • 普通二叉树+搜索树规则,增删查改才有价值;
//二叉树链式结构
typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

//创建节点
BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("BuyNode");
		exit(-1);
	}
	node->_data = x;
	node->_left = node->_right = NULL;
	return node;
}

//自定义二叉树
BTNode* CreatBinaryTree()
{
	BTNode* nodeA = BuyNode('A');
	BTNode* nodeB = BuyNode('B');
	BTNode* nodeC = BuyNode('C');
	BTNode* nodeD = BuyNode('D');
	BTNode* nodeE = BuyNode('E');
	BTNode* nodeF = BuyNode('F');
	nodeA->_left = nodeB;
	nodeA->_right = nodeC;
	nodeB->_left = nodeD;
	nodeC->_left = nodeE;
	nodeC->_right = nodeF;
	return nodeA;
}

二叉树的遍历(四种)

  • 前序遍历,根 \rightarrow 左子树 \rightarrow 右子树;
  • 中序遍历,左子树 \rightarrow 根 \rightarrow 右子树;
  • 后序遍历,左子树 \rightarrow 右子树 \rightarrow 根;
  • 层序遍历,一层一层遍历;

注:深度优先遍历(前序、中序、后序),广度优先遍历(层序);

1,前序遍历

//前序遍历
void PreOrder(BTNode* root)
{
	if (root == NULL)
		return;
	printf("%c ", root->_data);
	PreOrder(root->_left);
	PreOrder(root->_right);
}

2,中序遍历

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
		return;
	InOrder(root->_left);
	printf("%c ", root->_data);
	InOrder(root->_right);
}

3,后序遍历

//后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
		return;
	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%c ", root->_data);
}

4,层序遍历

//层序遍历-利用队列
//一个节点出列,入列其子节点
typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
    QDataType data;
    struct QueueNode* next;
}QueueNode;
typedef struct Queue
{
    QueueNode* phead;
    QueueNode* ptail;   
}

void LevelOrder(BTNode* root)
{
    Queue q;
    QueueInit(&q);
    if(root)
        QueuePush(&q, root);
    while(!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        printf("%c ", front->val);
        if(front->left)
            QueuePush(&q, front->left);
        if(front->right)
            QueuePush(&q, front->right);
    }
    printf("\n");
    QueueDestroy(&q);
}

二叉树接口

//求二叉树节点个数-递归
//方法一,全局变量或static
int size = 0; 
void BinaryTreeSize(BTNode* root)
{
	if (root)
		size++;
	else
		return;
	BinaryTreeSize(root->_left);
	BinaryTreeSize(root->_right);
}

//方法二,局部变量-传址
void BinaryTreeSize(BTNode* root, int* psize)
{
	if (root)
		(*psize)++;
	else
		return;
	BinaryTreeSize(root->_left, psize);
	BinaryTreeSize(root->_right, psize);
}

//方法三,返回值
int BinaryTreeSize(BTNode* root)
{
	if (root)
		return 1 + BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right);
	else
		return 0;
}
//求二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->_left == NULL && root->_right == NULL)
		return 1;
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
//求二叉树第k层节点个数
//当前树第K层节点个数 = 其左子树的第K-1层节点个数 + 其右子树的第K-1层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}
//求二叉树深度
//当前树深度 = max(左子树深度, 右子树深度) + 1;
int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
		return 0;
	int leftDepth = BinaryTreeDepth(root->_left);
	int rightDepth = BinaryTreeDepth(root->_right);
	return leftDepth > rightDepth ? (1 + leftDepth) : (1 + rightDepth);
}
//二叉树查找值为x的节点
//先当前节点查找,没有,在去左子树查找,没有,在取右子树查找
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->_data == x)
		return root;

	BTNode* retLeft = BinaryTreeFind(root->_left, x);
	if (retLeft)
		return retLeft;

	BTNode* retRight = BinaryTreeFind(root->_right, x);
	if (retRight)
		return retRight;

	return NULL;
}
//二叉树的销毁
void BinaryTreeDestory(BTNode* root)
{
    if(root==NULL)
        return;
    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    free(root);
}
//判断二叉树是否是完全二叉树
//利用层序,空也入列,完全二叉树非空是连续的
bool BinaryTreeComplete(BTNode* root)
{
    Queue q;
    QueueInit(&q);
    if(root)
        QueuePush(&q, root);
    while(!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        if(front == NULL)
            break;
        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
    }
    while(!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        if(front)
        {
            QueueDestroy(&q);
            return false; 
        }
    }
    QueueDestroy(&q);
    return true;
}

试题

  • 二叉树的前序遍历(设置子程序);
  • 二叉树的中序变量(设置子程序);
  • 二叉树的后序遍历(设置子程序);
  • 单值二叉树;
  • 两颗树是否相等(时间复杂度O(N)、空间复杂度即高度O(N));
  • 另一颗树的子树;
  • 对称二叉树;
  • 根据指定前序遍历的字符串,重构此二叉树;

注:完全二叉树O(log(N));

(前序/后序:可得到根,中序:可得到左右树的区间)

  • 前序+中序,可重建树;
  • 后序+中序,可重建树;
  • 前序+后序,不可重建树;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构初阶 —— 树(二叉树) 的相关文章

  • 分治策略-归并排序

    问题 xff1a 数组排序 分治策略 归并排序 xff1a 1 是合并这些子问题的解 2 分解原问题 xff0c 递归求解 span class token comment coding utf 8 span span class toke
  • 求股票最大收益问题

    问题 xff1a 求股票最大收益 xff0c 股票每天的价格 xff1a 100 113 110 85 105 102 86 63 81 101 94 106 101 79 94 90 97 买进和卖出都在当天结束后进行 xff0c 在某一
  • Python pip 包的安装和卸载 使用。

    Python pip 包的安装和卸载 使用 xff08 一 xff09 pip 安装 一般 来说 Python 需要什么包 直接 pip install 包 即可 但是 这种方法太慢 因为他通过美国的服务器下载 提高 pip 速度 这里提供
  • jdk1.8安装和环境变量配置

    一 安装JDK 选择安装目录 安装过程中会出现两次 安装提示 第一次是安装 jdk xff0c 第二次是安装 jre 建议两个都安装在同一个java文件夹中的不同文件夹中 xff08 不能都安装在java文件夹的根目录下 xff0c jdk
  • python 读取PDF(tabula和pdfminer和pdfplumber的简单操作)

    一 pdfminer 读取PDF 官方文档 xff1a http www unixuser org euske python pdfminer 这里针对python3 1 模块安装 xff1a pip install i https pyp
  • 一区即将要洗的DVD片子

    101 Dalmatians Animated 2009 SE 101斑点狗 预计2009年发行特别版 12 Monkeys 05 10 2005 COM DOC 12只猴子 预计2005年5月10日发行扩展版 加评论和记录片等 2001
  • UML — 五大关系

    在UML教学视频中 xff0c 关系有四种 xff0c 而课本中有五种 xff0c 其实就是多加了一种 xff0c 那么下面我一并总结出来 1 关联关系 通俗点说就是关联关系就是两个对象他们之间的联系和关系 关联分两种 xff1a xff0
  • rhel6.5救援模式修复系统

    如果系统中很多重要的部分被删除了例如 boot下的所有东西 xff0c 则可以通过救援模式 root 64 dazzle1 桌面 mkdir backup root 64 dazzle1 桌面 cp etc fstab backup fst

随机推荐

  • 利用nvm安装npm失败的解决办法

    最近发现在安装nodejs后 xff0c 想使用npm发现自己的电脑上没有安装npm xff0c 可是网上都说安装了nodejs后会自动安装npm xff0c 找了很久解决办法发现没有合适的解决办法 xff0c 于是自己尝试了很久发现了问题
  • chrome 浏览器的缩略图怎么没有了?就是浏览过网页的缩略图,一点击就能打开网站。

    这个问题 xff0c 突然今天解决了 哈哈 分享 首先新标签页 点击左下角 最常访问的网站 点击 最常访问的网站 紧接着再点击被置顶端的 最常访问的网站 Ok xff0c 大功告成了 烦恼了几天的这个小功能 xff0c 有缩略图还是看着舒服
  • 史上最详细的PID教程——理解PID原理及优化算法

    Matlab动态PID仿真及PID知识梳理 云社区 华为云 huaweicloud com 位置式PID与增量式PID区别浅析 Z小旋 CSDN博客 增量式pid https zhuanlan zhihu com p 38337248 期望
  • ubuntu 20.04搭建samba文件共享服务器,实现基于Linux和Windows的共享文件服务

    ubuntu 20 04搭建samba文件共享服务器 xff0c 实现基于Linux和Windows的共享文件服务 超详细 一 xff0c samba的基本概念二 xff0c samba的安装三 xff0c samba的基本配置创建文件夹更
  • ERROR: Could not find a version that satisfies the requirement torchvision

    打docker时出错 xff0c ERROR Could not find a version that satisfies the requirement torchvision from versions 0 1 6 0 1 7 0 1
  • openstack 常用命令回顾及总结

    1 概述 命令实际执行基于OpenStack Queens版本 xff0c 更高版本亦可 xff0c 长时间未使用openstack有些遗忘 xff0c 整理后方便自己回顾学习 xff0c 仅供各位参考 xff0c 详细命令及参数可以参考o
  • TPMS方案 传感器 infineon篇 (SP35 SP37)

    TPMS方案 xff08 SP35 SP37 xff09 传感器 infineon篇 关于sp37无压力芯片目前已有方案 关于sp35传感器已经稳定出货 xff0c 欢迎咨询 硬件原理图 软件说明 xff1a 协议 调制方式 FSK 频率
  • sudo rosdep init 出现 ERROR: cannot download default sources list from:

    sudo rosdep init 出现 ERROR cannot download default sources list from 针对目前安装ROS出现一下指令的错误 span class token function sudo sp
  • 新装linux主机可以ping通,但是SSH无法登陆

    0 xff0c 新装一台linux主机 xff0c 可是ssh连接不上 xff0c 能ping通 怎么办呢 xff1f 1 xff0c 先查看一下防火墙状态 sudo ufw status 2 xff0c 关闭防火墙 sudo ufw di
  • tcp头以及ip头

    转自http www cnblogs com zzq919101 p 7866550 html 在网上找了很多有关tcp ip头部解析的资料 xff0c 都是类似于下面的结构 抽象出图文是这种结构 xff0c 但是在底层中数据到底是怎么传输
  • C++初阶 —— 入门/概念

    目录 一 xff0c 关键字 xff08 C 43 43 98 xff09 二 xff0c 命名空间 命名空间定义 命名空间使用 三 xff0c C 43 43 输入 输出 四 xff0c 缺省参数 五 xff0c 函数重载 六 xff0c
  • C++初阶 —— list类

    目录 一 xff0c list介绍 二 xff0c list的使用 构造函数 list iterator的使用 list capacity list element access list modifiers list迭代器失效 三 xff
  • C++初阶 —— stack/queue

    目录 一 xff0c 容器适配器 deque双端队列 二 xff0c stack栈 stack接口 stack模拟实现 三 xff0c queue队列 queue接口 queue模拟实现 四 xff0c priority queue优先级队
  • C++初阶 —— 模板进阶

    目录 一 xff0c 非类型模板参数 模板参数分类 二 xff0c 模板特化 函数模板特化 类模板特化 三 xff0c 模板分离编译 分离编译 链接失败原因 解决方法 附 模板优点 模板缺点 一 xff0c 非类型模板参数 模板参数分类 类
  • C++进阶 —— 哈希

    目录 一 xff0c 哈希的介绍 哈希的概念 哈希冲突 哈希函数 二 xff0c 哈希冲突解决 闭散列 开散列 开散列与闭散列比较 在C 43 43 98中 xff0c STL提供了底层为红黑树结构的一系列关联式容器 xff0c 查询效率可
  • Linux —— 基本指令

    目录 ls pwd cd touch mkdir rmdir rm man cp mv cat more less head tail grep date cal find zip unzip tar bc uname shutdown 附
  • Linux —— 目录结构

    转载与 xff1a Linux 系统目录结构 菜鸟教程 文件目录结构由 34 34 起始的树形结构 xff01 FHS xff08 filesystem hierarchy standard xff09 xff0c 文件系统层次化标准 xf
  • Linux —— 编译器gcc/g++

    目录 程序编译过程 gcc选项 函数库 GCC GNU Compiler Collection GUN 编译器集合 xff0c 它可以编译C C 43 43 JAV Fortran Pascal Object C Ada等语言 gcc是GC
  • 完全自学C(干货) —— 预处理详解

    目录 一 xff0c 预定义符号 二 xff0c define define定义的标识符 define定义宏 和 带副作用的宏参数 宏和函数的对比 undef 三 xff0c 命令行定义 四 xff0c 条件编译 五 xff0c 文件包含
  • 数据结构初阶 —— 树(二叉树)

    目录 一 xff0c 二叉树 特殊二叉树 二叉树的性质 二叉树的存储结构 二 xff0c 二叉树链式结构 二叉树的遍历 xff08 四种 xff09 二叉树接口 试题 一 xff0c 二叉树 由一个根节点 xff0c 加上两颗左二叉树和右二