1
+ /*
2
+ * @Descripttion :
3
+ * @version :
4
+ * @Author : wenlan
5
+ * @Date : 2022-03-24 21:18:58
6
+ * @LastEditors : wenlan
7
+ * @LastEditTime : 2022-03-25 17:31:58
8
+ */
9
+ //节点类
10
+
11
+ class BinarySearchTree {
12
+ root = null ;
13
+ node = class Node {
14
+ constructor ( key ) {
15
+ this . left = null ;
16
+ this . key = key ;
17
+ this . right = null ;
18
+ }
19
+ } ;
20
+ constructor ( ) { }
21
+ //插入数据
22
+ insert ( key ) {
23
+ //创建新节点
24
+ const newNode = new this . node ( key ) ;
25
+ //没有根节点
26
+ if ( this . root === null ) {
27
+ this . root = newNode ;
28
+ } else {
29
+ this . insertNode ( this . root , newNode ) ;
30
+ }
31
+ }
32
+ //比较传入两个节点 root newNode
33
+ insertNode ( node , newNode ) {
34
+ //向左查找
35
+ if ( newNode . key < node . key ) {
36
+ //如果左节点为空
37
+ if ( node . left === null ) {
38
+ node . left = newNode ;
39
+ } else {
40
+ //继续递归下一个左节点
41
+ this . insertNode ( node . left , newNode ) ;
42
+ }
43
+ }
44
+ //向右查找
45
+ else {
46
+ if ( node . right === null ) {
47
+ node . right = newNode ;
48
+ } else {
49
+ this . insertNode ( node . right , newNode ) ;
50
+ }
51
+ }
52
+ }
53
+ //遍历二叉搜索树 DLR
54
+ // 先序遍历; 1 访问根节点 2访问左子树 3 访问右子树
55
+ //栈结构:
56
+ // DLR(5)
57
+ // -- DLR(NULL) [1,2,3,4]
58
+ // -- DLR(4) [1,2,3,4]
59
+ // DLR(3) [1,2,3]
60
+ // DLR(2) [1,2]
61
+ // DLR(1) [1]
62
+ preorderTraversal ( ) {
63
+ const result = [ ] ;
64
+ this . preorderTraversalNode ( this . root , result ) ;
65
+ return result ;
66
+ }
67
+ //DLR内部方法 递归
68
+ preorderTraversalNode ( node , result ) {
69
+ if ( node === null ) return result ;
70
+ result . push ( node . key ) ;
71
+ this . preorderTraversalNode ( node . left , result ) ;
72
+ this . preorderTraversalNode ( node . right , result ) ;
73
+ }
74
+ //中序遍历LDR
75
+ inorderTraversal ( ) {
76
+ const result = [ ] ;
77
+ this . inorderTraversalNode ( this . root , result ) ;
78
+ return result ;
79
+ }
80
+ inorderTraversalNode ( node , result ) {
81
+ if ( node === null ) return result ;
82
+ this . inorderTraversalNode ( node . left , result ) ;
83
+ result . push ( node . key ) ;
84
+ this . inorderTraversalNode ( node . right , result ) ;
85
+ }
86
+ //后序遍历(左右根 LRD)
87
+ postorderTraversal ( ) {
88
+ const result = [ ] ;
89
+ this . postorderTraversalNode ( this . root , result ) ;
90
+ return result ;
91
+ }
92
+
93
+ postorderTraversalNode ( node , result ) {
94
+ if ( node === null ) return result ;
95
+ this . postorderTraversalNode ( node . left , result ) ;
96
+ this . postorderTraversalNode ( node . right , result ) ;
97
+ result . push ( node . key ) ;
98
+ }
99
+ //最小值
100
+ min ( ) {
101
+ if ( ! this . root ) return null ;
102
+ let node = this . root ;
103
+ while ( node . left !== null ) {
104
+ node = node . left ;
105
+ }
106
+ return node ;
107
+ }
108
+ // //最小值
109
+ max ( ) {
110
+ if ( ! this . root ) return null ;
111
+ let node = this . root ;
112
+ while ( node . right !== null ) {
113
+ node = node . right ;
114
+ }
115
+ return node ;
116
+ }
117
+ //寻找特定的值
118
+ search ( key ) {
119
+ return this . searchNode ( this . root , key ) ;
120
+ }
121
+ searchNode ( node , key ) {
122
+ if ( node === null ) return false ;
123
+ if ( key < node . key ) {
124
+ return this . searchNode ( node . left , key ) ;
125
+ } else if ( key > node . key ) {
126
+ return this . searchNode ( node . right , key ) ;
127
+ } else {
128
+ return { message : true , node } ;
129
+ }
130
+ }
131
+ //删除数据
132
+ // 1 先找到需要删除的节点 若没找到 则不需要删除
133
+ // 首先定义变量current 用于保存需要删除的节点 parent表示父亲节点 isleft保存current是否parent的左节点
134
+ // 这样方便删除之后删除相关节点的指向
135
+ // 删除节点
136
+ remove ( key ) {
137
+ let currentNode = this . root ;
138
+ let parentNode = null ;
139
+ let isLeftChild = true ;
140
+
141
+ // 循环查找到要删除的节点 currentNode,以及它的 parentNode、isLeftChild
142
+ while ( currentNode . key !== key ) {
143
+ parentNode = currentNode ;
144
+
145
+ // 小于,往左查找
146
+ if ( key < currentNode . key ) {
147
+ isLeftChild = true ;
148
+ currentNode = currentNode . left ;
149
+ } else {
150
+ // 否则往右查找
151
+ isLeftChild = false ;
152
+ currentNode = currentNode . right ;
153
+ }
154
+
155
+ // 找到最后都没找到相等的节点,返回 false
156
+ if ( currentNode === null ) {
157
+ return false ;
158
+ }
159
+ }
160
+
161
+ // 1、删除的是叶子节点的情况
162
+ if ( currentNode . left === null && currentNode . right === null ) {
163
+ if ( currentNode === this . root ) {
164
+ this . root = null ;
165
+ } else if ( isLeftChild ) {
166
+ parentNode . left = null ;
167
+ } else {
168
+ parentNode . right = null ;
169
+ }
170
+
171
+ // 2、删除的是只有一个子节点的节点
172
+ } else if ( currentNode . right === null ) {
173
+ // currentNode 只存在左节点
174
+ //-- 2.1、currentNode 只存在<左节点>的情况
175
+ //---- 2.1.1、currentNode 等于 root
176
+ //---- 2.1.2、parentNode.left 等于 currentNode
177
+ //---- 2.1.3、parentNode.right 等于 currentNode
178
+
179
+ if ( currentNode === this . root ) {
180
+ this . root = currentNode . left ;
181
+ } else if ( isLeftChild ) {
182
+ parentNode . left = currentNode . left ;
183
+ } else {
184
+ parentNode . right = currentNode . left ;
185
+ }
186
+ } else if ( currentNode . left === null ) {
187
+ // currentNode 只存在右节点
188
+ //-- 2.2、currentNode 只存在<右节点>的情况
189
+ //---- 2.1.1 currentNode 等于 root
190
+ //---- 2.1.1 parentNode.left 等于 currentNode
191
+ //---- 2.1.1 parentNode.right 等于 currentNode
192
+
193
+ if ( currentNode === this . root ) {
194
+ this . root = currentNode . right ;
195
+ } else if ( isLeftChild ) {
196
+ parentNode . left = currentNode . right ;
197
+ } else {
198
+ parentNode . right = currentNode . right ;
199
+ }
200
+
201
+ // 3、删除的是有两个子节点的节点
202
+ } else {
203
+ // 1、找到后续节点
204
+ let successor = this . getSuccessor ( currentNode ) ;
205
+
206
+ // 2、判断是否为根节点
207
+ if ( currentNode === this . root ) {
208
+ this . root = successor ;
209
+ } else if ( isLeftChild ) {
210
+ parentNode . left = successor ;
211
+ } else {
212
+ parentNode . right = successor ;
213
+ }
214
+
215
+ // 3、将后续的左节点改为被删除的左节点
216
+ successor . left = currentNode . left ;
217
+ }
218
+ }
219
+
220
+ // 获取后续节点,即从要删除的节点的右边开始查找最小的值
221
+ getSuccessor ( delNode ) {
222
+ // 定义变量,保存要找到的后续
223
+ let successor = delNode ;
224
+ let current = delNode . right ;
225
+ let successorParent = delNode ;
226
+
227
+ // 循环查找 current 的右子树节点
228
+ while ( current !== null ) {
229
+ successorParent = successor ;
230
+ successor = current ;
231
+ current = current . left ;
232
+ }
233
+
234
+ // 判断寻找到的后续节点是否直接就是要删除节点的 right
235
+ if ( successor !== delNode . right ) {
236
+ successorParent . left = successor . right ;
237
+ successor . right = delNode . right ;
238
+ }
239
+ return successor ;
240
+ }
241
+ }
242
+ //test
243
+ const BST = new BinarySearchTree ( ) ;
244
+ BST . insert ( 11 ) ;
245
+ BST . insert ( 7 ) ;
246
+ BST . insert ( 15 ) ;
247
+ BST . insert ( 5 ) ;
248
+ BST . insert ( 9 ) ;
249
+ BST . insert ( 8 ) ;
250
+ BST . insert ( 10 ) ;
251
+ BST . insert ( 3 ) ;
252
+ BST . insert ( 6 ) ;
253
+ BST . insert ( 13 ) ;
254
+ BST . insert ( 12 ) ;
255
+ BST . insert ( 14 ) ;
256
+ BST . insert ( 20 ) ;
257
+ BST . insert ( 18 ) ;
258
+ BST . insert ( 25 ) ;
259
+ console . log ( BST ) ;
260
+ console . log ( "DLR" , BST . preorderTraversal ( ) ) ;
261
+ console . log ( "LRD" , BST . inorderTraversal ( ) ) ;
262
+ console . log ( "LRD" , BST . postorderTraversal ( ) ) ;
263
+ console . log ( "min" , BST . min ( ) ) ;
264
+ console . log ( "min" , BST . max ( ) ) ;
265
+ console . log ( "search" , BST . search ( 25 ) ) ;
266
+ console . log ( BST . remove ( 14 ) ) ;
267
+
268
+ //
0 commit comments