forked from TheAlgorithms/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThreadedBinaryTree.java
More file actions
145 lines (126 loc) · 4.06 KB
/
ThreadedBinaryTree.java
File metadata and controls
145 lines (126 loc) · 4.06 KB
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
/*
* TheAlgorithms (https://github.com/TheAlgorithms/Java)
* Author: Shewale41
* This file is licensed under the MIT License.
*/
package com.thealgorithms.datastructures.trees;
import java.util.ArrayList;
import java.util.List;
/**
* Threaded binary tree implementation that supports insertion and
* in-order traversal without recursion or stack by using threads.
*
* <p>In this implementation, a node's null left/right pointers are used
* to point to the in-order predecessor/successor respectively. Two flags
* indicate whether left/right pointers are real children or threads.
*
* @see <a href="https://en.wikipedia.org/wiki/Threaded_binary_tree">Wikipedia:
* Threaded binary tree</a>
*/
public final class ThreadedBinaryTree {
private Node root;
private static final class Node {
int value;
Node left;
Node right;
boolean leftIsThread;
boolean rightIsThread;
Node(int value) {
this.value = value;
this.left = null;
this.right = null;
this.leftIsThread = false;
this.rightIsThread = false;
}
}
public ThreadedBinaryTree() {
this.root = null;
}
/**
* Inserts a value into the threaded binary tree. Duplicate values are inserted
* to the right subtree (consistent deterministic rule).
*
* @param value the integer value to insert
*/
public void insert(int value) {
Node newNode = new Node(value);
if (root == null) {
root = newNode;
return;
}
Node current = root;
Node parent = null;
while (true) {
parent = current;
if (value < current.value) {
if (!current.leftIsThread && current.left != null) {
current = current.left;
} else {
break;
}
} else { // value >= current.value
if (!current.rightIsThread && current.right != null) {
current = current.right;
} else {
break;
}
}
}
if (value < parent.value) {
// attach newNode as left child
newNode.left = parent.left;
newNode.leftIsThread = parent.leftIsThread;
newNode.right = parent;
newNode.rightIsThread = true;
parent.left = newNode;
parent.leftIsThread = false;
} else {
// attach newNode as right child
newNode.right = parent.right;
newNode.rightIsThread = parent.rightIsThread;
newNode.left = parent;
newNode.leftIsThread = true;
parent.right = newNode;
parent.rightIsThread = false;
}
}
/**
* Returns the in-order traversal of the tree as a list of integers.
* Traversal is done without recursion or an explicit stack by following threads.
*
* @return list containing the in-order sequence of node values
*/
public List<Integer> inorderTraversal() {
List<Integer> result = new ArrayList<>();
Node current = root;
if (current == null) {
return result;
}
// Move to the leftmost node
while (current.left != null && !current.leftIsThread) {
current = current.left;
}
while (current != null) {
result.add(current.value);
// If right pointer is a thread, follow it
if (current.rightIsThread) {
current = current.right;
} else {
// Move to leftmost node in right subtree
current = current.right;
while (current != null && !current.leftIsThread && current.left != null) {
current = current.left;
}
}
}
return result;
}
/**
* Helper: checks whether the tree is empty.
*
* @return true if tree has no nodes
*/
public boolean isEmpty() {
return root == null;
}
}