二叉排序树的建立和各种遍历方法-java

转载自:https://www.2cto.com/kf/201608/534396.html

二叉排序树的定义:

二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
如下:

这里写图片描述
遍历方法:

树的遍历方法一般有如下几种方法:
(1)层次遍历:按照树的层次进行遍历,如图树:8、3、10、1、6、14、4、7、13
(2)先序遍历:节点遍历顺序为当前节点、左节点、右节点。如图树:8、3、1、6、4、7、10、14、13
(3)中序遍历:节点遍历顺序为左节点、当前节点、右节点。如图树:1、3、4、6、7、8、10、13、14
(4)后续遍历:节点遍历顺序为左节点、右节点、当前节点。如图树:1、4、7、6、3、8、13、14、10

代码实现:
(1)节点定义:Node.java
?
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
package com.lee.wait;
 
/**
  * Node 二叉树上的节点
  * @author wait
  *
  */
public class Node {
     /**
      * 节点的数据,这里我们用一个int表示
      */
     public int data;
     /**
      * 节点的左孩子
      */
     public Node left;
     /**
      * 节点的右孩子
      */
     public Node right;
     /**
      * 构造函数,data初始化节点的值
      * @param data
      */
     public Node( int data){
         this .data=data;
     }
     /**
      * 默认构造函数,data=0
      */
     public Node(){
         this ( 0 );
     }
}

(2)二叉排序树的类BTree.java

?
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
package com.lee.wait;
 
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
 
/**
  * BTree二叉排序树类
  *
  * @author wait
  *
  */
public class BTree {
     /**
      * 树的根节点
      */
     public Node root;
     /**
      * 记录树的节点个数
      */
     public int size;
 
     /**
      * 默认构造函数,树的根节点为null
      */
     public BTree() {
         root = null ;
         size = 0 ;
     }
 
     /**
      * 插入一个新的节点node
      *
      * @param node
      */
     public void insert(Node node) {
         if (root == null ) {
             root = node;
             size++;
             return ;
         }
         Node current = root;
         while ( true ) {
             if (node.data <= current.data) {
                 // 如果插入节点的值小于当前节点的值,说明应该插入到当前节点左子树,而此时如果左子树为空,就直接设置当前节点的左子树为插入节点。
                 if (current.left == null ) {
                     current.left = node;
                     size++;
                     return ;
                 }
                 current = current.left;
             } else {
                 // 如果插入节点的值大于当前节点的值,说明应该插入到当前节点右子树,而此时如果右子树为空,就直接设置当前节点的右子树为插入节点。
                 if (current.right == null ) {
                     current.right = node;
                     size++;
                     return ;
                 }
                 current = current.right;
             }
         }
     }
 
     /**
      * 插入一个值为data的节点
      *
      * @param data
      */
     public void insert( int data) {
         insert( new Node(data));
     }
 
     /**
      * 根据int数组里面的值建立一个二叉排序树
      *
      * @param datas
      */
     public void bulidTree( int [] datas) {
         for ( int i = 0 , len = datas.length; i < len; i++) {
             insert(datas[i]);
         }
     }
 
     /**
      * 返回二叉排序树的层次遍历的结果,使用通用的广度优先遍历方法
      *
      * @return 以int数组的形式返回结果
      */
     public int [] layerOrder() {
         int [] res = new int [size];
         if (root == null ) {
             return res;
         }
         // 用一个队列存储节点的顺序,一次放入根节点,根的左孩子节点,根的右孩子节点
         Queue<node> queue = new LinkedList<node>();
         queue.offer(root);
 
         int i = 0 ;
         while (!queue.isEmpty()) {
             Node current = queue.poll();
             res[i++] = current.data;
             if (current.left != null ) {
                 queue.offer(current.left);
             }
             if (current.right != null ) {
                 queue.offer(current.right);
             }
         }
         return res;
     }
 
     /**
      * 先序遍历二叉排序树,非递归的方法,深度优先思想
      *
      * @return 以int数组的形式返回结果
      */
     public int [] preOrder() {
         int [] res = new int [size];
         int i = 0 ;
         //使用stack存储遍历到的节点
         Stack<node> stack = new Stack<node>();
         Node node = root;
         while (node != null ) {
             //一直往下遍历,知道到左孩子节点为空
             while (node != null ) {
                 stack.push(node);
                 res[i++] = node.data;
                 node = node.left;
             }
             //左孩子节点为空之后,往后找,如果找到的上一个节点的右孩子节点为空,那么继续往上找,直到找到一个右孩子节点不为空的
             while (!stack.isEmpty() && stack.peek().right == null ) {
                 node = stack.pop();
             }
             if (!stack.isEmpty()){
                 node=stack.pop();
                 //找到了一个右孩子节点不为空的节点,就去遍历他的右孩子节点
                 if (node != null ) {
                     node = node.right;
                 }
             } else {
                 node= null ;
             }
         }
         return res;
     }
 
