【数据结构实践】手把手带你快速实现自定义二叉树

简介: 什么是树在学习二叉树之前.我们先来了解什么是树,跟我们现实生活中的树有什么联系,又有什么区别,树是一种很简单的结构,他是非线性的结构.在这种结构中,所有的元素之间的关系具有明显的层次特性,节点(Node)是树的基本构成部分,每个节点只有一个前件,成为父节点,没前件的父节点只有一个,那就是树的根节点(Root).每个节点可以有多个后件,这就是树的子节点(Children).没有后件(没有子节点)的节点称为叶子节点(Leaf Node),在树结构中,一个节点拥有的后件(子节点)个数称为节点的度,最大的度称为树的度,最大的层次(Level)称为树的深度(Height).

前言

什么是树

在学习二叉树之前.我们先来了解什么是树,跟我们现实生活中的树有什么联系,又有什么区别,树是一种很简单的结构,他是非线性的结构.在这种结构中,所有的元素之间的关系具有明显的层次特性,节点(Node)是树的基本构成部分,每个节点只有一个前件,成为父节点,没前件的父节点只有一个,那就是树的根节点(Root).每个节点可以有多个后件,这就是树的子节点(Children).没有后件(没有子节点)的节点称为叶子节点(Leaf Node),在树结构中,一个节点拥有的后件(子节点)个数称为节点的,最大的度称为树的,最大的层次(Level)称为树的深度(Height).

关于树的相关的还有其他的相关的概念:

边(Edge):也是树的基本构成部分。边连接两个节点,并表示它们之间存在联系。每个节点(除了根节点)都有且只有一条与其他节点相连的入边(指向该节点的边),每个节点可能有许多条出边(从该节点指向其他节点的边)。

路径(Path):是由边连接起来的节点的有序排列。例如:动物界 → 脊索动物门 → 哺乳动物纲 → 食肉动物目 → 犬科 →  猎犬.... 就是一条路径。

子节点集(Children):当一个节点的入边来自另一个节点时,称前者是后者的子节点。同一个节点的所有子节点构成子节点集。

兄弟节点(Sibling):同一个节点的所有子节点互为兄弟节点。

子树(Subtree):是一个父节点的某个子节点的所有边和后代节点所构成的集合

可以想象成我们现实生活中所看到的树,只不过计算机数据结构中所说的树是倒过来的,现实生活中的树根部在下:

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

而计算机数据结构中的树根部在上面,下图:

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

什么是二叉树

我们认识了树,接着我们介绍我们今天的主角--二叉树的相关概念.

二叉树是一种特殊的树,具有以下特点:

  1. 每个节点最多只能拥有两颗子树,即每个节点的度最多为2
  2. 二叉树的子树有左右之分,即左子树和右子树
  3. 单子树也要区分左右子树

二叉树有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空:如下图:

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

二叉树的基本性质

  1. 在二叉树的第k层上,最多2^k-1个节点,其中k>=1
  2. 深度为m的二叉树最多有2^m-1个节点,其中m>=1
  3. 在任意一颗二叉树中,度数为0的节点比度数为2的节点多一个
  4. 有n个节点的二叉树,其深度至少为log2(n+1)

满二叉树

除了最后一层,每层上的所有节点都有两个子节点,如果一颗树深度为d,最大层数为k,它的叶子数是: 2^d,第k层的节点数是: 2^(k-1),总节点数是: 2^k-1 (2的k次方减一),总节点数一定是奇数。如下图:

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

完全二叉树

除最后一层外,每一层上的节点数均达到最大值,叶子节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树,如下图:

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

二叉树的遍历

  • 前序遍历<DLR>:先访问根节点,再遍历左子树,最后遍历右子树
  • 中序遍历<LDR>:先遍历左子树,再访问根节点,最后遍历右子树
  • 后续遍历<LRD>:先遍历左子树,再遍历右子树,最后访问根节点

实现流程

具体实现步骤:

  1. 定义节点类,使用None类型数据表示空节点
  2. 定义二叉树类,初始化根节点
  3. 实现添加节点的方法
  4. 实现二叉树的遍历方法:实现前序遍历,中序遍历,后续遍历

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

二叉树的代码实现

自定义创建节点的类,并初始化类的属性:

class Node:
    def __init__(self, item):
        self.item = item
        self.child1 = None
        self.child2 = None

定义创建二叉树的类,并实现添加节点和二叉树的前中后序遍历

class Node:
    def __init__(self, item):
        self.item = item
        self.child1 = None
        self.child2 = None
class BinaryTree:
    def __init__(self):
        self.root = None
    #添加节点
    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
        else:
            q = [self.root]
            while True:
                pop_node = q.pop(0)
                if pop_node.child1 is None:
                    pop_node.child1 = node
                    return
                elif pop_node.child2 is None:
                    pop_node.child2 = node
                    return
                else:
                    q.append(pop_node.child1)
                    q.append(pop_node.child2)
    #使用递归实现遍历
    def preorder(self, root):  # 先序遍历
        if root is None:
            return []
        result = [root.item]
        left_item = self.preorder(root.child1)
        right_item = self.preorder(root.child2)
        return result + left_item + right_item
    def inorder(self, root):  # 中序遍历
        if root is None:
            return []
        result = [root.item]
        left_item = self.inorder(root.child1)
        right_item = self.inorder(root.child2)
        return left_item + result + right_item
    def postorder(self, root):  # 后序遍历
        if root is None:
            return []
        result = [root.item]
        left_item = self.postorder(root.child1)
        right_item = self.postorder(root.child2)
        return left_item + right_item + result

验证二叉树类:

tree=BinaryTree()
#0-9数字组成的树的遍历
for i in range(10):
    tree.add(i) #添加节点
print('前序遍历:', tree.preorder(tree.root))
print('中序遍历:', tree.inorder(tree.root))
print('后序遍历:', tree.postorder(tree.root))

执行结果:

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

总结

对于二叉树的遍历还有一种层序遍历,顾名思义,就是逐层遍历,对于树型结构,层序遍历就是按层从上到下,每层按一定顺序对树的节点进行遍历,比如每层从左到右逐个遍历。与前中后序遍历最根本的区别是双亲节点的访问时机不同.前序遍历是先访问双亲节点,然后左子节点,最后右子节点。而中序遍历是先访问左子节点,接着是双亲节点,最后右子节点。后序遍历是先访问左子节点,然后右子节点,最后双亲节点

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

热门文章

最新文章