diff --git a/.gitignore b/.gitignore index 45ab7ce21..2d5590d69 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__/ *.pyo .vscode/ .pytest_cache/ +pre_commit.ps1 diff --git a/.travis.yml b/.travis.yml index 12c298e55..2401b8ce3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,5 @@ python: install: - pip install -r requirements.txt script: + - python -m unittest discover pydatastructs - pytest --doctest-modules diff --git a/AUTHORS b/AUTHORS index c8508f2f1..716463088 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,3 @@ Gagandeep Singh +Kartikei Mittal + diff --git a/pydatastructs/__init__.py b/pydatastructs/__init__.py index 1ff5a79b9..40471c3f3 100644 --- a/pydatastructs/__init__.py +++ b/pydatastructs/__init__.py @@ -1,2 +1,4 @@ from .linear_data_structures import * from .trees import * +from .miscellaneous_data_structures import * +from .utils import * diff --git a/pydatastructs/linear_data_structures/__init__.py b/pydatastructs/linear_data_structures/__init__.py index 663cdfd8f..6225a2054 100644 --- a/pydatastructs/linear_data_structures/__init__.py +++ b/pydatastructs/linear_data_structures/__init__.py @@ -1,6 +1,9 @@ __all__ = [] -from . import arrays +from . import ( + arrays, +) + from .arrays import ( OneDimensionalArray, ) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 9db8d205f..2979a6189 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -1,12 +1,10 @@ from __future__ import print_function, division +from pydatastructs.utils.misc_util import _check_type, NoneType __all__ = [ 'OneDimensionalArray' ] -_check_type = lambda a, t: isinstance(a, t) -NoneType = type(None) - class Array(object): ''' Abstract class for arrays in pydatastructs. @@ -105,7 +103,10 @@ def __getitem__(self, i): return self._data.__getitem__(i) def __setitem__(self, idx, elem): - self._data[idx] = self._dtype(elem) + if elem is None: + self._data[idx] = None + else: + self._data[idx] = self._dtype(elem) def fill(self, elem): elem = self._dtype(elem) diff --git a/pydatastructs/miscellaneous_data_structures/__init__.py b/pydatastructs/miscellaneous_data_structures/__init__.py new file mode 100644 index 000000000..09edacdce --- /dev/null +++ b/pydatastructs/miscellaneous_data_structures/__init__.py @@ -0,0 +1,10 @@ +__all__ = [] + +from . import ( + stack, +) + +from .stack import ( + Stack, +) +__all__.extend(stack.__all__) diff --git a/pydatastructs/miscellaneous_data_structures/stack.py b/pydatastructs/miscellaneous_data_structures/stack.py new file mode 100644 index 000000000..b840cedd4 --- /dev/null +++ b/pydatastructs/miscellaneous_data_structures/stack.py @@ -0,0 +1,114 @@ + +from __future__ import print_function, division +from pydatastructs.linear_data_structures import OneDimensionalArray +from copy import deepcopy as dc + +__all__ = [ + 'Stack' +] + +_check_type = lambda a, t: isinstance(a, t) +NoneType = type(None) + +class Stack(object): + """Respresentation of stack data structure + + Parameters + ========== + + implementation : str + Implementation to be used for stack. + By default, 'array' + Currently only supports 'array' + implementation. + maxsize : int + The maximum size of the stack. + For array implementation. + top : int + The top element of the stack. + For array implementation. + items : OneDimensionalArray + Optional, by default, None + The inital items in the stack. + For array implementation. + dtype : A valid python type + Optional, by default int if item + is None, otherwise takes the data + type of OneDimensionalArray + For array implementation. + + Example + ======= + + >>> from pydatastructs import Stack + >>> s = Stack(maxsize=5, top=0) + >>> s.push(1) + >>> s.push(2) + >>> s.push(3) + >>> str(s) + '[1, 2, 3, None, None]' + >>> s.pop() + 3 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Stack_(abstract_data_type) + """ + + def __new__(cls, implementation='array', **kwargs): + if implementation == 'array': + return ArrayStack( + kwargs.get('maxsize', None), + kwargs.get('top', None), + kwargs.get('items', None), + kwargs.get('dtype', int)) + raise NotImplementedError( + "%s hasn't been implemented yet."%(implementation)) + + def push(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + + def pop(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + +class ArrayStack(Stack): + + def __new__(cls, maxsize=None, top=0, items=None, dtype=int): + if not _check_type(maxsize, int): + raise ValueError("maxsize is missing.") + if not _check_type(top, int): + raise ValueError("top is missing.") + if items == None: + items = OneDimensionalArray(dtype, maxsize) + if not _check_type(items, OneDimensionalArray): + raise ValueError("items is not of type, OneDimensionalArray") + if items._size > maxsize: + raise ValueError("Overflow, size of items %s is greater " + "than maxsize, %s"%(items._size, maxsize)) + obj = object.__new__(cls) + obj.maxsize, obj.top, obj.items, obj.dtype = \ + maxsize, top, items, items._dtype + return obj + + def push(self, x): + if self.top == self.maxsize: + raise ValueError("Stack is full.") + self.items[self.top] = self.dtype(x) + self.top += 1 + + def pop(self): + if self.top == 0: + raise ValueError("Stack is already empty.") + self.top -= 1 + r = self.items[self.top] + self.items[self.top] = None + return r + + def __str__(self): + """ + Used for printing. + """ + return str(self.items._data) diff --git a/pydatastructs/miscellaneous_data_structures/tests/__init__.py b/pydatastructs/miscellaneous_data_structures/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_stack.py b/pydatastructs/miscellaneous_data_structures/tests/test_stack.py new file mode 100644 index 000000000..ce0343d22 --- /dev/null +++ b/pydatastructs/miscellaneous_data_structures/tests/test_stack.py @@ -0,0 +1,22 @@ +from pydatastructs.miscellaneous_data_structures import Stack +from pydatastructs.linear_data_structures import OneDimensionalArray +from pydatastructs.utils.raises_util import raises + +def test_Stack(): + + s = Stack(maxsize=3, top=0) + s.push(1) + s.push(2) + s.push(3) + assert s.top == 3 + assert str(s) == '[1, 2, 3]' + raises(ValueError, lambda: s.push(4)) + assert s.pop() == 3 + assert s.pop() == 2 + assert s.pop() == 1 + assert s.top == 0 + raises(ValueError, lambda: s.pop()) + raises(ValueError, lambda: Stack()) + raises(ValueError, lambda: Stack(maxsize=5, top=0, items=[1, 2, 3])) + raises(ValueError, lambda: Stack(maxsize=5, top=0, + items=OneDimensionalArray(6))) diff --git a/pydatastructs/trees/__init__.py b/pydatastructs/trees/__init__.py index f68db60d6..91f9f5476 100644 --- a/pydatastructs/trees/__init__.py +++ b/pydatastructs/trees/__init__.py @@ -1,12 +1,15 @@ __all__ = [] -from . import binary_trees +from . import ( + binary_trees, + space_partitioning_trees +) + from .binary_trees import ( Node, BinaryTree, BinarySearchTree ) __all__.extend(binary_trees.__all__) -from . import space_partitioning_trees from .space_partitioning_trees import ( OneDimensionalSegmentTree ) diff --git a/pydatastructs/trees/binary_trees.py b/pydatastructs/trees/binary_trees.py index 1345485a6..f1c396b2c 100644 --- a/pydatastructs/trees/binary_trees.py +++ b/pydatastructs/trees/binary_trees.py @@ -1,4 +1,5 @@ from __future__ import print_function, division +from pydatastructs.utils import Node __all__ = [ 'Node', @@ -6,38 +7,6 @@ 'BinarySearchTree' ] -class Node(object): - """ - Represents node in trees. - - Parameters - ========== - - data - Any valid data to be stored in the node. - key - Required for comparison operations. - left: int - Optional, index of the left child node. - right: int - Optional, index of the right child node. - """ - - __slots__ = ['key', 'data', 'left', 'right', 'is_root'] - - def __new__(cls, key, data): - obj = object.__new__(cls) - obj.data, obj.key = data, key - obj.left, obj.right = None, None - obj.is_root = False - return obj - - def __str__(self): - """ - Used for printing. - """ - return str((self.left, self.key, self.data, self.right)) - class BinaryTree(object): """ Abstract binary tree. diff --git a/pydatastructs/trees/space_partitioning_trees.py b/pydatastructs/trees/space_partitioning_trees.py index 19f4e48d7..9a04c4048 100644 --- a/pydatastructs/trees/space_partitioning_trees.py +++ b/pydatastructs/trees/space_partitioning_trees.py @@ -1,4 +1,4 @@ -from pydatastructs.trees.binary_trees import Node +from pydatastructs.utils import Node from collections import deque as Queue from pydatastructs.linear_data_structures.arrays import _check_type diff --git a/pydatastructs/utils/__init__.py b/pydatastructs/utils/__init__.py index e69de29bb..2a74fd3a7 100644 --- a/pydatastructs/utils/__init__.py +++ b/pydatastructs/utils/__init__.py @@ -0,0 +1,7 @@ +__all__ = [] + +from . import misc_util +from .misc_util import ( + Node +) +__all__.extend(misc_util.__all__) diff --git a/pydatastructs/utils/misc_util.py b/pydatastructs/utils/misc_util.py new file mode 100644 index 000000000..77c281e96 --- /dev/null +++ b/pydatastructs/utils/misc_util.py @@ -0,0 +1,40 @@ +from __future__ import print_function, division + +__all__ = [ + 'Node' +] + +_check_type = lambda a, t: isinstance(a, t) +NoneType = type(None) + +class Node(object): + """ + Represents node in trees. + + Parameters + ========== + + data + Any valid data to be stored in the node. + key + Required for comparison operations. + left: int + Optional, index of the left child node. + right: int + Optional, index of the right child node. + """ + + __slots__ = ['key', 'data', 'left', 'right', 'is_root'] + + def __new__(cls, key, data): + obj = object.__new__(cls) + obj.data, obj.key = data, key + obj.left, obj.right = None, None + obj.is_root = False + return obj + + def __str__(self): + """ + Used for printing. + """ + return str((self.left, self.key, self.data, self.right))