@@ -13,8 +13,13 @@ class ThreadedBinaryNode<V extends Comparable>
13
13
14
14
/// Stores if [right] is a thread.
15
15
bool rightIsThread;
16
+
17
+ ThreadedBinaryNode (this .value,
18
+ {this .leftIsThread = true , this .rightIsThread = true });
16
19
}
17
20
21
+ enum _DeleteCase { twoChildren, oneChild, childless }
22
+
18
23
/// A [BinaryTree] is threaded by making all [right] pointers that would
19
24
/// normally be null point to the in-order successor of the node
20
25
/// (if it exists), and all [left] pointers that would normally be null point
@@ -25,21 +30,213 @@ class ThreadedBinaryTree<V extends Comparable>
25
30
26
31
@override
27
32
void add (V value) {
28
- throw UnimplementedError ();
33
+ ThreadedBinaryNode parent, node = root;
34
+ var isPresent = false ;
35
+
36
+ while (node != null ) {
37
+ if (node.value.compareTo (value) == 0 ) {
38
+ isPresent = true ;
39
+ break ;
40
+ }
41
+
42
+ parent = node;
43
+ if (node.value.compareTo (value) > 0 ) {
44
+ if (! node.leftIsThread) {
45
+ node = node.left;
46
+ } else {
47
+ break ;
48
+ }
49
+ } else if (! node.rightIsThread) {
50
+ node = node.right;
51
+ } else {
52
+ break ;
53
+ }
54
+ }
55
+
56
+ if (! isPresent) {
57
+ var newNode = ThreadedBinaryNode (value);
58
+
59
+ if (parent == null ) {
60
+ root = newNode;
61
+ } else if (parent.value.compareTo (value) > 0 ) {
62
+ newNode.left = parent.left;
63
+ newNode.right = parent;
64
+ parent.leftIsThread = false ;
65
+ parent.left = newNode;
66
+ } else {
67
+ newNode.left = parent;
68
+ newNode.right = parent.right;
69
+ parent.rightIsThread = false ;
70
+ parent.right = newNode;
71
+ }
72
+ }
29
73
}
30
74
31
75
@override
32
76
void delete (V value) {
33
- throw UnimplementedError ();
77
+ ThreadedBinaryNode parent, node = root;
78
+ var isPresent = false ;
79
+
80
+ while (node != null ) {
81
+ if (node.value.compareTo (value) == 0 ) {
82
+ isPresent = true ;
83
+ break ;
84
+ }
85
+
86
+ parent = node;
87
+ if (node.value.compareTo (value) > 0 ) {
88
+ if (! node.leftIsThread) {
89
+ node = node.left;
90
+ } else {
91
+ break ;
92
+ }
93
+ } else if (! node.rightIsThread) {
94
+ node = node.right;
95
+ } else {
96
+ break ;
97
+ }
98
+ }
99
+
100
+ if (isPresent) {
101
+ if (! node.leftIsThread && ! node.rightIsThread) {
102
+ // Node has 2 children.
103
+ _delete (parent, node, _DeleteCase .twoChildren);
104
+ } else if (! node.leftIsThread) {
105
+ // Node has only a left child.
106
+ _delete (parent, node, _DeleteCase .oneChild);
107
+ } else if (! node.rightIsThread) {
108
+ // Node has only a right child.
109
+ _delete (parent, node, _DeleteCase .oneChild);
110
+ } else {
111
+ // Node is childless.
112
+ _delete (parent, node, _DeleteCase .childless);
113
+ }
114
+ }
115
+ }
116
+
117
+ void _delete (ThreadedBinaryNode parent, ThreadedBinaryNode node,
118
+ _DeleteCase deleteCase) {
119
+ switch (deleteCase) {
120
+ case _DeleteCase .childless:
121
+ if (parent == null ) {
122
+ nullify ();
123
+ } else if (node == parent.left) {
124
+ parent.leftIsThread = true ;
125
+ parent.left = node.left;
126
+ } else {
127
+ parent.rightIsThread = true ;
128
+ parent.right = node.right;
129
+ }
130
+ break ;
131
+
132
+ case _DeleteCase .oneChild:
133
+ var child = node.leftIsThread ? node.right : node.left;
134
+
135
+ if (parent == null ) {
136
+ root = child;
137
+ } else if (node == parent.left) {
138
+ parent.left = child;
139
+ } else {
140
+ parent.right = child;
141
+ }
142
+
143
+ var successor = _inOrderSuccessor (node);
144
+ var predecessor = _inOrderPredecessor (node);
145
+ if (! node.leftIsThread) {
146
+ predecessor.right = successor;
147
+ } else {
148
+ if (! node.rightIsThread) {
149
+ successor.left = predecessor;
150
+ }
151
+ }
152
+ break ;
153
+
154
+ case _DeleteCase .twoChildren:
155
+ ThreadedBinaryNode successor, parentSuccessor;
156
+ parentSuccessor = node;
157
+ successor = node.right;
158
+
159
+ while (successor.left != null ) {
160
+ parentSuccessor = successor;
161
+ successor = successor.left;
162
+ }
163
+
164
+ node.value = successor.value;
165
+
166
+ if (successor.leftIsThread && successor.rightIsThread) {
167
+ _delete (parentSuccessor, successor, _DeleteCase .childless);
168
+ } else {
169
+ _delete (parentSuccessor, successor, _DeleteCase .oneChild);
170
+ }
171
+ break ;
172
+ }
34
173
}
35
174
36
175
@override
37
176
List <V > inOrder () {
38
- throw UnimplementedError ();
177
+ var result = < V > [];
178
+ if (isEmpty) return result;
179
+
180
+ var node = root;
181
+ while (! node.leftIsThread) {
182
+ node = node.left;
183
+ }
184
+
185
+ while (node.rightIsThread) {
186
+ result.add (node.value);
187
+ node = _inOrderSuccessor (node);
188
+ }
189
+ return result;
39
190
}
40
191
41
192
@override
42
193
List <V > preOrder () {
43
- throw UnimplementedError ();
194
+ var result = < V > [];
195
+ if (isEmpty) return result;
196
+
197
+ var node = root;
198
+ while (node != null ) {
199
+ result.add (node.value);
200
+ if (! node.leftIsThread) {
201
+ node = node.left;
202
+ } else if (! node.rightIsThread) {
203
+ node = node.right;
204
+ } else {
205
+ while (node != null && node.rightIsThread) {
206
+ node = node.right;
207
+ }
208
+
209
+ if (node != null ) {
210
+ node = node.right;
211
+ }
212
+ }
213
+ }
214
+ return result;
215
+ }
216
+
217
+ ThreadedBinaryNode _inOrderSuccessor (ThreadedBinaryNode node) {
218
+ if (node.rightIsThread) {
219
+ return node.right;
220
+ } else {
221
+ node = node.right;
222
+
223
+ while (! node.leftIsThread) {
224
+ node = node.left;
225
+ }
226
+ return node;
227
+ }
228
+ }
229
+
230
+ ThreadedBinaryNode _inOrderPredecessor (ThreadedBinaryNode node) {
231
+ if (node.leftIsThread) {
232
+ return node.left;
233
+ } else {
234
+ node = node.left;
235
+
236
+ while (! node.rightIsThread) {
237
+ node = node.right;
238
+ }
239
+ return node;
240
+ }
44
241
}
45
242
}
0 commit comments