Skip to content

Commit ccab31a

Browse files
committed
Add functions in ThreadedBinaryTree.
1 parent 40658dc commit ccab31a

File tree

1 file changed

+201
-4
lines changed

1 file changed

+201
-4
lines changed

Diff for: lib/trees/threaded_binary_tree.dart

+201-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ class ThreadedBinaryNode<V extends Comparable>
1313

1414
/// Stores if [right] is a thread.
1515
bool rightIsThread;
16+
17+
ThreadedBinaryNode(this.value,
18+
{this.leftIsThread = true, this.rightIsThread = true});
1619
}
1720

21+
enum _DeleteCase { twoChildren, oneChild, childless }
22+
1823
/// A [BinaryTree] is threaded by making all [right] pointers that would
1924
/// normally be null point to the in-order successor of the node
2025
/// (if it exists), and all [left] pointers that would normally be null point
@@ -25,21 +30,213 @@ class ThreadedBinaryTree<V extends Comparable>
2530

2631
@override
2732
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+
}
2973
}
3074

3175
@override
3276
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+
}
34173
}
35174

36175
@override
37176
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;
39190
}
40191

41192
@override
42193
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+
}
44241
}
45242
}

0 commit comments

Comments
 (0)