python、java实现二叉树,细说二叉树添加节点、深度优先(先序、中序、后续)遍历 、广度优先 遍历算法...
数据结构可以说是编程的内功心法,掌握好数据结构真的非常重要。目前基本上流行的数据结构都是c和c++版本的,我最近在学习python,尝试着用python实现了二叉树的基本操作。写下一篇博文,总结一下,希望能够对其他好伙伴带来一点借鉴价值~~
温馨提示:学习算法要先懂思想,后学代码。思想学会才是自己的。背下来代码,容易忘。
代码捉襟见肘,欢迎批评指正 ^.^ 先谈一下二叉树: 二叉树是常用的存储数据的方式。除了根节点之外,每个节点都有一个父节点,最多有两个子节点,左孩子和右孩子对于二叉树有如下操作: 1 添加节点: 按层次添加,优先选择层次最小的,并且优先靠左添加节点2 树的遍历: 分为 深度优先 和 广度优先 构造一个二叉树当作例子 根是1 左孩子2 右孩子3 ...... 1 2 3 4 5 6 7 广度优先遍历: 按照层次由低到高,先左后右的顺序 1 2 3 4 5 6 7 编程实现的思想: 开启一个队列 queue(队列是数据结构中先进先出的实现,队列的朋友需要再看一看数据结构链表的知识) 1 把 树根 1 放进队列 队列变成 1 2 重复执行:从队列取一个队头出队一个节点,如果它有左孩子,把左孩子放入队列,如果他有右孩子把右孩子放入队列。输出当前节点的数值 一直到队列空了为止 2.1 从队头取出1 把1输出,把1的左孩子和右孩子添加到队列 队列变成: 2 3 2.2 从对头取出2 把2输出,把2的左孩子和右孩子添加到队列 队列变成: 3 4 5 2.3 从对头取出3 把3输出, 把3的左孩子右孩子添加到队列, 队列变成: 4 5 6 7 2.4 从对头取出4 把4输出,它没有左孩子和右孩子 不用入队列 2.5 从对头取出5 把5输出, 它没有左孩子右孩子 不用入队列 2.6 从对头取出6 把6输出, 它没有左孩子右孩子 不用入队列 2.7 从对头取出7 把7输出, 它没有左孩子右孩子 不用入队列 2.8 队列空了,结束 深度优先遍历:又分为三种:先序 中序 后序 先序遍历(先输出根): 按照 根 左 右 的顺序 遍历结果:1 2 4 5 3 6 7 1 对于树根1,先输出1,然后再遍历它的左子树和右子树 1.1 对于左子树2是树根先输出2,再遍历它的左子树和右子树 1.1.1 对于左子树4 树根4输出,没有左右子树 不用向下遍历 1.1.2 对于右子树5 树根5输出 没有左右子树 不用向下遍历 1.2 对于右子树3树根3 输出3, 在遍历它的左子树和右子树 1.2.1 对于左子树6 输出根6 没有左右子树 不用向下遍历 1.2.2 对于右子树7 输出根7 没有左右子树 不用向下遍历 总结:先输出根,然后对左子树当成新树遍历,然后对右子树当成新树遍历,循环遍历到没有子树 中序遍历(中间输出根):按照 左 根 右 的顺序 遍历结果:4 2 5 1 6 3 7 1 对于树1 先对左子树遍历 再输出根 最后对右子树遍历 1.1 对于左子树2 先对左子树遍历 再输出根 最后对右子树遍历 1.1.1 对于左子树4,没有孩子了 输出树根 4 1.1.2 遍历完左子树了 输出根 2 再遍历右子树 1.1.3 对于右子树5,没有孩子了 输出树根 5 1.2 左子树2遍历完了 输出根 1 再遍历右子树 3 1.3 对于右子树3 先对左子树遍历 再输出根 最后对右子树遍历 1.3.1 对左子树6 没有孩子了 输出根6 1.3.2 左子树6遍历完了 输出根 3 再遍历右子树7 1.3.3 对于右子树7 没有孩子 输出根 7 后序遍历(最后输出根):按照 左 右 根 的顺序 遍历结果:4 5 2 6 7 3 1 1 对于树 先遍历左子树 再遍历右子树 最后输出根 1.1 对于左子树2 先遍历左子树 再遍历右子树 最后输出根 1.1.1对于左子树4 没有孩子了 输出根 4 1.1.2对于右子树5 没有孩子了 输出根 5 1.1.3左子树 右子树遍历完了输出根 2 1.2 对于右子树3 先遍历左子树 再遍历右子树 最后输出根 1.2.1 对于左子树6 没有孩子了 输出根 6 1.2.2 对于右子树7 没有孩子了 输出根 7 1.2.3 左右子树遍历完了 最后输出根 3 1。3 左右子树遍历完了 最后输出根 1 接下来 我们用python来实现一下各种操作!!!
1 #一个节点的数据类型,包含左子孩子节点指针 右孩子节点指针 和值 2 class Node(object): 3 def __init__(self , item): 4 self.left = None #指向左子节点 5 self.right = None #指向右子节点 6 self.item = item #保存值 7 8 #树的类 9 class Tree(object): 10 def __init__(self): 11 self.root = None #保存树根所在位置 12 #添加节点方法,按照层次由低到高,优先靠左的思想添加 13 def add(self , item ): 14 node = Node(item) #首先创建一个节点 15 #如果树还没有树根 16 if self.root is None: 17 self.root = node 18 else : 19 # 这里需要用到广度优先遍历的思想来找第一个可以添加节点的位置 20 # 开一个队列用于广度优先搜索 先把树根放进去 21 queue = [ self.root ] 22 #循环操作: 23 # 出队一个节点,如果它没有左海子,为它添加左孩子 退出 否则 左孩子入队列 24 # 如果他没有右孩子,为它添加右孩子 退出 否则 右孩子如队列 25 #如果队列里面有元素我们就一直操作。队列空了就退出来(这个只是保险条件,一般队列还没空就找到空位创建节点然后退出了) 26 while queue : 27 #取出队节点 28 temp = queue.pop(0) 29 #如果没有左孩子 我们 添加左孩子后退出 30 if temp.left is None: 31 temp.left = node 32 return 33 #如果有左孩子 我们把左孩子入队列 34 else: 35 queue.append(temp.left) 36 37 #如果没有右孩子 我们添加右孩子 然后退出 38 if temp.right is None: 39 temp.right = node 40 return 41 # 如果有右孩子 我们把右孩子入队列 42 else : 43 queue.append( temp.right ) 44 # 广度优先遍历 45 def breadth_travel(self): 46 #开启一个队列 把树根放进去 47 queue=[ self.root ] 48 #循环操作:从对头取出节点,把值输出后 把他们的左孩子右孩子添加到队列里,一直到队列空了,说明遍历结束 49 # 只要队列不是空的 我们就一直遍历 50 while queue : 51 #从队列头取出一个元素 52 temp = queue.pop(0) 53 #输出节点的值 54 print( temp.item,end=" " ) 55 #如果节点有左孩子 就把左孩子追加到队列 56 if temp.left is not None: 57 queue.append( temp.left ) 58 #如果节点有右孩子 就把右孩子追加到队列 59 if temp.right is not None: 60 queue.append(temp.right) 61 #最后来一个换行 62 print() 63 #先序遍历 按照 根 左 右 进行遍历 64 # 把当前子树的树根传进去做参数 65 def preOder(self , node): 66 #如果传进来的十个None,说明上一个节点 没有左孩子或者右孩子 传进来一个None 那就不遍历这个节点 67 if not node: 68 return 69 #先把根的值输出来 70 print(node.item,end=" ") 71 #然后对左孩子进行遍历 72 self.preOder( node.left ) 73 #然后对右孩子遍历 74 self.preOder( node.right ) 75 #中序遍历 按照 左 根 右 的顺序进行遍历 76 # 传入当前要遍历的子树的根 77 def inOrder(self, node): 78 #当传入的子树是None 说明上一个节点没有这个子树 传进来了None 此时不用遍历它了 79 if not node: 80 return None 81 #先对左子树进行遍历 82 self.inOrder( node.left ) 83 #再输出自己的数值 84 print( node.item,end=" " ) 85 #最后对右子树进行遍历 86 self.inOrder(node.right) 87 #后序遍历 按照 左 右 根 的顺序进行遍历 88 # 把当前子树的树根传进去做参数 89 def postOrder(self,node): 90 #如果传进来一个None 说明上一个节点没有这可子树,这时候不用遍历 91 if not node : 92 return 93 #先对左子树进行遍历 94 self.postOrder(node.left) 95 #再对右子树进行遍历 96 self.postOrder(node.right) 97 #最后输出自己的值 98 print( node.item,end=" " ) 99 100 #我们再封装一下,在外部调用自己的三个深度优先遍历可以不传入自己的根 101 def preOrder_travel(self): 102 self.preOder(self.root) 103 def inOrder_travel(self): 104 self.inOrder( self.root ) 105 def postOrder_travel(self): 106 self.postOrder(self.root) 107 108 109 110 if __name__ == '__main__': 111 tree = Tree() 112 tree.add(1) 113 tree.add(2) 114 tree.add(3) 115 tree.add(4) 116 tree.add(5) 117 tree.add(6) 118 tree.add(7) 119 tree.breadth_travel() # 1 2 3 4 5 6 7 120 tree.preOrder_travel() #1 2 4 5 3 6 7 121 print()# 回车换行 122 tree.inOrder_travel() #4 2 5 1 6 3 7 123 print()# 回车换行 124 tree.postOrder_travel() #4 5 2 6 7 3 1
java实现:
1 import java.util.LinkedList; 2 import java.util.Queue; 3 //二叉树的实现 4 class Main { 5 public static void main(String[] args) { 6 Tree tree = new Tree(); 7 tree.append(1); 8 tree.append(2); 9 tree.append(3); 10 tree.append(4); 11 tree.append(5); 12 tree.append(6); 13 tree.append(7); 14 tree.breadth(); 15 tree.preOrder_travel(); 16 tree.inOrder_travel(); 17 tree.postOrder_travel(); 18 } 19 20 } 21 //一棵树的叶子节点 22 class Node{ 23 int value; 24 Node left = null; 25 Node right = null; 26 public Node(int value){ 27 this.value = value; 28 } 29 } 30 31 public class Tree{ 32 private Node root = null; 33 public Node getRoot(){ 34 return this.root; 35 } 36 //添加叶子节点方法 37 public void append( int value ){ 38 Node node = new Node(value); 39 //如果根节点是空的,就添加根节点 40 if( this.root == null ){ 41 this.root = node; 42 //根节点不是空的 按层次遍历 找到最浅层次最靠左的位置把节点放进去 43 }else{ 44 Queue<Node> queue = new LinkedList<Node>(); 45 queue.offer(this.root); 46 while( ! queue.isEmpty() ){ 47 Node cur = queue.poll(); 48 if( cur.left == null ){ 49 cur.left = node; 50 break; 51 }else{ 52 queue.add(cur.left); 53 } 54 if( cur.right == null ){ 55 cur.right = node; 56 break; 57 }else{ 58 queue.add(cur.right); 59 } 60 } 61 } 62 } 63 //广度优先遍历 64 public void breadth( ){ 65 Queue<Node> queue = new LinkedList<Node>(); 66 queue.add(this.root); 67 while( !queue.isEmpty() ){ 68 Node cur = queue.poll(); 69 System.out.print(cur.value+" "); 70 if(cur.left!=null){ 71 queue.add(cur.left); 72 } 73 if(cur.right!= null){ 74 queue.add(cur.right); 75 } 76 } 77 System.out.println(); 78 } 79 //深度优先遍历 80 //先序遍历 81 public void preOrder_travel(){ 82 preOrder(this.root); 83 System.out.println(); 84 } 85 private void preOrder(Node root){ 86 if(root == null){ 87 return; 88 } 89 System.out.print( root.value + " " ); 90 preOrder(root.left); 91 preOrder(root.right); 92 } 93 //中序遍历 94 public void inOrder_travel(){ 95 inOrder(this.root); 96 System.out.println(); 97 } 98 private void inOrder(Node root){ 99 if(root == null){ 100 return; 101 } 102 inOrder(root.left); 103 System.out.print( root.value + " " ); 104 inOrder(root.right); 105 } 106 //后序遍历 107 public void postOrder_travel(){ 108 postOrder(this.root); 109 System.out.println(); 110 } 111 private void postOrder(Node root){ 112 if(root == null){ 113 return; 114 } 115 postOrder(root.left); 116 postOrder(root.right); 117 System.out.print( root.value + " " ); 118 } 119 }
对于初学者来说,二叉树的遍历可能有点难,不过没有关系,认真理解算法思想,一点一点来,总会理解的!
对于算法的实现,不同的人实现方式多少有些不一样,如果有好伙伴有更好的方案,也欢迎沟通交流~~
转载于:https://www.cnblogs.com/Lin-Yi/p/7324670.html
python、java实现二叉树,细说二叉树添加节点、深度优先(先序、中序、后续)遍历 、广度优先 遍历算法...相关推荐
- 数据结构与算法实验 实验6:二叉树ADT的二叉链式实现 (由完全前序序列创建二叉树 / 求二叉树的节点数/树高/叶子节点数 /先序中序后序层序遍历)
假设二叉数的数据元素为字符,采用二叉链式存储结构.请编码实现二叉树ADT,其中包括创建二叉树.遍历二叉树(深度.广度).求二叉树的深度(高度).计算二叉树的元素个数.计算二叉树的叶子数.二叉树的格式输 ...
- 二叉树前序后序中序互推总结
最近笔试题一直遇到这个题,今天就总结一下.本文主要回答以下几个问题(Java实现): 前序 + 中序 => 后序 + 层序 后序 + 中序 => 前序 + 层序 以上2个问题的2种解决办法 ...
- 二叉树--先序中序遍历求后序遍历
先序遍历:根 左 右 中序遍历:左 根 右 后序遍历:左 右 根 我们可以先从先序遍历中找到根节点,由于知道了根节点那么可以依靠中序遍历找到左子树,右子树.这样再去先序遍历中找到左子树的根节点,然后再 ...
- 【IT笔试面试题整理】给定二叉树先序中序,建立二叉树的递归算法
[试题描述]: 给定二叉树先序中序,建立二叉树的递归算法 其先序序列的第一个元素为根节点,接下来即为其左子树先序遍历序列,紧跟着是右子树先序遍历序列,固根节点已可从先序序列中分离.在中序序列中找到 ...
- 【笔记】二叉树递归算法和非递归算法的实现 先序/中序/后续遍历 打印结点以及顺序数 构造二叉树
递归先序遍历和中序遍历 先序: void preorder(bnode *t){if(t!=NULL){ visit(t);preorder(t->lchild); preorder(t-> ...
- C/C++面试题—重建二叉树【前序 + 中序- 重建二叉树 和 后序 + 中序 - 重建二叉树】
题目介绍 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{ ...
- 二叉树前序中序,后序中序,公共最近祖先的实现
二叉树前序中序,后序中序,公共最近祖先的实现 注释中详细介绍了算法,故不再赘述. 无论是前序还是后序,一个节点的左子树和右子树都是可以看做是分开的,有一定规律可循,故可用递归进行实现. #includ ...
- 先序中序建立二叉树的递归算法
其先序序列的第一个元素为根节点,接下来即为其左子树先序遍历序 列,紧跟着是右子树先序遍历序列,故根节点已可从先序序列中分离.在中序序列中找 到 确定的根节点,根据中序遍历特性,在巾序序列中,根节点前面 ...
- 【好记性不如烂笔头】二叉树之利用先序中序还原树
利用先序中序还原树 前言 一.二叉树示例 二.思路 写一下节点信息 考虑递归实现 前言 之前进行了二叉树的先序中序后序打印,那么反过来怎么把先序中序还原出二叉树呢? 一.二叉树示例 二.思路 写一下节 ...
- 前序中序、后序中序遍历创建二叉树,并检验是否是二叉搜索树,若是则转换为双向链表
finalbst.h //该程序的作用是根据所给的前序序列以及中序序列或者中序序列以及后序序列创建二叉树 #include <iostream> #include <vector&g ...
最新文章
- rspec 测试页面元素_如何使用共享示例使您的RSpec测试干燥
- R线性回归模型构建示例
- 微隔离的红蔷薇在湾区创见的舞台绽放
- bzoj 1968: [Ahoi2005]COMMON 约数研究【枚举】
- 叫你两招编辑PDF文档的方法
- 大四生活总结20101015
- 平滑均值滤波讲解-Matlab
- sentinel的@SentinelResource注解使用
- python断言assert实例_Python 拓展之断言(assert)
- JAVA开发必须掌握的21个核心技术
- 给Visual Studio 2005设置一个代码边界线
- Stata+R:一文读懂中介效应
- 收据模板 纯css+html
- 堆排序算法知识点总结
- 密码学入门(7):数字签名和证书
- Nagios监控服务器与客户端的安装
- human pose estimation期刊简单汇总
- No fallbackFactory instance of type class com.chongyou.system.api.factory.RemoteUserFallbackFactory
- 【小王的安卓之路】Android原生网络请求
- android studio中的文本替换