Skip to content

Commit 179284a

Browse files
Hocnonsensecclauss
authored andcommitted
Update treap.py (TheAlgorithms#1358)
* Update treap.py check merge() * Update treap.py random() is used. its difficult to write doctests l->left r->right key->value add __repr__ and __str__ in preorder
1 parent 7376add commit 179284a

File tree

1 file changed

+116
-72
lines changed

1 file changed

+116
-72
lines changed

data_structures/binary_tree/treap.py

Lines changed: 116 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,129 +2,173 @@
22
from typing import Tuple
33

44

5-
class Node:
5+
class Node(object):
66
"""
77
Treap's node
8-
Treap is a binary tree by key and heap by priority
8+
Treap is a binary tree by value and heap by priority
99
"""
10-
11-
def __init__(self, key: int):
12-
self.key = key
10+
def __init__(self, value: int = None):
11+
self.value = value
1312
self.prior = random()
14-
self.l = None
15-
self.r = None
13+
self.left = None
14+
self.right = None
1615

16+
def __repr__(self):
17+
from pprint import pformat
1718

18-
def split(root: Node, key: int) -> Tuple[Node, Node]:
19+
if self.left is None and self.right is None:
20+
return "'%s: %.5s'" % (self.value, self.prior)
21+
else:
22+
return pformat(
23+
{
24+
"%s: %.5s"
25+
% (self.value, self.prior): (self.left, self.right)
26+
},
27+
indent=1,
28+
)
29+
30+
def __str__(self):
31+
value = str(self.value) + " "
32+
left = str(self.left or "")
33+
right = str(self.right or "")
34+
return value + left + right
35+
36+
def split(root: Node, value: int) -> Tuple[Node, Node]:
1937
"""
20-
We split current tree into 2 trees with key:
38+
We split current tree into 2 trees with value:
2139
22-
Left tree contains all keys less than split key.
23-
Right tree contains all keys greater or equal, than split key
40+
Left tree contains all values less than split value.
41+
Right tree contains all values greater or equal, than split value
2442
"""
2543
if root is None: # None tree is split into 2 Nones
2644
return (None, None)
27-
if root.key >= key:
28-
"""
29-
Right tree's root will be current node.
30-
Now we split(with the same key) current node's left son
31-
Left tree: left part of that split
32-
Right tree's left son: right part of that split
33-
"""
34-
l, root.l = split(root.l, key)
35-
return (l, root)
45+
elif root.value is None:
46+
return (None, None)
3647
else:
37-
"""
38-
Just symmetric to previous case
39-
"""
40-
root.r, r = split(root.r, key)
41-
return (root, r)
42-
48+
if value < root.value:
49+
"""
50+
Right tree's root will be current node.
51+
Now we split(with the same value) current node's left son
52+
Left tree: left part of that split
53+
Right tree's left son: right part of that split
54+
"""
55+
left, root.left = split(root.left, value)
56+
return (left, root)
57+
else:
58+
"""
59+
Just symmetric to previous case
60+
"""
61+
root.right, right = split(root.right, value)
62+
return (root, right)
4363

4464
def merge(left: Node, right: Node) -> Node:
4565
"""
4666
We merge 2 trees into one.
47-
Note: all left tree's keys must be less than all right tree's
67+
Note: all left tree's values must be less than all right tree's
4868
"""
49-
if (not left) or (not right):
50-
"""
51-
If one node is None, return the other
52-
"""
69+
if (not left) or (not right): # If one node is None, return the other
5370
return left or right
54-
if left.key > right.key:
71+
elif left.prior < right.prior:
5572
"""
5673
Left will be root because it has more priority
5774
Now we need to merge left's right son and right tree
5875
"""
59-
left.r = merge(left.r, right)
76+
left.right = merge(left.right, right)
6077
return left
6178
else:
6279
"""
6380
Symmetric as well
6481
"""
65-
right.l = merge(left, right.l)
82+
right.left = merge(left, right.left)
6683
return right
6784

68-
69-
def insert(root: Node, key: int) -> Node:
85+
def insert(root: Node, value: int) -> Node:
7086
"""
7187
Insert element
7288
73-
Split current tree with a key into l, r,
89+
Split current tree with a value into left, right,
7490
Insert new node into the middle
75-
Merge l, node, r into root
91+
Merge left, node, right into root
7692
"""
77-
node = Node(key)
78-
l, r = split(root, key)
79-
root = merge(l, node)
80-
root = merge(root, r)
81-
return root
93+
node = Node(value)
94+
left, right = split(root, value)
95+
return merge(merge(left, node), right)
8296

83-
84-
def erase(root: Node, key: int) -> Node:
97+
def erase(root: Node, value: int) -> Node:
8598
"""
8699
Erase element
87100
88-
Split all nodes with keys less into l,
89-
Split all nodes with keys greater into r.
90-
Merge l, r
101+
Split all nodes with values less into left,
102+
Split all nodes with values greater into right.
103+
Merge left, right
91104
"""
92-
l, r = split(root, key)
93-
_, r = split(r, key + 1)
94-
return merge(l, r)
95-
105+
left, right = split(root, value-1)
106+
_, right = split(right, value)
107+
return merge(left, right)
96108

97-
def node_print(root: Node):
109+
def inorder(root: Node):
98110
"""
99111
Just recursive print of a tree
100112
"""
101-
if not root:
113+
if not root: # None
102114
return
103-
node_print(root.l)
104-
print(root.key, end=" ")
105-
node_print(root.r)
115+
else:
116+
inorder(root.left)
117+
print(root.value, end=" ")
118+
inorder(root.right)
106119

107120

108-
def interactTreap():
121+
def interactTreap(root, args):
109122
"""
110123
Commands:
111-
+ key to add key into treap
112-
- key to erase all nodes with key
113-
114-
After each command, program prints treap
124+
+ value to add value into treap
125+
- value to erase all nodes with value
126+
127+
>>> root = interactTreap(None, "+1")
128+
>>> inorder(root)
129+
1
130+
>>> root = interactTreap(root, "+3 +5 +17 +19 +2 +16 +4 +0")
131+
>>> inorder(root)
132+
0 1 2 3 4 5 16 17 19
133+
>>> root = interactTreap(root, "+4 +4 +4")
134+
>>> inorder(root)
135+
0 1 2 3 4 4 4 4 5 16 17 19
136+
>>> root = interactTreap(root, "-0")
137+
>>> inorder(root)
138+
1 2 3 4 4 4 4 5 16 17 19
139+
>>> root = interactTreap(root, "-4")
140+
>>> inorder(root)
141+
1 2 3 5 16 17 19
142+
>>> root = interactTreap(root, "=0")
143+
Unknown command
115144
"""
116-
root = None
117-
while True:
118-
cmd = input().split()
119-
cmd[1] = int(cmd[1])
120-
if cmd[0] == "+":
121-
root = insert(root, cmd[1])
122-
elif cmd[0] == "-":
123-
root = erase(root, cmd[1])
145+
for arg in args.split():
146+
if arg[0] == "+":
147+
root = insert(root, int(arg[1:]))
148+
149+
elif arg[0] == "-":
150+
root = erase(root, int(arg[1:]))
151+
124152
else:
125153
print("Unknown command")
126-
node_print(root)
127154

155+
return root
156+
157+
def main():
158+
"""After each command, program prints treap"""
159+
root = None
160+
print("enter numbers to creat a tree, + value to add value into treap, - value to erase all nodes with value. 'q' to quit. ")
161+
162+
args = input()
163+
while args != 'q':
164+
root = interactTreap(root, args)
165+
print(root)
166+
args = input()
167+
168+
print("good by!")
169+
pass
128170

129171
if __name__ == "__main__":
130-
interactTreap()
172+
import doctest
173+
doctest.testmod()
174+
main()

0 commit comments

Comments
 (0)