Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemeted Treaps and CartesianTree #235

Merged
merged 35 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
60a8458
Implemented CartesianTreeNode
Aimaanhasan Mar 30, 2020
b1daa60
Added CartesianTreeNode in __init__
Aimaanhasan Mar 30, 2020
16d8076
Implemented CartesianTree and Treap
Aimaanhasan Mar 30, 2020
d9b69b7
Added CartesianTree and Treap in __init__
Aimaanhasan Mar 30, 2020
596b4a3
Added suggestions
Aimaanhasan Mar 30, 2020
695d1e3
Updated reference as in suggestion
Aimaanhasan Mar 30, 2020
34520f1
Removed See Also on line 805 as suggested
Aimaanhasan Mar 30, 2020
bb96d0d
Removed line as suggested
Aimaanhasan Mar 30, 2020
29a81c5
Removed rotations from `CartesianTree`
Aimaanhasan Mar 30, 2020
91522f8
Updated as suggested in importing the nodes
Aimaanhasan Mar 30, 2020
3d0b1cd
Tests added
Aimaanhasan Apr 16, 2020
6a56115
Merge branch 'master' into Treaps
Aimaanhasan Apr 16, 2020
e6fafe6
Removed trailing white spaces
Aimaanhasan Apr 19, 2020
686cdb3
Removed trailing white spaces from test
Aimaanhasan Apr 19, 2020
3e0fa6a
Removed whitespace on line 308
Aimaanhasan Apr 19, 2020
8db5848
Replaced comparison by values with comparison by references in binary…
Aimaanhasan Apr 19, 2020
99c8c41
Removed reference by values in test_binary_trees.py
Aimaanhasan Apr 19, 2020
b62df25
Updated delete of `CartesianTree`
Aimaanhasan Apr 19, 2020
5b362c0
Updated docs
Aimaanhasan Apr 19, 2020
4e8a06f
Removed trailing spaces in misc_util.py
Aimaanhasan Apr 19, 2020
d9a8a79
Added CartesianTreeNode test
Aimaanhasan Apr 19, 2020
5b2a671
Imported CartesianTreeNode in test_misc_util.py
Aimaanhasan Apr 19, 2020
d97bd8c
As suggested #1
Aimaanhasan Apr 24, 2020
0471425
Added seed when calling random as suggested
Aimaanhasan Apr 24, 2020
27df682
As suggested to add space when defining `__slots__`
Aimaanhasan Apr 24, 2020
f1245a4
As suggested to add spaces between commas
Aimaanhasan Apr 24, 2020
59f2539
Made `data` an optional argument in both `CartesianTree` and `Treap`
Aimaanhasan Apr 24, 2020
5bfa2bb
Added spaces in commas in test
Aimaanhasan Apr 24, 2020
e7cbfb8
Updated docs according to the change in API
Aimaanhasan Apr 24, 2020
628ad51
Updated tests with the change in API
Aimaanhasan Apr 24, 2020
b475780
Assertion error fix
Aimaanhasan Apr 24, 2020
5b52087
Merge branch 'master' into Treaps
czgdp1807 Apr 24, 2020
d1a41c8
some minor changes
czgdp1807 Apr 24, 2020
5420313
some minor changes
czgdp1807 Apr 24, 2020
cd6852b
Apply suggestions from code review
czgdp1807 Apr 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pydatastructs/trees/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
BinaryTreeTraversal,
AVLTree,
BinaryIndexedTree,
CartesianTree,
Treap,
SplayTree
)
__all__.extend(binary_trees.__all__)
Expand Down
141 changes: 140 additions & 1 deletion pydatastructs/trees/binary_trees.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
from pydatastructs.utils import TreeNode
from pydatastructs.utils import TreeNode, CartesianTreeNode
from pydatastructs.miscellaneous_data_structures import Stack
from pydatastructs.linear_data_structures import (
OneDimensionalArray, DynamicOneDimensionalArray)
from pydatastructs.linear_data_structures.arrays import ArrayForTrees
from collections import deque as Queue
import random
from copy import deepcopy


czgdp1807 marked this conversation as resolved.
Show resolved Hide resolved
__all__ = [
'AVLTree',
'BinaryTree',
'BinarySearchTree',
'BinaryTreeTraversal',
'BinaryIndexedTree',
'CartesianTree',
'Treap',
'SplayTree'
]

Expand Down Expand Up @@ -632,6 +636,141 @@ def _left_rotate(self, j, k):
if kp is None:
self.root_idx = k

