<基础巩固>二叉树的遍历

简介:

引入:

这里我们来复习下二叉树的基本操作,这里假定我们定义一个有序二叉树,就是对于任意的节点,其如果有左子节点,那么左子节点的值一定小于该节点,如果有右子节点,则右子节点的值一定大于该节点。我们这里还给出代码表明如何前序,中序,后序来遍历这个二叉树。


实践:

我们先定义一个二叉树节点的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package  com.charles.algo.binarytree;
/**
  * 这个类定义了一个二叉树的节点
  * @author charles.wang
  *
  */
public  class  BinaryTreeNode {
                                                                                                                                                                                            
     //二叉树中当前节点的内容
     private  Object data;
     //二叉树的左子节点
     private  BinaryTreeNode leftChild;
     //二叉树的右子节点
     private  BinaryTreeNode rightChild;
                                                                                                                                                                                            
     public  BinaryTreeNode(Object data,BinaryTreeNode leftChild,BinaryTreeNode rightChild){
         this .data =data;
         this .leftChild=leftChild;
         this .rightChild=rightChild;
     }
                                                                                                                                                                                            
     public  Object getData() {
         return  data;
     }
     public  void  setData(Object data) {
         this .data = data;
     }
     public  BinaryTreeNode getLeftChild() {
         return  leftChild;
     }
     public  void  setLeftChild(BinaryTreeNode leftChild) {
         this .leftChild = leftChild;
     }
     public  BinaryTreeNode getRightChild() {
         return  rightChild;
     }
     public  void  setRightChild(BinaryTreeNode rightChild) {
         this .rightChild = rightChild;
     }
                                                                                                                                                                                            
                                                                                                                                                                                            
                                                                                                                                                                                            
                                                                                                                                                                                            
                                                                                                                                                                                          
}


然后我们定义一个二叉树类,这个二叉树提供了插入节点,前序遍历,中序遍历,后序遍历的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package  com.charles.algo.binarytree;
/**
  * 这里定义了一个基本的有序二叉树的数据结构
  * @author charles.wang
  *
  */
public  class  OrderedBinaryTree<T> {
                                                                                                                                                                
     //用链表来实现排序二叉树的数据存储,这里放着根节点
     private  BinaryTreeNode rootNode;
                                                                                                                                                                
                                                                                                                                                                
     public  OrderedBinaryTree(){
         rootNode =  null ;
     }
                                                                                                                                                                
     /**
      * 返回当前有序二叉树的最大高度
      * @return
      */
     public  int  getMaxHeight(){
                                                                                                                                                                    
         return  getHeight(rootNode);
                                                                                                                                                                    
     }
                                                                                                                                                                
     /**
      * 基于当前树根节点确定子树的高度,这是一个递归的方法
      * @return
      */
     private  int  getHeight(BinaryTreeNode currentNode){
                                                                                                                                                                    
         //如果当前树根节点为空,则返回 0
         if (currentNode== null )
             return  0 ;
                                                                                                                                                                    
         //如果当前树根节点不为空,那么获取左子树高度和右字数高度的最大值
         int  maxLeftTreeHeight = getHeight(currentNode.getLeftChild())+ 1 ;
         int  maxRightTreeHeight = getHeight(currentNode.getRightChild())+ 1 ;
         return  Math.max(maxLeftTreeHeight, maxRightTreeHeight);
                                                                                                                                                                    
     }
                                                                                                                                                                
     /**
      * 插入节点到当前的有序二叉树,
      */
     public  OrderedBinaryTree insertNode(Object data ){
                                                                                                                                                                    
         //如果有序二叉树中rootNode为空,那么就直接新建一个节点并且赋值给root
         if (rootNode== null ){
             BinaryTreeNode binaryTreeNode =  new  BinaryTreeNode(data, null , null );
             rootNode=binaryTreeNode;
             return  this ;      
         }
                                                                                                                                                                    
         //如果有序二叉树的rootNode不为空,那么就调用递归方法进行插入
         else
             return  insertNode(data,rootNode);
                                                                                                                                                                    
                                                                                                                                                                    
                                                                                                                                                                    
     }
                                                                                                                                                                