     /**
      * 中序遍历二叉排序树  非递归的方法,深度优先思想
      * @return
      */
     public int [] inOrder() {
         int [] res = new int [size];
         int i = 0 ;
         //使用stack存储遍历到的节点
         Stack<node> stack = new Stack<node>();
         Node node = root;
         while (node != null ) {
             //一直往下遍历,知道到左孩子节点为空
             while (node != null ) {
                 stack.push(node);
                 node = node.left;
             }
             //左孩子节点为空之后,往后找,找到上一个节点.如果找到的上一个节点的右孩子节点为空,那么继续往上找,直到找到一个右孩子节点不为空的
             while (!stack.isEmpty() && stack.peek().right == null ) {
                 node = stack.pop();
                 res[i++] = node.data;
             }
             if (!stack.isEmpty()) {
                 node = stack.pop();
                 res[i++] = node.data;
                 //找到了一个右孩子节点不为空的节点,就去遍历他的右孩子节点
                 if (node != null ) {
                     node = node.right;
                 }
             } else {
                 node= null ;
             }
 
         }
         return res;
     }
 
 
     /**
      * 后序遍历二叉排序树  非递归的方法,深度优先思想
      * @return
      */
     public int [] postOrder() {
         int [] res = new int [size];
         int i = 0 ;
         //使用stack存储遍历到的节点
         Stack<node> stack = new Stack<node>();
         Node node = root;
         //存储每个节点是否访问被回访过,也就是是否是从左子树还是右子树回访的。
         Stack< boolean > stackFlag= new Stack< boolean >();
 
         while (node != null ) {
             //一直往下遍历,知道到左孩子节点为空
             while (node != null ) {
                 stack.push(node);
                 stackFlag.add( false );
                 node = node.left;
             }
             //左孩子节点为空之后,往后找,找到上一个节点.如果找到的上一个节点的右孩子节点为空,那么继续往上找,直到找到一个右孩子节点不为空的
             while (!stack.isEmpty() && (stack.peek().right == null ||stackFlag.peek()== true )) {
                 node = stack.pop();
                 stackFlag.pop();
                 res[i++] = node.data;
             }
             if (!stack.isEmpty()) {
                 node=stack.peek();
                 stackFlag.pop();
                 stackFlag.add( true );
                 //找到了一个右孩子节点不为空的节点,就去遍历他的右孩子节点
                 if (node != null ) {
                     node = node.right;
                 }
             } else {
                 node= null ;
             }
 
         }
         return res;
     }
     /**
      * 先序遍历,递归方法实现
      * @param node 当前访问的节点
      * @param list 存储节点值的容器
      */
     private void preOrderRe(Node node,List<integer> list){
 
         if (list== null ){
             list= new ArrayList<>();
         }
         if (node== null ){
             return ;
         }
         list.add(node.data);
         if (node.left!= null ){
             preOrderRe(node.left,list);
         }
         if (node.right!= null ){
             preOrderRe(node.right,list);
         }
     }
     /**
      * 先序遍历,递归 调用上面实现函数
      * @return
      */
     public int [] preOrderRe(){
         List<integer> list = new ArrayList<>();
         preOrderRe(root, list);
         int [] res= new int [size];
         for ( int i= 0 ,size=list.size();i<size;i++){ integer= "" list= "" node= "" param= "" private = "" return = "" void = "" > list){
 
         if (list== null ){
             list= new ArrayList<>();
         }
         if (node== null ){
             return ;
         }
         if (node.left!= null ){
             inOrderRe(node.left,list);
         }
         list.add(node.data);
         if (node.right!= null ){
             inOrderRe(node.right,list);
         }
     }
     /**
      * 中序遍历,递归 调用上面实现函数
      * @return
      */
     public int [] inOrderRe(){
         List<integer> list = new ArrayList<>();
         inOrderRe(root, list);
         int [] res= new int [size];
         for ( int i= 0 ,size=list.size();i<size;i++){ integer= "" list= "" node= "" param= "" private = "" return = "" void = "" > list){
 
         if (list== null ){
             list= new ArrayList<>();
         }
         if (node== null ){
             return ;
         }
         if (node.left!= null ){
             postOrderRe(node.left,list);
         }
         if (node.right!= null ){
             postOrderRe(node.right,list);
         }
         list.add(node.data);
     }
     /**
      * 后序遍历,递归 调用上面实现函数
      * @return
      */
     public int [] postOrderRe(){
         List<integer> list = new ArrayList<>();
         postOrderRe(root, list);
         int [] res= new int [size];
         for ( int i= 0 ,size=list.size();i<size;i++){ pre= "" return = "" ><p>( 3 ) 测试代码TestBTree.java</p><pre class = "brush:java;" > package com.lee.wait;
 
public class TestBTree {
     /**
      **********************************************************
      * 下面是测试代码,测试二叉排序树每个方法的结果
      **********************************************************
      */
     @org .junit.Test
     public void testInOrder() {
         int [] datas={ 2 , 8 , 7 , 4 , 9 , 3 , 1 , 6 , 7 , 5 };
         BTree bt= new BTree();
         bt.bulidTree(datas);
         int [] res = bt.inOrder();
         System.out.print( "中序遍历(非递):" );
         for ( int i= 0 ,len=res.length;i<len;i++){ bt= "new" btree= "" datas= "{2,8,7,4,9,3,1,6,7,5};" i= "0,len=res.length;i<len;i++){" int = "" org.junit.test= "" pre= "" public = "" res= "bt.preOrder();" void = "" >
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值