Skip to content

Commit 4008e49

Browse files
authored
Add treap class (#5563)
1 parent 07cb6c4 commit 4008e49

File tree

2 files changed

+419
-0
lines changed
  • src
    • main/java/com/thealgorithms/datastructures/trees
    • test/java/com/thealgorithms/datastructures/trees

2 files changed

+419
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
package com.thealgorithms.datastructures.trees;
2+
3+
import java.util.Random;
4+
5+
/**
6+
* Treap -> Tree + Heap
7+
* Also called as cartesian tree
8+
*
9+
* @see
10+
* <a href = "https://cp-algorithms.com/data_structures/treap.html" />
11+
*/
12+
13+
public class Treap {
14+
15+
public static class TreapNode {
16+
/**
17+
* TreapNode class defines the individual nodes in the Treap
18+
*
19+
* value -> holds the value of the node.
20+
* Binary Search Tree is built based on value.
21+
*
22+
* priority -> holds the priority of the node.
23+
* Heaps are maintained based on priority.
24+
* It is randomly assigned
25+
*
26+
* size -> holds the size of the subtree with current node as root
27+
*
28+
* left -> holds the left subtree
29+
* right -> holds the right subtree
30+
*/
31+
public int value;
32+
private int priority;
33+
private int size;
34+
public TreapNode left;
35+
public TreapNode right;
36+
37+
public TreapNode(int valueParam, int priorityParam) {
38+
value = valueParam;
39+
priority = priorityParam;
40+
size = 1;
41+
left = null;
42+
right = null;
43+
}
44+
45+
/**
46+
* updateSize -> updates the subtree size of the current node
47+
*/
48+
private void updateSize() {
49+
size = 1;
50+
if (left != null) {
51+
size += left.size;
52+
}
53+
if (right != null) {
54+
size += right.size;
55+
}
56+
}
57+
}
58+
59+
/**
60+
* root -> holds the root node in the Treap
61+
* random -> to generate random priority for the nodes in the Treap
62+
*/
63+
private TreapNode root;
64+
private Random random = new Random();
65+
66+
/**
67+
* Constructors
68+
*
69+
* Treap() -> create an empty Treap
70+
* Treap(int[] nodeValues) -> add the elements given in the array to the Treap
71+
*/
72+
public Treap() {
73+
root = null;
74+
}
75+
76+
/**
77+
* merges two Treaps left and right into a single Treap
78+
*
79+
* @param left left Treap
80+
* @param right right Treap
81+
* @return root of merged Treap
82+
*/
83+
private TreapNode merge(TreapNode left, TreapNode right) {
84+
if (left == null) {
85+
return right;
86+
}
87+
if (right == null) {
88+
return left;
89+
}
90+
91+
if (left.priority > right.priority) {
92+
left.right = merge(left.right, right);
93+
left.updateSize();
94+
return left;
95+
} else {
96+
right.left = merge(left, right.left);
97+
right.updateSize();
98+
return right;
99+
}
100+
}
101+
102+
/**
103+
* split the Treap into two Treaps where left Treap has nodes <= key and right Treap has nodes > key
104+
*
105+
* @param node root node to be split
106+
* @param key key to compare the nodes
107+
* @return TreapNode array of size 2.
108+
* TreapNode[0] contains the root of left Treap after split
109+
* TreapNode[1] contains the root of right Treap after split
110+
*/
111+
private TreapNode[] split(TreapNode node, int key) {
112+
if (node == null) {
113+
return new TreapNode[] {null, null};
114+
}
115+
116+
TreapNode[] result;
117+
118+
if (node.value <= key) {
119+
result = split(node.right, key);
120+
node.right = result[0];
121+
node.updateSize();
122+
result[0] = node;
123+
} else {
124+
result = split(node.left, key);
125+
node.left = result[1];
126+
node.updateSize();
127+
result[1] = node;
128+
}
129+
130+
return result;
131+
}
132+
133+
/**
134+
* insert a node into the Treap
135+
*
136+
* @param value value to be inserted into the Treap
137+
* @return root of the Treap where the value is inserted
138+
*/
139+
public TreapNode insert(int value) {
140+
if (root == null) {
141+
root = new TreapNode(value, random.nextInt());
142+
return root;
143+
}
144+
145+
TreapNode[] splitted = split(root, value);
146+
147+
TreapNode node = new TreapNode(value, random.nextInt());
148+
149+
TreapNode tempMerged = merge(splitted[0], node);
150+
tempMerged.updateSize();
151+
152+
TreapNode merged = merge(tempMerged, splitted[1]);
153+
merged.updateSize();
154+
155+
root = merged;
156+
157+
return root;
158+
}
159+
160+
/**
161+
* delete a value from root if present
162+
*
163+
* @param value value to be deleted from the Treap
164+
* @return root of the Treap where delete has been performed
165+
*/
166+
public TreapNode delete(int value) {
167+
root = deleteNode(root, value);
168+
return root;
169+
}
170+
171+
private TreapNode deleteNode(TreapNode root, int value) {
172+
if (root == null) {
173+
return null;
174+
}
175+
176+
if (value < root.value) {
177+
root.left = deleteNode(root.left, value);
178+
} else if (value > root.value) {
179+
root.right = deleteNode(root.right, value);
180+
} else {
181+
root = merge(root.left, root.right);
182+
}
183+
184+
if (root != null) {
185+
root.updateSize();
186+
}
187+
return root;
188+
}
189+
190+
/**
191+
* print inorder traversal of the Treap
192+
*/
193+
public void inOrder() {
194+
System.out.print("{");
195+
printInorder(root);
196+
System.out.print("}");
197+
}
198+
199+
private void printInorder(TreapNode root) {
200+
if (root == null) {
201+
return;
202+
}
203+
printInorder(root.left);
204+
System.out.print(root.value + ",");
205+
printInorder(root.right);
206+
}
207+
208+
/**
209+
* print preOrder traversal of the Treap
210+
*/
211+
public void preOrder() {
212+
System.out.print("{");
213+
printPreOrder(root);
214+
System.out.print("}");
215+
}
216+
217+
private void printPreOrder(TreapNode root) {
218+
if (root == null) {
219+
return;
220+
}
221+
System.out.print(root.value + ",");
222+
printPreOrder(root.left);
223+
printPreOrder(root.right);
224+
}
225+
226+
/**
227+
* print postOrder traversal of the Treap
228+
*/
229+
public void postOrder() {
230+
System.out.print("{");
231+
printPostOrder(root);
232+
System.out.print("}");
233+
}
234+
235+
private void printPostOrder(TreapNode root) {
236+
if (root == null) {
237+
return;
238+
}
239+
printPostOrder(root.left);
240+
printPostOrder(root.right);
241+
System.out.print(root.value + ",");
242+
}
243+
244+
/**
245+
* Search a value in the Treap
246+
*
247+
* @param value value to be searched for
248+
* @return node containing the value
249+
* null if not found
250+
*/
251+
public TreapNode search(int value) {
252+
return searchVal(root, value);
253+
}
254+
255+
private TreapNode searchVal(TreapNode root, int value) {
256+
if (root == null) {
257+
return null;
258+
}
259+
260+
if (root.value == value) {
261+
return root;
262+
} else if (root.value < value) {
263+
return searchVal(root.right, value);
264+
} else {
265+
return searchVal(root.left, value);
266+
}
267+
}
268+
269+
/**
270+
* find the lowerBound of a value in the Treap
271+
*
272+
* @param value value for which lowerBound is to be found
273+
* @return node which is the lowerBound of the value passed
274+
*/
275+
public TreapNode lowerBound(int value) {
276+
TreapNode lowerBoundNode = null;
277+
TreapNode current = root;
278+
279+
while (current != null) {
280+
if (current.value >= value) {
281+
lowerBoundNode = current;
282+
current = current.left;
283+
} else {
284+
current = current.right;
285+
}
286+
}
287+
288+
return lowerBoundNode;
289+
}
290+
291+
/**
292+
* find the upperBound of a value in the Treap
293+
*
294+
* @param value value for which upperBound is to be found
295+
* @return node which is the upperBound of the value passed
296+
*/
297+
public TreapNode upperBound(int value) {
298+
TreapNode upperBoundNode = null;
299+
TreapNode current = root;
300+
301+
while (current != null) {
302+
if (current.value > value) {
303+
upperBoundNode = current;
304+
current = current.left;
305+
} else {
306+
current = current.right;
307+
}
308+
}
309+
310+
return upperBoundNode;
311+
}
312+
313+
/**
314+
* returns size of the Treap
315+
*/
316+
public int size() {
317+
if (root == null) {
318+
return 0;
319+
}
320+
return root.size;
321+
}
322+
323+
/**
324+
* returns if Treap is empty
325+
*/
326+
public boolean isEmpty() {
327+
return root == null;
328+
}
329+
330+
/**
331+
* returns root node of the Treap
332+
*/
333+
public TreapNode getRoot() {
334+
return root;
335+
}
336+
337+
/**
338+
* returns left node of the TreapNode
339+
*/
340+
public TreapNode getLeft(TreapNode node) {
341+
return node.left;
342+
}
343+
344+
/**
345+
* returns the right node of the TreapNode
346+
*/
347+
public TreapNode getRight(TreapNode node) {
348+
return node.right;
349+
}
350+
351+
/**
352+
* prints the value, priority, size of the subtree of the TreapNode, left TreapNode and right TreapNode of the node
353+
*/
354+
public String toString(TreapNode node) {
355+
return "{value : " + node.value + ", priority : " + node.priority + ", subTreeSize = " + node.size + ", left = " + node.left + ", right = " + node.right + "}";
356+
}
357+
}

0 commit comments

Comments
 (0)