class CartesianTree(SelfBalancingBinaryTree):
"""
Represents cartesian trees.

Examples
========

>>> from pydatastructs.trees import CartesianTree as CT
>>> c = CT()
>>> c.insert(1, 1, 4)
>>> c.insert(2, 2, 3)
>>> child = c.tree[c.root_idx].left
>>> c.tree[child].data
1
>>> c.search(1)
0
>>> c.search(-1) is None
True
>>> c.delete(1) is True
True
>>> c.search(1) is None
True
>>> c.delete(2) is True
True
>>> c.search(2) is None
True

References
==========

.. [1] https://www.cs.princeton.edu/courses/archive/spr09/cos423/Lectures/geo-st.pdf

See Also
========

pydatastructs.trees.binary_tree.SelfBalancingBinaryTree
"""
def _bubble_up(self, node_idx):
node = self.tree[node_idx]
parent_idx = self.tree[node_idx].parent
parent = self.tree[parent_idx]
while (node.parent is not None) and (parent.priority > node.priority):
if parent.right == node_idx:
self._left_rotate(parent_idx, node_idx)
else:
self._right_rotate(parent_idx, node_idx)
node = self.tree[node_idx]
parent_idx = self.tree[node_idx].parent
if parent_idx is not None:
parent = self.tree[parent_idx]
if node.parent is None:
self.tree[node_idx].is_root = True

def _trickle_down(self, node_idx):
node = self.tree[node_idx]
parent_idx = node.parent
while node.left is not None or node.right is not None:
if node.left is None:
self._left_rotate(node_idx, self.tree[node_idx].right)
elif node.right is None:
self._right_rotate(node_idx, self.tree[node_idx].left)
elif self.tree[node.left].priority < self.tree[node.right].priority:
self._right_rotate(node_idx, self.tree[node_idx].left)
else:
self._left_rotate(node_idx, self.tree[node_idx].right)
node = self.tree[node_idx]
parent_idx = node.parent

def insert(self, key, data, priority):
czgdp1807 marked this conversation as resolved.
Show resolved Hide resolved
super(CartesianTree, self).insert(key, data)
node_idx = super(CartesianTree, self).search(key)
node = self.tree[node_idx]
new_node = CartesianTreeNode(key, priority, data)
new_node.parent = node.parent
new_node.left = node.left
new_node.right = node.right
self.tree[node_idx] = new_node
if node.is_root:
self.tree[node_idx].is_root = True
else:
self._bubble_up(node_idx)

def delete(self, key, **kwargs):
balancing_info = kwargs.get('balancing_info', False)
node_idx = super(CartesianTree, self).search(key)
if node_idx is not None:
self._trickle_down(node_idx)
return super(CartesianTree, self).delete(key, balancing_info = balancing_info)

def __str__(self):
to_be_printed = ['' for i in range(self.tree._last_pos_filled + 1)]
for i in range(self.tree._last_pos_filled + 1):
if self.tree[i] is not None:
node = self.tree[i]
to_be_printed[i] = (node.left, node.key, node.priority, node.data, node.right)
return str(to_be_printed)

class Treap(CartesianTree):
"""
Represents treaps.

Examples
========

>>> from pydatastructs.trees import Treap as T
>>> t = T()
>>> t.insert(1, 1)
>>> t.insert(2, 2)
>>> t.search(1)
0
>>> t.search(-1) is None
True
>>> t.delete(1) is True
True
>>> t.search(1) is None
True
>>> t.delete(2) is True
True
>>> t.search(2) is None
True
czgdp1807 marked this conversation as resolved.
Show resolved Hide resolved

References
==========

.. [1] https://en.wikipedia.org/wiki/Treap

"""
priorities = set()
def insert(self, key, data):
priority = random.random()
while priority in self.priorities:
priority = random.random()
self.priorities.add(priority)
super(Treap, self).insert(key, data, priority)
czgdp1807 marked this conversation as resolved.
Show resolved Hide resolved

