设为首页 - 加入收藏  
您的当前位置:首页 >人工智能 >详解数据结构二叉树及其代码实现 正文

详解数据结构二叉树及其代码实现

来源:亿华互联编辑:人工智能时间:2025-11-05 13:03:25

 树

树是详解一种非常重要的非线性结构,本身具有递归的数据实现性质(在其后的编程中体现的淋漓尽致)。

看下图,结构及A 节点就是叉树 B 节点的父节点,B 节点是代码 A 节点的子节点。B、详解C、数据实现D 这三个节点的结构及父节点是同一个节点A,没有父节点的叉树叫做根节点,也就是代码 E 。

 

没有子节点的详解节点叫作叶子节点或者叶节点,图中的数据实现G,H,结构及I,叉树J,代码K,L

关于“树”,还有三个比较相似的概念:高度(Height)、网站模板深度(Depth),层(level)

二叉树(binary Tree)

二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

上图中,编号1是普通二叉树,编号2又是满二叉树,编号2又是完全二叉树。

满二叉树:在一棵二叉树中。如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。

满二叉树的特点有:

叶子只能出现在最下一层。出现在其它层就不可能达成平衡。 非叶子结点的度一定是2。 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。

编号3是云南idc服务商完全二叉树

「对一颗具有n个结点的二叉树按层编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。」

就是保证叶子节点的上面层都要达到最大,最低下两层,最后一层的叶子节点都靠左排列

二叉树具备以下数学性质:

在二叉树的第i层上至多有2(i-1)个结点(i>0)

深度为k的二叉树至多有2K-1个结点(k>0)

对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;

具有n个结点的完全二叉树的深度必为log2(n+1)

二叉树的遍历和节点的删除

二叉树的遍历是指从二叉树的根结点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次。

中序遍历:先左子树,再根节点,最后右子树 前序遍历:先根节点,站群服务器再左子树,最后右子树 后序遍历:先左子树,再右子树,最后根节点。

前序遍历通俗的说就是从二叉树的根结点出发,当第一次到达结点时就输出结点数据,按照先向左在向右的方向访问。

中序遍历就是从二叉树的根结点出发,当第二次到达结点时就输出结点数据,按照先向左在向右的方向访问。

后序遍历就是从二叉树的根结点出发,当第三次到达结点时就输出结点数据,按照先向左在向右的方向访问。

删除共有三种情况

被删除的节点是叶子节点,这时候只要把这个节点删除,再把指向这个节点的父节点指针置为空就行 被删除的节点有左子树,或者有右子树,而且只有其中一个,那么只要把当前删除节点的父节点指向被删除节点的左子树或者右子树就行。 如果要删除的节点有两个子节点,需要找到这个节点的右子树的最小节点,把它替换到要删除的节点上,然后再删除掉这个最小节点,因为最小节点肯定没有左子节点

 

代码具体实现二叉树

上面就是二叉树全部内容,下面用Pytho代码具体实现二叉树。

按下来就是编程实现了,请动手自己实现一把。

先实现一个 node 节点类:

class Node(object):     def __init__(self, item):         self.item = item         self.left = None         self.right = None     def __str__(self):         return str(self.item) 

这里的 __str__ 方法是为了方便打印。在 print 一个 Node 类时会打印__str__的返回值,例如:print(Node(5)) 就会打印出字符串 5 。

实现一个二叉树类:

class Tree(object):     def __init__(self):         # 根节点定义为 root 永不删除,做为哨兵使用。         self.root = Node(root)     # 添加节点操作     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.left is None:                     pop_node.left = node                     return                 elif pop_node.right is None:                     pop_node.right = node                     return                 else:                     q.append(pop_node.left)                     q.append(pop_node.right)     def get_parent(self, item):         找到 Item 的父节点         if self.root.item == item:             return None  # 根节点没有父节点         tmp = [self.root]         while tmp:             pop_node = tmp.pop(0)             if pop_node.left and pop_node.left.item == item:                 return pop_node             if pop_node.right and pop_node.right.item == item:                 return pop_node             if pop_node.left is not None:                 tmp.append(pop_node.left)             if pop_node.right is not None:                 tmp.append(pop_node.right)         return None     def delete(self, item):         从二叉树中删除一个元素         先获取 待删除节点 item 的父节点         如果父节点不为空,             判断 item 的左右子树             如果左子树为空,那么判断 item 是父节点的左孩子,还是右孩子,如果是左孩子,将父节点的左指针指向 item 的右子树,反之将父节点的右指针指向 item 的右子树             如果右子树为空,那么判断 item 是父节点的左孩子,还是右孩子,如果是左孩子,将父节点的左指针指向 item 的左子树,反之将父节点的右指针指向 item 的左子树             如果左右子树均不为空,寻找右子树中的最左叶子节点 x ,将 x 替代要删除的节点。         删除成功,返回 True         删除失败, 返回 False         if self.root is None:  # 如果根为空,就什么也不做             return False         parent = self.get_parent(item)         if parent:             del_node = parent.left if parent.left.item == item else parent.right  # 待删除节点             if del_node.left is None:                 if parent.left.item == item:                     parent.left = del_node.right                 else:                     parent.right = del_node.right                 del del_node                 return True             elif del_node.right is None:                 if parent.left.item == item:                     parent.left = del_node.left                 else:                     parent.right = del_node.left                 del del_node                 return True             else:  # 左右子树都不为空                 tmp_pre = del_node                 tmp_next = del_node.right                 if tmp_next.left is None:                     # 替代                     tmp_pre.right = tmp_next.right                     tmp_next.left = del_node.left                     tmp_next.right = del_node.right                 else:                     while tmp_next.left:  # 让tmp指向右子树的最后一个叶子                         tmp_pre = tmp_next                         tmp_next = tmp_next.left                     # 替代                     tmp_pre.left = tmp_next.right                     tmp_next.left = del_node.left                     tmp_next.right = del_node.right                 if parent.left.item == item:                     parent.left = tmp_next                 else:                     parent.right = tmp_next                 del del_node                 return True         else:             return False     def traverse(self):  # 层次遍历         if self.root is None:             return None         q = [self.root]         res = [self.root.item]         while q != []:             pop_node = q.pop(0)             if pop_node.left is not None:                 q.append(pop_node.left)                 res.append(pop_node.left.item)             if pop_node.right is not None:                 q.append(pop_node.right)                 res.append(pop_node.right.item)         return res     def preorder(self, root):  # 先序遍历         if root is None:             return []         result = [root.item]         left_item = self.preorder(root.left)         right_item = self.preorder(root.right)         return result + left_item + right_item     def inorder(self, root):  # 中序遍历         if root is None:             return []         result = [root.item]         left_item = self.inorder(root.left)         right_item = self.inorder(root.right)         return left_item + result + right_item     def postorder(self, root):  # 后序遍历         if root is None:             return []         result = [root.item]         left_item = self.postorder(root.left)         right_item = self.postorder(root.right)         return left_item + right_item + result 

运行测试:

if __name__ == __main__:     t = Tree()     for i in range(10):         t.add(i)     print(层序遍历:, t.traverse())     print(先序遍历:, t.preorder(t.root))     print(中序遍历:, t.inorder(t.root))     print(后序遍历:, t.postorder(t.root))     for i in range(10):         print(i, " 的父亲", t.get_parent(i))     for i in range(0, 15, 3):         print(f"删除 {i}", 成功 if t.delete(i) else 失败)         print(层序遍历:, t.traverse())         print(先序遍历:, t.preorder(t.root))         print(中序遍历:, t.inorder(t.root))         print(后序遍历:, t.postorder(t.root)) 

执行结果如下:

层序遍历: [root, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 先序遍历: [root, 0, 2, 6, 7, 3, 8, 9, 1, 4, 5] 中序遍历: [6, 2, 7, 0, 8, 3, 9, root, 4, 1, 5] 后序遍历: [6, 7, 2, 8, 9, 3, 0, 4, 5, 1, root] 0  的父亲 root 1  的父亲 root 2  的父亲 0 3  的父亲 0 4  的父亲 1 5  的父亲 1 6  的父亲 2 7  的父亲 2 8  的父亲 3 9  的父亲 3 删除 0 成功 层序遍历: [root, 8, 1, 2, 3, 4, 5, 6, 7, 9] 先序遍历: [root, 8, 2, 6, 7, 3, 9, 1, 4, 5] 中序遍历: [6, 2, 7, 8, 3, 9, root, 4, 1, 5] 后序遍历: [6, 7, 2, 9, 3, 8, 4, 5, 1, root] 删除 3 成功 层序遍历: [root, 8, 1, 2, 9, 4, 5, 6, 7] 先序遍历: [root, 8, 2, 6, 7, 9, 1, 4, 5] 中序遍历: [6, 2, 7, 8, 9, root, 4, 1, 5] 后序遍历: [6, 7, 2, 9, 8, 4, 5, 1, root] 删除 6 成功 层序遍历: [root, 8, 1, 2, 9, 4, 5, 7] 先序遍历: [root, 8, 2, 7, 9, 1, 4, 5] 中序遍历: [2, 7, 8, 9, root, 4, 1, 5] 后序遍历: [7, 2, 9, 8, 4, 5, 1, root] 删除 9 成功 层序遍历: [root, 8, 1, 2, 4, 5, 7] 先序遍历: [root, 8, 2, 7, 1, 4, 5] 中序遍历: [2, 7, 8, root, 4, 1, 5] 后序遍历: [7, 2, 8, 4, 5, 1, root] 删除 12 失败 层序遍历: [root, 8, 1, 2, 4, 5, 7] 先序遍历: [root, 8, 2, 7, 1, 4, 5] 中序遍历: [2, 7, 8, root, 4, 1, 5] 后序遍历: [7, 2, 8, 4, 5, 1, root] 

Binarytree是一个Python库,它通过一个简单的API生成二叉树,可以进行检查和操作。Github:https://github.com/joowani/binarytree/releases。

本文已收录 GitHub  https://github.com/MaoliRUNsen/runsenlearnpy100

上一篇:先安装VMWare10,这个没什么可说的,安装好后启动,点击新建虚拟机,因为想设置虚拟机的磁盘保存方式,所以选择自定义选择“稍后安装操作系统”选择64位的版本给自己的机器取个名字,设定虚拟机磁盘路径,电脑c盘是SSD,为了速度就安到C盘了设置处理器的配置,这里需要看个人电脑配置,我是四核8线程的i7,这里就选了2*2,假如CPU核心数不多,就选择1*2分配内存,先来2G,以后不够再改配置后面的设置,除了磁盘的设置:将虚拟磁盘存储为单个文件,其他都默认就OK设置完成后,点击编辑虚拟机配置,设置ISO镜像文件路径完成后启动虚拟机,等安装文件加载,进入语言选择,默认是英文,下面有中文的语言选择我选择安装完成后再更新,音频解码就算了,虚拟机主要是为了布开发环境清除磁盘就行,不用怕,不会把真实磁盘清理掉的=。=把我默认到哈尔滨去了。。点击国内区域,选成shanghai注意:键盘布局选择英语(美国)设置用户名,密码下面登陆Ubuntu账户,愿意的填email创建一个,我选择以后登陆,估计很久很久以后=。=安装开始,趁机赶几行代码。。SSD安装就是快,完毕重启可以登陆了桌面很小,这时候还要安装VMtool点击顶部菜单栏的虚拟机选项,下拉选择“安装VMware Tools”,会自动载入光盘,打开窗口运行“vmware-tools-upgrader-64”无反应,把VMwareTools.tar.gz 文件拷贝而到桌面,右键提取到此处,会解压为一个 vmware-tools-distrib 目录打开终端,输入以下命令$ cd 桌面/vmware-tools-distrib$ sudo ./vmware-install.pl输入密码,执行,一路回车摁下去,到最后出现“Enjoy——the VMware team”的字样,安装完成打开VMware上方菜单栏的查看-自动调整大小,设置为自动适应客户机和自动适应窗口,右上角按钮重启虚拟机,登陆后就发现虚拟机桌面铺满窗口,调整壁纸平铺方式,显示OK至此,安装完成~
下一篇:挖掘有价值的域名(如何选择具有潜力的域名及其价值分析)
最新文章

1.1332s , 11784.734375 kb

Copyright © 2025 Powered by 详解数据结构二叉树及其代码实现,亿华互联  滇ICP备2023000592号-16

sitemap

Top