数据结构第三周笔记——树(上)(慕课浙大版本--XiaoYu)(二)

简介: 数据结构第三周笔记——树(上)(慕课浙大版本--XiaoYu)(二)

二叉树及存储结构


3.2.1 二叉树的定义及性质


二叉树的定义


  二叉树T:一个有穷的结点集合
​   这个集合可以为空
    若不为空,则它是由根结点和称为其左子树TL和右子树TR的两个不相交的二叉树组成(L和R是下标)


二叉树具体五种基本形态


网络异常,图片无法展示
|


二叉树的子树有左右之分


网络异常,图片无法展示
|


特殊的二叉树


斜二叉树(Skewed Binary Tree)


  1. 只有左边或者只有右边,相当于一个链表
  2. 网络异常,图片无法展示
    |


完美二叉树(Perfect Binary Tree)


或者叫做满二叉树(Full Binary Tree)


网络异常,图片无法展示
|


特点: 一个深度为k(>=-1)且有2^(k+1) - 1个结点的二叉树称为完美二叉树。 满二叉树


完全二叉树(Complete Binary Tree)


有n个结点的二叉树,对树种结点按从上到下,从左到右的顺序进行编号,编号为i(1 <= i <= n)结点与满二叉树中编号为i结点在二叉树中位置相同
跟上方的区别就是除了最底下一层可以右边缺一点,上面跟满二叉树是一样的。最底下一层左边顺序不能乱


二叉树的几个重要性质


网络异常,图片无法展示
|


叶结点的总数等于有两个儿子的结点的总数加1

有一颗二叉树,其两个儿子的结点个数为15个,一个儿子的结点个数为32个,问该二叉树的叶结点个数是多少?
16


二叉树的抽象数据类型定义


类型名称:二叉树
数据对象集:一个有穷的结点集合。
  若不为空,则由根结点和其左、右二叉子树组成。
操作集: BT属于BinTree,Item属于ElementType
重要操作有:
1.Boolean IsEmpty(BinTree BT):判别BT是否为空;
2.void Traversal(BinTree BT):遍历,按某顺序访问每个结点;(重要)
3.BinTree CreateBinTree():创建一个二叉树
常用的遍历方法
1.void PreOrderTraversal(BinTree BT)://先序--根、左子树、右子树
2.void InOrderTraversal(BinTree BT)://中序--左子树、根、右子树
3.void PostOrderTraversal(BinTree BT)://后序--左子树、右子树、根
4.void LevelOrderTraversal(BinTree BT)://层次遍历(层序遍历,从上到下、从左到右

3.2.2 二叉树的存储结构


1.顺序存储结构


完全二叉树:按从上至下,从左到右顺序存储n个结点的完全二叉树的结点父子关系;
//这个树最适合数组方式解决

网络异常,图片无法展示
|


  1. 非根结点(序号 i > 1)的父节点的序号是[i/2]
  1. 这句话的意思就是说假设我们目前知道M结点时6,如果想知道它的父节点就是6/2=3,Q结点就是7/2=3.5,把小数去掉,父节点一样是3
  1. 结点(序号为i)的左孩子结点的序号是2i,(若2i <= n,否则没有左孩子)
  1. 举例:意思就是B左孩子是C,O的左孩子是M
  1. 结点(序号为i)的右孩子结点的序号是2i+1,(若2i+1 <= n,否则没有右孩子)
  1. 举例:类似上方的意思B右孩子是S...


一般二叉树也可以采用这种结构,缺点:但会造成空间浪费....(将缺少的结点补上一个空结点)


网络异常,图片无法展示
|


网络异常,图片无法展示
|

问题:
如果参照完全二叉树的表示方法用数组存储下面这棵二叉树,那么结点e所对应的数组下标是多少(树根下标为1)?
答案:6

网络异常,图片无法展示
|


2.链表存储


网络异常,图片无法展示
|


typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
}


网络异常,图片无法展示
|


二叉树的遍历


3.3.1 先序中序后序遍历


二叉树的遍历