     /**
      * 递归的插入一个节点到当前节点使得仍然保持 一个有序二叉树
      */
     public  OrderedBinaryTree insertNode(Object data, BinaryTreeNode rootNode){
                                                                                                                                                                    
                                                                                                                                                                    
         //创建一个代表当前待查数据的节点
         BinaryTreeNode currentNode =  new  BinaryTreeNode(data, null , null );
                                                                                                                                                                    
         //吧当前的数据和被插入的rootNode的大小进行比较
                                                                                                                                                                    
         //如果当前数据小于被插入的rootNode,那么这个新的数据节点必定插在rootNode的左边
         if ( (Integer)data< (Integer)rootNode.getData()){
                                                                                                                                                                        
             //如果待插的rootNode的左节点为空,那么直接插入
             if (rootNode.getLeftChild()== null ){
                 rootNode.setLeftChild(currentNode);
                 return  this ;
             }
             //如果待插的rotNode的左节点不为空,则递归的吧待插入点设为root的左节点,然后递归的调用方法插入
             else
                 return  insertNode(data ,rootNode.getLeftChild());
         }
                                                                                                                                                                    
         //如果当前数据大于被插入的rootNode,那么这个新的数据节点必定插在rootNode的右边
         else  {
                                                                                                                                                                        
             //如果待插的rootNode的右边节点为空,那么直接插入
             if (rootNode.getRightChild()== null ){
                 rootNode.setRightChild(currentNode);
                 return  this ;
             }
             //如果待插的rootNode的右边节点不为空,则赌鬼的吧所待插入点设为root的右节点,然后递归调用方法插入
             else
                 return  insertNode(data,rootNode.getRightChild());
         }
                                                                                                                                                                    
                                                                                                                                                                    
     }
                                                                                                                                                                
     /**
      * 前序遍历这个二叉树,并且打印出这个二叉树的各个节点
      */
     public  void  preOrderFullBinaryTree(){
         preOrder(rootNode);
     }
                                                                                                                                                                
     /**
      * 中序遍历这个二叉树,并且打印出这个二叉树的各个节点
      */
     public  void  midOrderFullBinaryTree(){
         midOrder(rootNode);
     }
                                                                                                                                                                
     /**
      * 后序遍历这个二叉树,并且打印出这个二叉树的各个节点
      */
     public  void  postOrderFullBinaryTree(){
         postOrder(rootNode);
     }
                                                                                                                                                                
     /**
      * 前序遍历某节点,它会先打印当前节点,然后打印出左边节点,然后打印出右边节点
      */
     private  void  preOrder(BinaryTreeNode currentNode){
                                                                                                                                                                    
         //当前的节点如果是null,则不打印出当前节点,并且退出递归
                                                                                                                                                                    
         if (currentNode!= null ){
             System.out.print(currentNode.getData()+ " " );  
             //遍历左边子树
             preOrder(currentNode.getLeftChild());
             //遍历右边子树
             preOrder(currentNode.getRightChild());
         }
     }
                                                                                                                                                                
     /**
      * 中序遍历某节点,它会先打印左边节点,再打印当前节点,最后打印出右边节点
      * @param args
      */
     private  void  midOrder(BinaryTreeNode currentNode){
                                                                                                                                                                    
         //当前节点如果是null,则不打印出当前节点,并且退出递归
         if (currentNode!= null ){
             midOrder(currentNode.getLeftChild());
             System.out.print(currentNode.getData()+ " " );
             midOrder(currentNode.getRightChild());
         }
     }
                                                                                                                                                                
     /**
      * 后序遍历某个节点,它会先打印出左边节点,再打印出右边节点,最后打印出当前节点
      * @param args
      */
     private  void  postOrder(BinaryTreeNode currentNode){
                                                                                                                                                                    
         //如果当前的节点是null,则不打印出当前节点,并且退出递归
         if (currentNode!= null ){
             postOrder(currentNode.getLeftChild());
             postOrder(currentNode.getRightChild());
             System.out.print(currentNode.getData()+ " " );
         }
     }
                                                                                                                                                                
                                                                                                                                                                
                                                                                                                                                                
     public  static  void  main(String[] args){
         OrderedBinaryTree<Integer> fbt =  new  OrderedBinaryTree<Integer>();
         fbt.insertNode( 12 ).insertNode( 5 ).insertNode( 9 ).insertNode( 11 ).insertNode( 8 ).insertNode( 42 ).insertNode( 4 );
                                                                                                                                                                    
                                                                                                                                                                    
         //前序遍历所有的节点
         System.out.println( "前序的方式遍历二叉树的所有的节点:" );
         fbt.preOrderFullBinaryTree();
         System.out.println();
                                                                                                                                                                    
         //中序遍历所有的节点
         System.out.println ( "中序的方式遍历二叉树的所有的节点:" );
         fbt.midOrderFullBinaryTree();
         System.out.println();
                                                                                                                                                                    
         //后序遍历所有的节点
         System.out.println( "后序的方式遍历二叉树的所有的节点:" );
         fbt.postOrderFullBinaryTree();
         System.out.println();
     }
}


