408数据结构学习笔记——树、二叉树

简介: 408数据结构学习笔记——树、二叉树

1.树的基本概念f2f3599064bc47f9af124672b64f65ee.png

  1. 根节点:有且仅有一个
  2. 分支节点:有后继的节点
  3. 叶子节点:没有后继的节点
  4. 除根节点外,所有节点有且仅有一个前驱(与图相对)
  5. 子树:除根节点外,可以分为m个互不相交的集合(例:BEFKL、CG、DHIJM)
  6. 祖先节点:根A到结点K的从上往下的唯一路径上的任意结点,例:B是K的祖先结点
  7. 子孙结点:根A到结点K的从上往下的唯一路径上的任意结点,例:K是B的子孙结点
  8. 双亲结点(父结点):某结点的前驱。例:E是K的双亲结点,B是F的双亲结点
  9. 孩子结点:某结点的后继。例:K是E的孩子结点,F是B的孩子结点
  10. 兄弟结点:同一层上的结点。例如:E是F的兄弟结点,K是L的兄弟结点
  11. 路径:两个结点之间所经过的结点序列(单向,且由上往下,B到L有路径,而B到D没路径
  12. 路径长度:路径上所经过的边的个数
  13. 结点的层次:由上往下,A是1层,B是2层,E是3层,K是4层
  14. 结点的高度:由下往上,K是1层,E是2层,B是3层,A是4层。特别地,F也是2层
  15. 树的高度:根节点的高度,即总共多少层
  16. 结点的度:有几个孩子结点。E的度为2,K的度为0,A的度为3。特别地,度为0时,结点为叶子结点;度>0时,结点为分支结点
  17. 树的度:各个结点中度数最大的值
  18. 森林:n棵互不相交的树的集合,森林和树可以相互转换(添加根节点)

2.树的性质

  1. 结点数 = 总度数 + 1(除根节点外,每个结点都有一条边指向其前驱)
  2. 度为m的树和m叉树
  1. 相同点:允许结点的度 ≤ m

         b.不同点:m叉树的结点度数可以都<m,但是度为m的树至少有一个节点的度 = m;m叉树可以为空树,度为m的树至少有m + 1个结点(根节点 + m个叶子节点)

3.度为m的树第 i 层至多有gif.gif个结点(最多情况下:第一层为根节点,结点数1,即gif.gif;第二层为m个结点,即gif.gif第二层为gif.gif以此类推)

4.高度为h的m叉树至多又gif.gif个结点(等比数列求和)

5.高度为h的m叉树最少有h个结点;高度为h的度为m的树最少有 h + m - 1 个结点(设最后一个结点为 m,高度为 h,m + h - 1,- 1 为减去最后一个结点的高度)

3.二叉树

3.1.二叉树

3.1.1.二叉树的基本概念

  1. 二叉树由根节点和左右子树构成
  2. 每个结点至多有两个子树(注意区别度为2的树)
  3. 有序树(左右子树不能颠倒)
  4. 可以是个空树

3.1.2.二叉树的性质

设二叉树中度为0、度为1、度为2的结点个数分别为a、b、c,则a = c + 1

  1. 设 n 为结点总个数
  2. n = 0 * a + 1 * b + 2 * c + 1(结点个数 = 总度数 + 1)
  3. n = a + b + c(结点个数相加得到总个数)
  4. b + 2c + 1 = a + b + c → a = c + 1

3.2.满二叉树

  1. 除了叶结点外,所有结点都有左右子树


2.设高度为 h,共gif.gif 个结点

3.按层序编号,根节点为1,则结点 i 的左孩子为2i,右孩子为2i + 1,父结点为⌊ i / 2⌋


7d961a8e04124859b04871e85d3cc955.png

3.3.完全二叉树

3.3.1.完全二叉树的概念

  1. 当且仅当其每个结点都与高度为 h 的二叉树中编号为1 - n 的节点一一对应
  2. 只有可能有一个度为1的叶子结点(在倒数第二层)
  3. 叶子结点出现在最后两层
  4. 按层序编号,根节点为1,则结点 i 的左孩子为2i,右孩子为2i + 1,父结点为⌊ i / 2⌋
  5. i ≤ ⌊ n / 2⌋为分支节点 i > ⌊ n / 2 ⌋为叶子结点

dd5b63e7ee0b46268128173c3e9c2c7b.png

3.3.2.完全二叉树的性质

  1. 具有 n 个结点的完全二叉树的高度 h 为⌈gif.gif⌉ 或 gif.gif⌋ + 1

    1. 第 h - 1 层的完全二叉树的结点个数为gif.gif

   2. 第 h 层的完全二叉树的结点个数为gif.gif

   3.gif.gif

    4.gif.gif

2.设度为0的结点个数为a,度为1的结点个数为b,度为2的结点个数为c,完全二叉树可以推出a、b和c的值

   1. 在二叉树中,a = c + 1(二叉树的性质),因此,a + c必为奇数

    2.完全二叉树中度为1的结点个数最大为1(即b = 1 或 0)

    3.设总结点个数为2k(偶数):a + c为奇数→b = 1→a = k、c = k - 1

    4.设总结点个数为2k - 1(奇数):a + c为奇数→b=0→a = k,c = k - 1

3.5.二叉排序树

  1. 左子树的所有结点的关键字都小于根节点
  2. 右子树的所有结点的关键字都大于根节点
  3. 左右子树依然是二叉排序树

b576ce8f37b24066af4bd9235bc3fe9a.png

3.6.平衡二叉树

  1. 树上任意一个结点的左右子树的深度差不超过1
  2. 平衡二叉树具有更高的搜索效率

8e18ed6b42d4438cb20f17a58c8da237.png

4.二叉树的存储结构

4.1.二叉树的顺序存储

#define MAXSIZE 100
typedef struct treeNode{
    elemType value;    //结点中元素的值
    bool isEmpty;    //结点是否为空
}treeNode;
//申明一个长度为MAXSIZE的结构体数组
//由上至下、从左至右的方式存放完全二叉树的各个结点数据
treeNode T[MAXSIZE];
//初始化时,把结点置空
for(int i = 0; i < MAXSIZE; i++) T[i].isEmpty = true;
  1. 为了方便存储,从数组下标1开始存储数据。
  2. 树的顺序存储通常只用于存储完全二叉树(普通二叉树采用顺序存储的方式跟完全二叉树一样,但是采用这种方式的代价是浪费大量存储空间)

4.2.二叉树的链式存储

typedef struct BiTNode{
    elemtype value;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
//定义一个空树
BiTree root = NULL;
//插入根结点
root = (BiTNode*)malloc(sizeof(BiTNode));
root->data = {1};
root->lchild = NULL;
root->rchild = NULL;
//插入新结点
BiTNode *p = (BiTNode*)malloc(sizeof(BiTNode));
p->data = {2}
p->lchild = NULL;
p->rchild = NULL;
root->lchild = p;    //作为根结点的左孩子
  1. n个节点的二叉链表共有n + 1个空指针域
  1. 总共n个节点,除了头结点,每个节点都被一个指针指着
  2. 2n个指针就有n-1个指针不是空指针
  3. 2n-(n-1)= n + 1
  1. 普通二叉树的链式存储中,找其双亲结点只能通过从根节点重新遍历树寻找,如果经常需要找到某个结点的父亲节点,可以增加一个指针指向双亲结点(三叉链表)
typedef struct BiTNode{
    struct BiTNode *parent, *lchild, *rchild;
    elemType value;
}BiTNode, *BiTree;

5.王道课后题

68dd84c307944dffa703a8df1c4e67bc.png

  1. 设度为0的结点个数为a,度为1的结点个数为b,度为c的结点个数为c
  2. 当b = 1时:

      1.a = c + 1,总结点个数为 0 * a + 1 * b + 2 * c + 1 = 2a

      2.高度为gif.gif向上取整

3.当b = 0时:

  1. a = c + 1,总结点个数为 0 * a + 1 * b + 2 * c + 1 = 2a - 1
  2. 高度为gif.gif向上取整

9878fbde9a3249a7af4d196d1a2dada7.png

  1. 设度为0的结点个数为a,度为1的结点个数为b,度为c的结点个数为c,总结点个数为n
  2. 度为0的结点,即叶子结点
  3. 度为2的结点,即分支节点
  4. a = c + 1 → c = a - 1
  5. 满二叉树 → b = 0
  6. n = a + b + c → n = 2a - 1 → a = (n + 1) / 2 即 叶子结点 = (n + 1) / 2
  7. n = a + b + c → n = 2c + 1 → c = (n - 1) / 2 即 分支节点 = (n - 1) / 2
  8. 高度gif.gif向上取整

3edb93a1655f430882c0d1f39f4b50ad.png

  1. 整个完全二叉树295个结点
  1. 前八层的总数为255
  2. 第九层的结点个数240
  1. 叶子结点的个数为248个
  1. 第九层为完全二叉树的最后一层,其结点都为叶子结点,即240个
  2. 第八层的结点共128个,其分支节点的个数为第九层的一半,即120个,剩下的都是叶子结点,即8个

db1779c5c8be476d99f4584b84909b09.png

#define MAXSIZE 100
typedef struct treeNode{
    elemType value;
    bool isEmpty;
}treeNode;
treeNode T[MAXSIZE];
elemType commonParent(treeNode T, int p, int q){
    //寻找公共结点
    while (p != q){
        //谁大谁找双亲结点
        if (p > q) p /= 2;
        else q /= 2;
    }
    return T[p].value;
}


相关文章
|
9天前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
45 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
9天前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
34 12
|
9天前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
33 10
|
9天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
31 2
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
281 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
43 1
|
9天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
125 75
|
9天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
34 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
9天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
34 9
|
9天前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
27 7

热门文章

最新文章