(1)先序遍历
遍历过程为:
1.访问根节点
2.先序遍历其左子树
3.先序遍历其右子树 
对应的递归程序:
void PreOrderTraversal(BinTree BT)//BT是树
{
    if( BT ){//看树是不是空的,空的就退出去,不空就访问根节点
        printf("d",BT->Data);
        PreOrderTraversal(BT->Left);//指向左子树的那个根节点的地址进行递归
        PreOrderTraversal(BT->Right);//指向右子树的那个根节点的地址进行递归
    }
}


网络异常,图片无法展示
|


先是从根开始  A(B D F E)(C G H I)
先序遍历=>A B D F E C G H I
(2)中序遍历


遍历过程为:
1.中序遍历其左子树
2.访问根结点;
3.中序遍历其右子树 
对应的递归程序:
void PreOrderTraversal(BinTree BT)//BT是树
{
    if( BT ){//看树是不是空的,空的就退出去,不空就访问根节点
        PreOrderTraversal(BT->Left);//指向左子树的那个根节点的地址进行递归
        printf("d",BT->Data);
        PreOrderTraversal(BT->Right);//指向右子树的那个根节点的地址进行递归
    }
}

网络异常,图片无法展示
|


中序遍历 => D B E F A G H C I
(D B E F) A ( G H C I)
先是左边再右边,这里我原本的疑问是为什么是先E在F而不是先F再E
原因是E-F是一个树,然后因为这个是左子树,所以从左边开始,E在F的左边


网络异常,图片无法展示
|


(3)后序遍历
遍历过程为:
1.后序遍历其左子树
2.中序遍历其右子树 
3.访问根结点
对应的递归程序:
void PreOrderTraversal(BinTree BT)//BT是树
{
    if( BT ){//看树是不是空的,空的就退出去,不空就访问根节点
        PreOrderTraversal(BT->Left);//指向左子树的那个根节点的地址进行递归
        PreOrderTraversal(BT->Right);//指向右子树的那个根节点的地址进行递归
        printf("d",BT->Data);
    }
}

网络异常,图片无法展示
|


注意点:后序遍历,那当然得从下面开始咯,所以会发现B跟E是E优先。H跟C比是H优先
 (D E F B)(H G I C) A
 后序遍历 => D E F B H G I C A


总结


先序、中序和后序遍历过程:遍历过程中经过结点的路线一样,只是访问各结点的时机不同
图中先从入口到出口的曲线上用三种符号分别标记除先序,中序和后序的访问各结点时刻


网络异常,图片无法展示
|


3.3.2 中序非递归遍历


二叉树的非递归遍历


中序遍历非递归遍历算法


非递归算法实现的基本思路:使用堆栈


这里建议看视频的演示,非常形象


1.遇到一个结点,就把它压栈,并去遍历它的左子树;
2.当左子树遍历结束后,从栈顶弹出这个结点并访问它;
3.然后按其右指针再去中序遍历该结点的右子树
以下是完整代码实现演示
void InOrderTraversal(BinTree BT)
{
    BinTree T = BT;//把BT赋给临时变量T
    Stack S = CreateStack(MaxSize);//创建并初始化堆栈
    while(T || !IsEmpty(S) ){//树不空且堆栈不空
        while(T){//判断堆栈空不空
            //一直向左并将沿途结点压入堆栈
            Push(S,T);//把T压入堆栈S中
            T = T->Left;//然后把T往左挪,就是边挪边把结点压到堆栈里面去,压到底T为NULL就退出来
        }
        if(!IsEmpty(S)){
            T = Pop(S);//结点弹出堆栈
            printf("%5d",T->Data);//(访问)打印结点
            T = T->Right;//转向右子树
        }
    }
}
ppoopoppoo错误
PPOPOOPPOO正确
    第二次碰到同一个的时候就print出来


网络异常,图片无法展示
|


先序遍历的非递归遍历算法?


把上方那个算法中if中的printf("%5d",T->Data)移到while(T)中Push的后面


后序遍历非递归遍历算法?
目录
相关文章
|
3月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
80 0
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
63 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
50 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
49 10
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
54 2
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
103 5
|
3月前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
94 0
|
3月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
356 9
|
3月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
58 1
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
145 77