Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 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
143 changes: 142 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


__all__ = [
'AVLTree',
'BinaryTree',
'BinarySearchTree',
'BinaryTreeTraversal',
'BinaryIndexedTree',
'CartesianTree',
'Treap',
'SplayTree'
]

Expand Down Expand Up @@ -642,6 +646,143 @@ 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, 4, 1)
>>> c.insert(2, 3, 2)
>>> 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
"""
@classmethod
def methods(cls):
return ['__str__', 'insert', 'delete']

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]
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]

def insert(self, key, priority, data=None):
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

References
==========

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

"""
@classmethod
def methods(cls):
return ['insert']

def insert(self, key, data=None):
priority = random.random()
super(Treap, self).insert(key, priority, data)

class AVLTree(SelfBalancingBinaryTree):
"""
Represents AVL trees.
Expand Down
56 changes: 55 additions & 1 deletion pydatastructs/trees/tests/test_binary_trees.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
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
import random

def test_BinarySearchTree():
BST = BinarySearchTree
Expand Down Expand Up @@ -320,6 +321,59 @@ 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, 1, 3)
tree.insert(1, 6, 1)
tree.insert(0, 9, 0)
tree.insert(5, 11, 5)
tree.insert(4, 14, 4)
tree.insert(9, 17, 9)
tree.insert(7, 22, 7)
tree.insert(6, 42, 6)
tree.insert(8, 49, 8)
tree.insert(2, 99, 2)
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, 4, 1.5)
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():

random.seed(0)
tree = Treap()
tree.insert(7, 7)
tree.insert(2, 2)
tree.insert(3, 3)
tree.insert(4, 4)
tree.insert(5, 5)
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__)
31 changes: 30 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 @@ -56,6 +57,34 @@ 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']

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
3 changes: 2 additions & 1 deletion pydatastructs/utils/tests/test_code_quality.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ def _apis():
pyds.miscellaneous_data_structures.stack.LinkedListStack,
pyds.DisjointSetForest, pyds.BinomialTree, pyds.TreeNode, pyds.MAryTreeNode,
pyds.LinkedListNode, pyds.BinomialTreeNode, pyds.AdjacencyListGraphNode,
pyds.AdjacencyMatrixGraphNode, pyds.GraphEdge, pyds.Set, pyds.BinaryIndexedTree]
pyds.AdjacencyMatrixGraphNode, pyds.GraphEdge, pyds.Set, pyds.BinaryIndexedTree,
pyds.CartesianTree, pyds.CartesianTreeNode, pyds.Treap]

def test_public_api():
pyds = pydatastructs
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)
assert str(c) == "(None, 1, 1, 1, None)"