『数据结构与算法』解读树(Tree)和二叉树(Binary Tree)!

文章目录

  • 一. 树
    • 1.1. 树的定义
    • 1.2. 树的基本术语
    • 1.3. 树的性质
  • 二. 二叉树
    • 2.1. 二叉树的定义
    • 2.2. 几种特殊的二叉树
    • 2.3. 二叉树的性质
    • 2.4. 二叉树的存储结构
      • 2.4.1. 二叉树的顺序存储结构
      • 2.4.2. 二叉树的链式存储结构
    • 2.5. 本节总结
  • 三. 二叉树的遍历
    • 3.1. 二叉树遍历的概念
    • 3.2. 前序中序后序层次遍历
    • 3.3. 二叉树遍历(前序,中序,后序)递归算法(C++)
    • 3.4. 二叉树的构造(通过遍历)
  • 四. 二叉树的基本运算及其实现(c++)
    • 4.1. 创建二叉树
    • 4.2. 销毁二叉树
    • 4.3. 查找节点
    • 4.4. 找孩子节点(左或右)
    • 4.5. 求树的高度
    • 4.6. 输出二叉树
    • 4.7. 代码总结
  • 五. 线索二叉树
    • 5.1. 线索二叉树的概念
    • 5.2. 线索化二叉树
    • 5.3. 遍历线索化二叉树
  • 六. 哈夫曼树
    • 6.1. 哈夫曼树的定义
    • 6.2. 构造哈夫曼树
    • 6.3. 哈夫曼树编码
  • 七. 以上内容总结
    • 7.1. 二叉树遍历
    • 7.2. 二叉树构造
    • 7.3. 线索二叉树
    • 7.4. 哈夫曼树

之前解读的内容如下:

  • 『数据结构与算法』解读链表!
  • 『数据结构与算法』解读栈(Stack)和队列(Queue)!

一. 树

1.1. 树的定义