其实由于考虑到二叉树定义的递归性,我们上述方法都是用递归实现的,比如插入就是比较当前元素,如果插入元素比当前元素少,那么就比较当前元素的左子元素,如果左子元素不存在,那么新插入的元素就作为左子元素,否则就以左子元素为根,递归的插入该元素到左子二叉树中。反过来也一样,如果插入元素比当前元素大,那么久比较当前元素的右子元素,如果右子元素不存在,那么新插元素就作为右子元素,否则就以右子元素为根,递归的插入到该元素到右子二叉树中。


前序,中序,后序遍历也是一样的。


验证结果:

最后我们来运行这个简单的例子,果然是期望的,比如我们分别插入了果然的不一样的数,那么遍历结果顺序是不一样的但是都遍历二叉树的所有节点。

wKiom1LOW1nw9s9_AADdUvAfbdo940.jpg





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1350157,如需转载请自行联系原作者
目录
相关文章
|
JavaScript
js判断是否微信PC端打开内置浏览器
js判断是否微信PC端打开内置浏览器
|
开发者 程序员
基于阿里云快速搭建数字营销引擎【计算广告】
阿里云营销引擎有别于其他阿里云产品,它是配合阿里云MaxComputer,画像分析,分析型数据库等多个云产品,并在高德DMP和友盟+DMP提供人群分析能力的基础上,提供一整套数字营销解决方案。 在过去搭建一套成熟DSP平台需要一个强大的技术和业务团队,现在只需要一个人就能够轻松完成,大幅降低了系统构建的基础设施成本,运维成本,容灾成本,开发成本,时间成本。
3482 0
|
5月前
|
存储 运维 分布式计算
OSS迁移实战:从自建MinIO到阿里云OSS的完整数据迁移方案
本文介绍了从自建MinIO迁移至阿里云OSS的完整方案,涵盖成本优化、稳定性提升与生态集成需求。通过双写代理、增量同步、分层校验等技术,解决数据一致性、权限迁移、海量小文件处理等挑战,实现业务零中断与数据强一致性,最终达成79%的TCO降低和显著性能提升。
1408 0
|
存储 前端开发 JavaScript
太爽了!这12个前端库,帮我在工作中赢得了不少摸鱼时间!!
太爽了!这12个前端库,帮我在工作中赢得了不少摸鱼时间!!
|
JSON 测试技术 持续交付
自动化测试与脚本编写:Python实践指南
【4月更文挑战第9天】本文探讨了Python在自动化测试中的应用,强调其作为热门选择的原因。Python拥有丰富的测试框架(如unittest、pytest、nose)以支持自动化测试,简化测试用例的编写与维护。示例展示了使用unittest进行单元测试的基本步骤。此外,Python还适用于集成测试、系统测试等,提供模拟外部系统行为的工具。在脚本编写实践中,Python的灵活语法和强大库(如os、shutil、sqlite3、json)助力执行复杂测试任务。同时,Python支持并发、分布式执行及与Jenkins、Travis CI等持续集成工具的集成,提升测试效率和质量。
742 3
|
SQL JavaScript Java
StarCoder 2:GitHub Copilot本地开源LLM替代方案
GitHub CoPilot拥有超过130万付费用户,部署在5万多个组织中,是世界上部署最广泛的人工智能开发工具。使用LLM进行编程辅助工作不仅提高了生产力,而且正在永久性地改变数字原住民开发软件的方式,我也是它的付费用户之一。
667 0
|
网络协议 网络安全 Android开发
防火墙NAT策略(一)
人类对计算机网路的使用已经拓展到各个领域,而计算机网络的设计者在当时无法想象网络能有今天的规模。任何一个接入互联网的计算机、lpad、手机及安卓电视,要想在互联网中畅游,必须有一个合法的IP地址。而IP地址,曾经认为足以容纳全球的计算机,但是在今天看来,已经严重枯竭。IPv6的出现就是为了解决地址不足的问题。但在IPv6普及之前,需要有一个过渡技术——NAT。NAT的出现缓解了地址不够用的情况,它可以让同一局域网内60000多用户同时使用一个合法P地址访问互联网。NAT技术不是新技术,对于我们来说也并不陌生,文本重点介绍华为的NAT技术。
防火墙NAT策略(一)
|
网络虚拟化
华为eNSP网络配置综合练习一(vlan +MSTP+VLANif+VRRP+ 静态路由+单臂路由+STP+BFD)
华为eNSP网络配置综合练习一(vlan +MSTP+VLANif+VRRP+ 静态路由+单臂路由+STP+BFD)
|
存储 缓存 算法
数据结构与算法第十六讲:分布式算法之一致性Hash算法
数据结构与算法第十六讲:分布式算法之一致性Hash算法
317 0