mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-24 05:21:09 +00:00
Update treap.py (#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
This commit is contained in:
parent
7376addcd5
commit
179284a41b
|
@ -2,129 +2,173 @@ from random import random
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
class Node:
|
class Node(object):
|
||||||
"""
|
"""
|
||||||
Treap's node
|
Treap's node
|
||||||
Treap is a binary tree by key and heap by priority
|
Treap is a binary tree by value and heap by priority
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, value: int = None):
|
||||||
def __init__(self, key: int):
|
self.value = value
|
||||||
self.key = key
|
|
||||||
self.prior = random()
|
self.prior = random()
|
||||||
self.l = None
|
self.left = None
|
||||||
self.r = None
|
self.right = None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
from pprint import pformat
|
||||||
|
|
||||||
def split(root: Node, key: int) -> Tuple[Node, Node]:
|
if self.left is None and self.right is None:
|
||||||
|
return "'%s: %.5s'" % (self.value, self.prior)
|
||||||
|
else:
|
||||||
|
return pformat(
|
||||||
|
{
|
||||||
|
"%s: %.5s"
|
||||||
|
% (self.value, self.prior): (self.left, self.right)
|
||||||
|
},
|
||||||
|
indent=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
value = str(self.value) + " "
|
||||||
|
left = str(self.left or "")
|
||||||
|
right = str(self.right or "")
|
||||||
|
return value + left + right
|
||||||
|
|
||||||
|
def split(root: Node, value: int) -> Tuple[Node, Node]:
|
||||||
"""
|
"""
|
||||||
We split current tree into 2 trees with key:
|
We split current tree into 2 trees with value:
|
||||||
|
|
||||||
Left tree contains all keys less than split key.
|
Left tree contains all values less than split value.
|
||||||
Right tree contains all keys greater or equal, than split key
|
Right tree contains all values greater or equal, than split value
|
||||||
"""
|
"""
|
||||||
if root is None: # None tree is split into 2 Nones
|
if root is None: # None tree is split into 2 Nones
|
||||||
return (None, None)
|
return (None, None)
|
||||||
if root.key >= key:
|
elif root.value is None:
|
||||||
"""
|
return (None, None)
|
||||||
Right tree's root will be current node.
|
|
||||||
Now we split(with the same key) current node's left son
|
|
||||||
Left tree: left part of that split
|
|
||||||
Right tree's left son: right part of that split
|
|
||||||
"""
|
|
||||||
l, root.l = split(root.l, key)
|
|
||||||
return (l, root)
|
|
||||||
else:
|
else:
|
||||||
"""
|
if value < root.value:
|
||||||
Just symmetric to previous case
|
"""
|
||||||
"""
|
Right tree's root will be current node.
|
||||||
root.r, r = split(root.r, key)
|
Now we split(with the same value) current node's left son
|
||||||
return (root, r)
|
Left tree: left part of that split
|
||||||
|
Right tree's left son: right part of that split
|
||||||
|
"""
|
||||||
|
left, root.left = split(root.left, value)
|
||||||
|
return (left, root)
|
||||||
|
else:
|
||||||
|
"""
|
||||||
|
Just symmetric to previous case
|
||||||
|
"""
|
||||||
|
root.right, right = split(root.right, value)
|
||||||
|
return (root, right)
|
||||||
|
|
||||||
def merge(left: Node, right: Node) -> Node:
|
def merge(left: Node, right: Node) -> Node:
|
||||||
"""
|
"""
|
||||||
We merge 2 trees into one.
|
We merge 2 trees into one.
|
||||||
Note: all left tree's keys must be less than all right tree's
|
Note: all left tree's values must be less than all right tree's
|
||||||
"""
|
"""
|
||||||
if (not left) or (not right):
|
if (not left) or (not right): # If one node is None, return the other
|
||||||
"""
|
|
||||||
If one node is None, return the other
|
|
||||||
"""
|
|
||||||
return left or right
|
return left or right
|
||||||
if left.key > right.key:
|
elif left.prior < right.prior:
|
||||||
"""
|
"""
|
||||||
Left will be root because it has more priority
|
Left will be root because it has more priority
|
||||||
Now we need to merge left's right son and right tree
|
Now we need to merge left's right son and right tree
|
||||||
"""
|
"""
|
||||||
left.r = merge(left.r, right)
|
left.right = merge(left.right, right)
|
||||||
return left
|
return left
|
||||||
else:
|
else:
|
||||||
"""
|
"""
|
||||||
Symmetric as well
|
Symmetric as well
|
||||||
"""
|
"""
|
||||||
right.l = merge(left, right.l)
|
right.left = merge(left, right.left)
|
||||||
return right
|
return right
|
||||||
|
|
||||||
|
def insert(root: Node, value: int) -> Node:
|
||||||
def insert(root: Node, key: int) -> Node:
|
|
||||||
"""
|
"""
|
||||||
Insert element
|
Insert element
|
||||||
|
|
||||||
Split current tree with a key into l, r,
|
Split current tree with a value into left, right,
|
||||||
Insert new node into the middle
|
Insert new node into the middle
|
||||||
Merge l, node, r into root
|
Merge left, node, right into root
|
||||||
"""
|
"""
|
||||||
node = Node(key)
|
node = Node(value)
|
||||||
l, r = split(root, key)
|
left, right = split(root, value)
|
||||||
root = merge(l, node)
|
return merge(merge(left, node), right)
|
||||||
root = merge(root, r)
|
|
||||||
return root
|
|
||||||
|
|
||||||
|
def erase(root: Node, value: int) -> Node:
|
||||||
def erase(root: Node, key: int) -> Node:
|
|
||||||
"""
|
"""
|
||||||
Erase element
|
Erase element
|
||||||
|
|
||||||
Split all nodes with keys less into l,
|
Split all nodes with values less into left,
|
||||||
Split all nodes with keys greater into r.
|
Split all nodes with values greater into right.
|
||||||
Merge l, r
|
Merge left, right
|
||||||
"""
|
"""
|
||||||
l, r = split(root, key)
|
left, right = split(root, value-1)
|
||||||
_, r = split(r, key + 1)
|
_, right = split(right, value)
|
||||||
return merge(l, r)
|
return merge(left, right)
|
||||||
|
|
||||||
|
def inorder(root: Node):
|
||||||
def node_print(root: Node):
|
|
||||||
"""
|
"""
|
||||||
Just recursive print of a tree
|
Just recursive print of a tree
|
||||||
"""
|
"""
|
||||||
if not root:
|
if not root: # None
|
||||||
return
|
return
|
||||||
node_print(root.l)
|
else:
|
||||||
print(root.key, end=" ")
|
inorder(root.left)
|
||||||
node_print(root.r)
|
print(root.value, end=" ")
|
||||||
|
inorder(root.right)
|
||||||
|
|
||||||
|
|
||||||
def interactTreap():
|
def interactTreap(root, args):
|
||||||
"""
|
"""
|
||||||
Commands:
|
Commands:
|
||||||
+ key to add key into treap
|
+ value to add value into treap
|
||||||
- key to erase all nodes with key
|
- value to erase all nodes with value
|
||||||
|
|
||||||
After each command, program prints treap
|
>>> root = interactTreap(None, "+1")
|
||||||
|
>>> inorder(root)
|
||||||
|
1
|
||||||
|
>>> root = interactTreap(root, "+3 +5 +17 +19 +2 +16 +4 +0")
|
||||||
|
>>> inorder(root)
|
||||||
|
0 1 2 3 4 5 16 17 19
|
||||||
|
>>> root = interactTreap(root, "+4 +4 +4")
|
||||||
|
>>> inorder(root)
|
||||||
|
0 1 2 3 4 4 4 4 5 16 17 19
|
||||||
|
>>> root = interactTreap(root, "-0")
|
||||||
|
>>> inorder(root)
|
||||||
|
1 2 3 4 4 4 4 5 16 17 19
|
||||||
|
>>> root = interactTreap(root, "-4")
|
||||||
|
>>> inorder(root)
|
||||||
|
1 2 3 5 16 17 19
|
||||||
|
>>> root = interactTreap(root, "=0")
|
||||||
|
Unknown command
|
||||||
"""
|
"""
|
||||||
root = None
|
for arg in args.split():
|
||||||
while True:
|
if arg[0] == "+":
|
||||||
cmd = input().split()
|
root = insert(root, int(arg[1:]))
|
||||||
cmd[1] = int(cmd[1])
|
|
||||||
if cmd[0] == "+":
|
elif arg[0] == "-":
|
||||||
root = insert(root, cmd[1])
|
root = erase(root, int(arg[1:]))
|
||||||
elif cmd[0] == "-":
|
|
||||||
root = erase(root, cmd[1])
|
|
||||||
else:
|
else:
|
||||||
print("Unknown command")
|
print("Unknown command")
|
||||||
node_print(root)
|
|
||||||
|
|
||||||
|
return root
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""After each command, program prints treap"""
|
||||||
|
root = None
|
||||||
|
print("enter numbers to creat a tree, + value to add value into treap, - value to erase all nodes with value. 'q' to quit. ")
|
||||||
|
|
||||||
|
args = input()
|
||||||
|
while args != 'q':
|
||||||
|
root = interactTreap(root, args)
|
||||||
|
print(root)
|
||||||
|
args = input()
|
||||||
|
|
||||||
|
print("good by!")
|
||||||
|
pass
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
interactTreap()
|
import doctest
|
||||||
|
doctest.testmod()
|
||||||
|
main()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user