树是 n(n≥0)n(n \geq 0)n(n0)个节点的有限集。当 n=0n = 0n=0 时,称为空树。在任意一颗非空树中应满足:

  • ①有且仅有一个特定的称为根的结点。
  • ②当 n>1n>1n>1 时, 其余节点可分为 m(m>0)m (m > 0)m(m>0个互不相交的有限集 T1,…,TmT_1,…, T_mT1,,Tm , 其中每个集合本身又是一颗树,并且称为根的子树。

显然,树的定义是递归的,即在树的定义中又用到了其自身,树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:

  • ①树的根结点没有前驱, 除根结点外的所有结点有且只有一个前驱。
  • ②树中所有结点可以有零个或多个后继。

树适合于表示具有层次结构的数据。树中的某个结点(除根结点)最多只和上一层的一个结点(即其父结点)有直接关系,根结点没有直接上层结点,因此在 nnn 个结点的树中有 n−1n -1n1条边。 而树中每个结点与其下一层的零个或多个结点(即其子女结点〉有直接关系。

1.2. 树的基本术语

1、节点的度与树的度: 树中一个节点的子树个数称为该节点的度 。树中各节点的度最大值称为树的度,通常将度为 mmm 的树称为 mmm 次树或者 mmm 叉树

2、分支节点与叶节点: 度不为零的节点称非终端,又叫分支节点。度为零的节点称终端或叶节点 (或叶子节点)。度为1的节点称为单分支节点;度为2的节点称为双分支节点,依此类推。

3、路径与路径长度: 两个节点 did_ididjd_jdj 的节点序列(di,di1,di2,…,dj)(d_i,d_{i1},d_{i2},…,d_j)(didi1di2,,dj) 称为路径。其中<dx,dy><d_{x}, \ d_{y}><dx,dy>是分支。路径长度等于路径所通过的节点数目减1(即路径上分支数目)。

4、孩子节点 、双亲节点和兄弟节点: 在一棵树中 ,每个节点的后继,被称作该节点的孩子节点(或子女节点 )。相应地 ,该节点被称作孩子节点的双亲节点(或父母节点)。具有同一双亲的孩子节点互为兄弟节点

5、子孙节点和祖先节点: 在一棵树中 ,一个节点的所有子树中节点称为该节点的子孙节点 。从根节点到达一个的路径上经过所有被称作该祖先节点

6、节点的层次和树高度: 树中的每个节点都处在一个层次上。 节点的层次从树根开始定义,根节点第1层,它的孩子节点为第2层,以此类推,一个节点所在的层次为其双亲节点所在的层次为其双亲加1。树中节点的最大层次称为树高度 (或树的深度)

7、有序树和无序树: 若树中各节点的子树是按照一定次序从左 向右安排的,且相对次序是不能随意变换的,则称为有序树,否则称为无序树

8、森林: n(n>0)n(n>0)n(n0) 个互不相交的树集合称为森林。

1.3. 树的性质

二. 二叉树

2.1. 二叉树的定义

递归定义: 二叉树是有限的节点集合。

  • 这个集合或者是空。
  • 或者由一个根节点和两棵互不相交的左子树和右子树的二叉树组成。

二叉树与度为2的有序树的区别:(二叉树是有序树,若将其左、右子树颠倒, 则成为另一棵不同的二叉树)

  • ①度为2的树至少有3个结点,而二叉树可以为空。
  • ②度为2的有序树的孩子的左右次序是相对于另一孩子而言的, 若某个结点只有一个孩子,则这个孩子就无须区分其左右次序,而二叉树无论其孩子数是否为2 ,均需确定其左右次序,即二叉树的结点次序不是相对于另一结点而言, 而是确定的。

2.2. 几种特殊的二叉树

二又排序树。左子树上所有结点的关键字均小于根结点的关键字: 右子树上的所有结点的关键宇均大于根结点的关键宇; 左子树和l右子树又各是一棵二叉排序树。

平衡二又树。树上任一结点的左子树和右子树的深度之差不超过1。

2.3. 二叉树的性质

性质5: 具有 n(n>0)n(n>0)n(n>0) 个节点的完全二叉树的高度为 ⌈log⁡2(n+1)⌉\left\lceil\log _{2}(n+1)\right\rceillog2(n+1) 或者 ⌊log⁡2n⌋+1\left\lfloor\log _{2} n\right\rfloor+1log2n+1证明如下:

2.4. 二叉树的存储结构

2.4.1. 二叉树的顺序存储结构

2.4.2. 二叉树的链式存储结构

typedef int ElemType;
typedef struct node
{ElemType data;struct node *lchild, *rchild;
}BTNode;

2.5. 本节总结

  • nnn 个不同的节点构造的二叉树的个数?

  • ② 二叉树中节点计算方法
  • ③ 完全二叉树中节点计算方法

  • ④ 满二叉树中节点计算方法

  • ① 二叉树的顺序存储结构
  • ② 二叉树的链式存储结构

三. 二叉树的遍历

3.1. 二叉树遍历的概念

3.2. 前序中序后序层次遍历

  • 1、前序遍历
  • 2、中序遍历
  • 3、后序遍历
  • 4、层次遍历
  • 快速写遍历的方法:

3.3. 二叉树遍历(前序,中序,后序)递归算法(C++)

#include <iostream>
#define MaxSize 50
using namespace std;
//二叉树节点(结构体定义)
typedef char ElemType;
typedef struct node
{ElemType data;struct node *lchild, *rchild;
} BTNode;
//======================= 创建二叉树 =========================
void createBTNode(BTNode *&b, char *str) //由str===>二叉链b
{//我们设置一个栈,这里采用顺序栈实现;BTNode *St[MaxSize], *p;int top = -1, k, j = 0;char ch;  //字符b = NULL; //建立的二叉链初始时为空ch = str[j];while (ch != '\0') //str未扫描完时循环{switch (ch){case '(':top++;       //栈顶指针上移St[top] = p; //进栈k = 1;break;case ')':top--;break;case ',':k = 2;break;default: //遇到节点值p = (BTNode *)malloc(sizeof(BTNode));p->data = ch;p->lchild = p->rchild = NULL; //左右子树都设置为空if (b == NULL)                //一个节点都没创建,此时p为二叉树根节点;b = p;else //已经建立二叉树根节点{switch (k) //判断左右子树{case 1:St[top]->lchild = p;break;case 2:St[top]->rchild = p;break;}}}j++;ch = str[j]; //继续扫描str;}
}
//============================ 1. 前序递归算法 =========================
void preOrder(BTNode *b)
{if (b != NULL){cout << b->data; //访问根节点;preOrder(b->lchild);preOrder(b->rchild);}
}
//============================ 2. 中序递归算法 =========================
void inOrder(BTNode *b)
{if (b != NULL){inOrder(b->lchild);cout << b->data; //访问根节点;inOrder(b->rchild);}
}
//============================ 3. 后序递归算法 =========================
void postOrder(BTNode *b)
{if (b != NULL){postOrder(b->lchild);postOrder(b->rchild);cout << b->data; //访问根节点;}
}
int main()
{BTNode *btree = new BTNode;char a[] = "A(B(D(,G)),C(E,F))"; //字符数组createBTNode(btree, a);//1、先序遍历cout << "================================1.preOrder: " << endl;preOrder(btree);//2、中序遍历cout << "\n================================2.InOrder: " << endl;inOrder(btree);//3、后序遍历cout << "\n================================3.postOrder: " << endl;postOrder(btree);cout << endl;system("pause");return 0;
}

三种遍历输出结果:

================================1.preOrder:
ABDGCEF
================================2.InOrder:
DGBAECF
================================3.postOrder:
GDBEFCA
请按任意键继续. . .

3.4. 二叉树的构造(通过遍历)

由二叉树的先序序列和中序序列可以唯一地确定一棵二叉树。

  • 在先序遍历序列中,第一个结点一定是二叉树的根结点;而在中序遍历中,根结点必然将中序序列分割成两个子序列,前一个子序列是根结点的左子树的中序序列,后一个子序列是根结点的右子树的中序序列。根据这两个子序列,在先序序列中找到对应的左子序列和右子序列。在先序序列中, 左子序列的第一个结点是左子树的根结点,右子序列的第一个结点是右子树的根结点。如此递归地进行下去,便能唯一地确定这棵二叉树。

同理,由二叉树的后序序列和中序序列也可以唯一地确定一棵二叉树。

  • 因为后序序列的最后一个结点就如同先序序列的第一个结点,可以将中序序列分割成两个子序列,然后来用类似的方法递归地进行划分,进而得到一棵二叉树。

由二叉树的层序序列和中序序列也可以唯一地确定一棵二叉树,实现方法留给读者思考。

  • 需要注意的是,若只知道二叉树的先序序列和后序序列,则无法唯一确定一棵二叉树。

四. 二叉树的基本运算及其实现(c++)

4.1. 创建二叉树

创建二叉树

#include <iostream>
#define MaxSize 50
using namespace std;
//二叉树节点(结构体定义)
typedef char ElemType;
typedef struct node
{ElemType data;struct node *lchild, *rchild;
} BTNode;
//========================================1、创建二叉树
void createBTNode(BTNode *&b, char *str) //由str===>二叉链b
{//我们设置一个栈,这里采用顺序栈实现;BTNode *St[MaxSize], *p;int top = -1, k, j = 0;char ch;  //字符b = NULL; //建立的二叉链初始时为空ch = str[j];while (ch != '\0') //str未扫描完时循环{switch (ch){case '(':top++;       //栈顶指针上移St[top] = p; //进栈k = 1;break;case ')':top--;break;case ',':k = 2;break;default: //遇到节点值p = (BTNode *)malloc(sizeof(BTNode));p->data = ch;p->lchild = p->rchild = NULL; //左右子树都设置为空if (b == NULL)                //一个节点都没创建,此时p为二叉树根节点;b = p;else //已经建立二叉树根节点{switch (k) //判断左右子树{case 1:St[top]->lchild = p;break;case 2:St[top]->rchild = p;break;}}}j++;ch = str[j]; //继续扫描str;}
}
//========================================2、打印二叉树
void dispBTNode(BTNode *b)
{if (b != NULL){cout << b->data;if (b->lchild != NULL || b->rchild != NULL){cout << "(";dispBTNode(b->lchild);if (b->rchild != NULL) //递归处理左子树;cout << ",";dispBTNode(b->rchild); //递归处理右子树;cout << ")" << endl;}}
}int main()
{BTNode *btree = new BTNode;char a[] = "A(B(D(,G)),C(E,F))"; //字符数组createBTNode(btree, a);dispBTNode(btree);system("pause");return 0;
}
A(B(D(,G)),C(E,F))
请按任意键继续. . .

4.2. 销毁二叉树

//========================================3、销毁二叉树
void destroyBT(BTNode *&b) //指针的引用
{if (b == NULL)return;else{destroyBT(b->lchild);destroyBT(b->rchild);free(b); //剩下一个节点*b, 直接释放;}
}

4.3. 查找节点

//========================================4、查找节点
BTNode *findNode(BTNode *b, ElemType x) //返回指针类型;
{BTNode *p;if (b == NULL)return NULL;else if (b->data == x)return b;else{p = findNode(b->lchild, x);if (p != NULL)return p;else{return findNode(b->rchild, x);}}
}

4.4. 找孩子节点(左或右)

//========================================5、找孩子节点
BTNode *lchildNode(BTNode *p)
{return p->lchild;
}
BTNode *rchildNode(BTNode *p)
{return p->rchild;
}

4.5. 求树的高度

//========================================6、求树的高度
int btNodeDepth(BTNode *b)
{int lchildDep, rchildDep;if (b == NULL) //空数的高度为0return 0;else{lchildDep = btNodeDepth(b->lchild); //求左子树的高度rchildDep = btNodeDepth(b->rchild); //求右子树的高度return (lchildDep > rchildDep) ? (lchildDep + 1) : (rchildDep + 1);}
}

4.6. 输出二叉树

//========================================2、输出二叉树
void dispBTNode(BTNode *b)
{if (b != NULL){cout << b->data;if (b->lchild != NULL || b->rchild != NULL){cout << "(";dispBTNode(b->lchild);if (b->rchild != NULL) //递归处理左子树;cout << ",";dispBTNode(b->rchild); //递归处理右子树;cout << ")";}}
}

4.7. 代码总结

#include <iostream>
#define MaxSize 50
using namespace std;
//二叉树节点(结构体定义)
typedef char ElemType;
typedef struct node
{ElemType data;struct node *lchild, *rchild;
} BTNode;
//========================================1、创建二叉树
void createBTNode(BTNode *&b, char *str) //由str===>二叉链b
{//我们设置一个栈,这里采用顺序栈实现;BTNode *St[MaxSize], *p;int top = -1, k, j = 0;char ch;  //字符b = NULL; //建立的二叉链初始时为空ch = str[j];while (ch != '\0') //str未扫描完时循环{switch (ch){case '(':top++;       //栈顶指针上移St[top] = p; //进栈k = 1;break;case ')':top--;break;case ',':k = 2;break;default: //遇到节点值p = (BTNode *)malloc(sizeof(BTNode));p->data = ch;p->lchild = p->rchild = NULL; //左右子树都设置为空if (b == NULL)                //一个节点都没创建,此时p为二叉树根节点;b = p;else //已经建立二叉树根节点{switch (k) //判断左右子树{case 1:St[top]->lchild = p;break;case 2:St[top]->rchild = p;break;}}}j++;ch = str[j]; //继续扫描str;}
}
//========================================2、输出二叉树
void dispBTNode(BTNode *b)
{if (b != NULL){cout << b->data;if (b->lchild != NULL || b->rchild != NULL){cout << "(";dispBTNode(b->lchild);if (b->rchild != NULL) //递归处理左子树;cout << ",";dispBTNode(b->rchild); //递归处理右子树;cout << ")";}}
}
//========================================3、销毁二叉树
void destroyBT(BTNode *&b) //指针的引用
{if (b == NULL)return;else{destroyBT(b->lchild);destroyBT(b->rchild);free(b); //剩下一个节点*b, 直接释放;}
}//========================================4、查找节点
BTNode *findNode(BTNode *b, ElemType x) //返回指针类型;
{BTNode *p;if (b == NULL)return NULL;else if (b->data == x)return b;else{p = findNode(b->lchild, x);if (p != NULL)return p;else{return findNode(b->rchild, x);}}
}
//========================================5、找孩子节点
BTNode *lchildNode(BTNode *p)
{return p->lchild;
}
BTNode *rchildNode(BTNode *p)
{return p->rchild;
}//========================================6、求树的高度
int btNodeDepth(BTNode *b)
{int lchildDep, rchildDep;if (b == NULL) //空数的高度为0return 0;else{lchildDep = btNodeDepth(b->lchild); //求左子树的高度rchildDep = btNodeDepth(b->rchild); //求右子树的高度return (lchildDep > rchildDep) ? (lchildDep + 1) : (rchildDep + 1);}
}int main()
{BTNode *btree = new BTNode;char a[] = "A(B(D(,G)),C(E,F))"; //字符数组cout << "====================1. createBTNode ==========================" << endl;createBTNode(btree, a);cout << "====================2. dispBTNode ==========================" << endl;dispBTNode(btree);cout << "\n====================3. btNodeDepth ==========================" << endl;cout << "\ndepth of tree: " << btNodeDepth(btree) << endl;cout << "====================4. findNode ==========================" << endl;ElemType find = 'D';BTNode *p;p = findNode(btree, find);cout << p->data << endl;cout << "====================5. destroyBT ==========================" << endl;destroyBT(btree);system("pause");return 0;
}

运行结果:

====================1. createBTNode ==========================
====================2. dispBTNode ==========================
A(B(D(,G)),C(E,F))
====================3. btNodeDepth ==========================depth of tree: 4
====================4. findNode ==========================
D
====================5. destroyBT ==========================
请按任意键继续. . .

五. 线索二叉树

5.1. 线索二叉树的概念

回顾:

相关概念:

5.2. 线索化二叉树

线索二叉树过程

5.3. 遍历线索化二叉树

中序线索二叉树的中序遍历示例演示!

六. 哈夫曼树

6.1. 哈夫曼树的定义

6.2. 构造哈夫曼树

6.3. 哈夫曼树编码

建立哈夫曼树示例的演示!

七. 以上内容总结

7.1. 二叉树遍历

  • 例子1:
  • 例子2:

7.2. 二叉树构造

7.3. 线索二叉树

7.4. 哈夫曼树

  • 最后提醒: 以上代码会持续的更新中!

『数据结构与算法』解读树(Tree)和二叉树(Binary Tree)!相关推荐

  1. 由任意二叉树的前序遍历序列和中序遍历序列求二叉树的思想方法_算法与数据结构基础 - 二叉树(Binary Tree)...

    二叉树基础 满足这样性质的树称为二叉树:空树或节点最多有两个子树,称为左子树.右子树, 左右子树节点同样最多有两个子树. 二叉树是递归定义的,因而常用递归/DFS的思想处理二叉树相关问题,例如Leet ...

  2. 废柴日记6:迟到的『构造最小生成树算法』③

    ================================================= 废柴日记6:迟到一个月的『构造最小生成树算法』· 其三 ====================== ...

  3. 废柴日记7:迟到的『构造最小生成树算法』④

    ================================================= 废柴日记7:迟到的『构造最小生成树算法』· 其四(完结撒花) =================== ...

  4. 数据结构与算法之2-3-4树

    数据结构与算法之2-3-4树 原文来自个人博客(求访问/关注/收藏): https://bbing.com.cn/ CSDN个人博客不定期转载 平衡树 [外链图片转存失败,源站可能有防盗链机制,建议将 ...

  5. 【数据结构】二叉树 (Binary Tree)

    目录 一. 什么是树? 二. 二叉树 特殊二叉树 二叉树的性质 二叉树的存储 二叉树的遍历 二叉树的基本操作 一.什么是树? 之前咱们学习了一些简单的数据结构,如顺序表,链表,这些都是线性结构,线性结 ...

  6. 二叉树 Binary Tree

    我怀着激动的心 走上了这颗树 今天是2021年11月12日 今天开始上树!!!!!! 生活中的树形结构: 树:  根节点: 一棵树有且只有一个根节点就是最上面的节点 兄弟节点: 每一行的节点  它们具 ...

  7. js遍历树节点下的所有子节点_【数据结构与算法】(3)——树和二叉树

    树 树的基本概念 树是一种非线性的数据结构,样子如图所示: 树的主要特点是树中的数据是分层存储的,每个元素称为树的节点,最顶层有且只有一个元素,称为根节点,其余层可以有任意数量的节点.除了根节点,其余 ...

  8. 数据结构与算法一览(树、图、排序算法、搜索算法等)- Review

    算法基础简介 - OI Wiki (oi-wiki.org) 文章目录 1. 数据结构介绍 1.1 什么是数据结构 1.2 数据结构分类 2. 链表.栈.队列:略 3. 哈希表:略 4. 树 4.1 ...

  9. 数据结构与算法学习笔记-树和二叉树

    声明:本博客仅为本人学习途中做的笔记 采自青岛大学王卓老师的视频教学 主要内容为算法思路,具体代码实现还需修改后才能运行,望各位看官多多包涵,您的点赞与评论是对我最大的肯定! 1.树和二叉树的定义 数 ...

最新文章

  1. 三年 Git 使用心得 常见问题整理
  2. Android性能优化之App应用启动分析与优化
  3. Knative 应用在阿里云容器服务上的最佳实践
  4. STL常用对象,不会搞得C++跟没学一样
  5. Go_笔试题记录-指针与值类型实现接口的区别
  6. 冲刺阶段 day 6
  7. iphone固件降级_手机资讯:降级必备:Phone5如何下载备份SHSH文件
  8. 11款样式新颖的 jQuery/CSS3 网页菜单
  9. java 日期 yyyy_java日期中YYYY与yyyy的区别
  10. python 爬虫生成csv文件和图_python爬虫系列(4.2-python操作csv文件)
  11. 编写自己的tomcat, 并运行tomcat源码于eclipse中
  12. 《SAP CRM管理与实施指南》一一2.1 SAP CRM基础数据管理
  13. 佟年计算机大赛,佟年成电竞高手,老韩带老婆打比赛,solo内网被佟年轻松攻破...
  14. 过招多家大厂提炼的iOS面试心经(答案版)
  15. 电脑发送打印任务后打印机没有执行是怎么回事
  16. 【论文泛读76】将来自bert的提取信息和多种嵌入方法与深度神经网络集成在一起,以进行幽默检测
  17. 口红机 抖音口红机 女神赢口红系统源码 全开源可二次开发 微信游戏,公众号游戏,口红机源码安装部署、调试...
  18. 【日语】日语商务情景口语
  19. 【Java】抽象类继承的综合案例
  20. matlab 循环平稳检测,循环平稳信号处理完整的Matlab工具箱

热门文章

  1. 年份的读法与读数字不同
  2. 解决Ubuntu16.04软件商店无法加载
  3. OpenHD---低成本开源高清数字图传
  4. RESTful介绍(应用场合、常见的注解)
  5. C语言学习纯纯小白-1,C语言代码开头为什么要有#include <stdio.h>
  6. 【人工智能】未来三年(2018-2020),我们在新一代人工智能产业能做什么
  7. java研发网页数据采集
  8. html加入图片如何自动平铺,css怎么让图片平铺?
  9. Splunklive!2018北京站激情开场:合格的大数据处理平台到底是什么样子?
  10. “中国天眼”启动地外文明搜索,真的能找到吗?