class AVLTree(SelfBalancingBinaryTree):
"""
Represents AVL trees.
Expand Down
53 changes: 52 additions & 1 deletion pydatastructs/trees/tests/test_binary_trees.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pydatastructs.trees.binary_trees import (
BinarySearchTree, BinaryTreeTraversal, AVLTree,
ArrayForTrees, BinaryIndexedTree, SelfBalancingBinaryTree, SplayTree)
ArrayForTrees, BinaryIndexedTree, SelfBalancingBinaryTree, SplayTree, CartesianTree, Treap)
from pydatastructs.utils.raises_util import raises
from pydatastructs.utils.misc_util import TreeNode
from copy import deepcopy
Aimaanhasan marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -320,6 +320,57 @@ def test_BinaryIndexedTree():
assert t.get_sum(0, 4) == 114
assert t.get_sum(1, 9) == 54

def test_CartesianTree():
tree = CartesianTree()
tree.insert(3, 3, 1)
tree.insert(1, 1, 6)
tree.insert(0, 0, 9)
tree.insert(5, 5, 11)
tree.insert(4, 4, 14)
tree.insert(9, 9, 17)
tree.insert(7, 7, 22)
tree.insert(6, 6, 42)
tree.insert(8, 8, 49)
tree.insert(2, 2, 99)
assert str(tree) == \
("[(1, 3, 1, 3, 3), (2, 1, 6, 1, 9), "
"(None, 0, 9, 0, None), (4, 5, 11, 5, 5), "
"(None, 4, 14, 4, None), (6, 9, 17, 9, None), "
"(7, 7, 22, 7, 8), (None, 6, 42, 6, None), "
"(None, 8, 49, 8, None), (None, 2, 99, 2, None)]")
tree.insert(1.5, 1.5, 4)
assert str(tree) == \
("[(10, 3, 1, 3, 3), (2, 1, 6, 1, None), "
"(None, 0, 9, 0, None), (4, 5, 11, 5, 5), "
"(None, 4, 14, 4, None), (6, 9, 17, 9, None), "
"(7, 7, 22, 7, 8), (None, 6, 42, 6, None), "
"(None, 8, 49, 8, None), (None, 2, 99, 2, None), "
"(1, 1.5, 4, 1.5, 9)]")
k = tree.search(1.5)
assert tree.tree[tree.tree[k].parent].key == 3
tree.delete(1.5)
tree.tree[tree.tree[tree.root_idx].left].key == 1
tree.delete(8)
assert tree.search(8) is None
tree.delete(7)
assert tree.search(7) is None
tree.delete(3)
assert tree.search(3) is None
assert tree.delete(18) is None

def test_Treap():
Aimaanhasan marked this conversation as resolved.
Show resolved Hide resolved
tree = Treap()
tree.insert(7,7)
tree.insert(2,2)
tree.insert(3,3)
tree.insert(4,4)
tree.insert(5,5)
Aimaanhasan marked this conversation as resolved.
Show resolved Hide resolved
assert isinstance(tree.tree[0].priority, float)
tree.delete(1)
assert tree.search(1) is None
assert tree.search(2) == 1
assert tree.delete(1) is None

def test_issue_234():
"""
https://github.com/codezonediitj/pydatastructs/issues/234
Expand Down
3 changes: 2 additions & 1 deletion pydatastructs/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
AdjacencyListGraphNode,
AdjacencyMatrixGraphNode,
GraphEdge,
Set
Set,
CartesianTreeNode
)
__all__.extend(misc_util.__all__)
30 changes: 29 additions & 1 deletion pydatastructs/utils/misc_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
'AdjacencyListGraphNode',
'AdjacencyMatrixGraphNode',
'GraphEdge',
'Set'
'Set',
'CartesianTreeNode'
]

_check_type = lambda a, t: isinstance(a, t)
Expand Down Expand Up @@ -52,6 +53,33 @@ def __str__(self):
"""
return str((self.left, self.key, self.data, self.right))

class CartesianTreeNode(TreeNode):
"""
Represents node in cartesian trees.

Parameters
==========

data
Any valid data to be stored in the node.
key
Required for comparison operations.
priority: int
An integer value for heap property.

"""
__slots__ = ['key', 'data', 'priority']
Aimaanhasan marked this conversation as resolved.
Show resolved Hide resolved
def __new__(cls, key, priority, data=None):
obj = TreeNode.__new__(cls, key, data)
obj.priority = priority
return obj

def __str__(self):
"""
Used for printing.
"""
return str((self.left, self.key, self.priority, self.data, self.right))

class BinomialTreeNode(TreeNode):
"""
Represents node in binomial trees.
Expand Down
6 changes: 5 additions & 1 deletion pydatastructs/utils/tests/test_misc_util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pydatastructs.utils import (AdjacencyListGraphNode, AdjacencyMatrixGraphNode,
GraphEdge, BinomialTreeNode, MAryTreeNode)
GraphEdge, BinomialTreeNode, MAryTreeNode, CartesianTreeNode)
from pydatastructs.utils.raises_util import raises

def test_AdjacencyListGraphNode():
Expand Down Expand Up @@ -38,3 +38,7 @@ def test_MAryTreeNode():
m.add_children(*[i for i in range(2,10)])
assert str(m) == "(1, 1)"
assert str(m.children) == "['2', '3', '4', '5', '6', '7', '8', '9']"

def test_CartesianTreeNode():
c = CartesianTreeNode(1,1,1)
Aimaanhasan marked this conversation as resolved.
Show resolved Hide resolved
assert str(c) == "(None, 1, 1, 1, None)"