From 0c74a432a8bb6aff7a8bb10a2f3a3582e2515e61 Mon Sep 17 00:00:00 2001 From: warmachine028 Date: Fri, 17 Dec 2021 16:25:08 +0530 Subject: [PATCH] Added changes for V0.0.2 --- LICENSE | 2 +- README.md | 125 +++++++++++++++++- assets/datastax.ico | Bin 0 -> 10996 bytes assets/icon.png | Bin 0 -> 15481 bytes datastax/__init__.py | 5 + datastax/__main__.py | 35 +++++ datastax/linkedlists/__init__.py | 9 +- ...rcular_list.py => circular_linked_list.py} | 11 -- datastax/linkedlists/doubly_circular_list.py | 15 +-- datastax/linkedlists/doubly_linked_list.py | 31 ++--- datastax/linkedlists/linked_list.py | 7 +- datastax/trees/__init__.py | 8 +- datastax/trees/avl_tree.py | 64 +++++---- datastax/trees/binary_search_tree.py | 8 +- datastax/trees/binary_tree.py | 37 +++--- desktop.ini | 2 + setup.py | 18 ++- tests/Trees/AVLTree.py | 8 -- tests/linkedlists_tests/__init__.py | 0 tests/linkedlists_tests/circular_list_test.py | 10 ++ .../doubly_circular_list_test.py | 9 ++ .../doubly_linked_list_test.py | 12 ++ .../linked_list_test.py} | 16 +-- tests/trees_tests/__init__.py | 0 tests/trees_tests/avl_tree_test.py | 18 +++ .../binary_search_tree_test.py} | 1 + tests/trees_tests/binary_tree_test.py | 22 +++ 27 files changed, 350 insertions(+), 123 deletions(-) create mode 100644 assets/datastax.ico create mode 100644 assets/icon.png create mode 100644 datastax/__main__.py rename datastax/linkedlists/{circular_list.py => circular_linked_list.py} (70%) create mode 100644 desktop.ini delete mode 100644 tests/Trees/AVLTree.py create mode 100644 tests/linkedlists_tests/__init__.py create mode 100644 tests/linkedlists_tests/circular_list_test.py create mode 100644 tests/linkedlists_tests/doubly_circular_list_test.py create mode 100644 tests/linkedlists_tests/doubly_linked_list_test.py rename tests/{LinkedLists/LinkedList.py => linkedlists_tests/linked_list_test.py} (63%) create mode 100644 tests/trees_tests/__init__.py create mode 100644 tests/trees_tests/avl_tree_test.py rename tests/{Trees/BinarySeaarchTree.py => trees_tests/binary_search_tree_test.py} (96%) create mode 100644 tests/trees_tests/binary_tree_test.py diff --git a/LICENSE b/LICENSE index 63b4b68..3120fd6 100644 --- a/LICENSE +++ b/LICENSE @@ -14,7 +14,7 @@ copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE diff --git a/README.md b/README.md index 698f5d3..b041727 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,134 @@ -# datastax + updated: Friday, 17th December 2021 + +
+ datastax +

Simplicity meets intelligence

+ +
+ +
+ + + +
+ +# [Datastax](https://github.com/warmachine028/datastax) + +## What's New? + +- Added terminal demo +- Improved type hinting using mypy static type checker +- Removed few bugs and potential errors +- Purified test_structure +- Improvised for uploading in PyPI + +## Table of Contents + +- [Introduction](#introduction) +- [Problem Statement](#problem-statement) +- [Benefits](#benefits) +- [Requirements](#requirements) +- [Installation](#installation) +- [Usage](#usage) ## Introduction -- This is a very simple yet powerful project to implement day to day data structures. +- This is a very simple yet powerful project to implement day to day abstract data structures. - A pure implementation of Python in representing Trees and Linkedlists in basic command prompt + - It helps visualize each data structure for better understanding - Students can be beneficial in using this Package - This project is still under construction +## Problem Statement + +- Often in the beginning CS students face problems in understanding the internal architecture of ADTs +- While solving coding challenges locally where test cases have to be written using these ADTs, it becomes really + cumbersome to write these data structures from scratch. +- Often while writing a programs implementing these ADS we encounter lots of errors just because we are unable to + preview what's actually going on under the hood. + +## Benefits + +- Instant installation +- Quick Updates +- Very small size +- No extra modules required +- Written purely from scratch +- Easy Documentation [Upcoming] +- Command Line Demo + +## Requirements + +- Runs on latest Python 3.8+ +- This Library requires no extra modules + ## Installation -Use the python package manager [pip](https://pip.pypa.io/en/stable/) to install datastax. +1. Clone this repository locally +2. Reach base folder _datastax/_ +3. Use the python package manager [pip](https://pip.pypa.io/en/stable/) to install datastax. ```bash -pip install datastax +pip install . +``` + +## Usage + +### Demo + +- To get a demo of the library use the following command + - **Windows**: + + ```bash + > py -m datastax + ``` + - **Unix based systems**: + + ```bash + $ python -m datastax + ``` + - _Result_ + ```bash + Available modules are: + 1. LinkedLists + 2. Trees + + Usage + $ py datastax [data] + Data Structures: + trees Hierarchical DS + linkedlists Linear DS + ``` +- Then follow as the instruction guides + +```bash +> py -m datastax linkedlist 1 2 3 4 + Visuals for LinkedLists: + + 1. Singly Linked List: + Node[1] -> Node[2] -> Node[3] -> Node[4] -> NULL + + 2. Doubly Linked List: + NULL <-> Node[1] <-> Node[2] <-> Node[3] <-> Node[4] <-> NULL + ... +``` + +### Practical Usage + +```py +from datastax.trees import BinaryTree + +bt = BinaryTree([1, 2, 3, 4, 5]) +print(bt) + +## OUTPUT: +""" + 1 + ┌─────┴─────┐ + 2 3 + ┌──┴──┐ + 4 5 +""" ``` -## Usage \ No newline at end of file diff --git a/assets/datastax.ico b/assets/datastax.ico new file mode 100644 index 0000000000000000000000000000000000000000..3976a8c4f6bebf3bc4beb30d340555edf68a7f15 GIT binary patch literal 10996 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 1: + data_structure = sys.argv[1].lower() + data = sys.argv[2:] if len(sys.argv) > 2 else [*range(5)] # take User given data or default + if data_structure in ('linkedlist', "linkedlists"): + print("Visuals for LinkedLists:\n\n" + f"1. Singly Linked List: \n{ll.LinkedList(data)}\n\n" + f"2. Doubly Linked List: \n{ll.DoublyLinkedList(data)}\n\n" + f"3. Circular Linked List: \n{ll.CircularLinkedList(data)}\n\n" + f"4. Doubly Circular List: \n{ll.DoublyCircularList(data)}\n\n") + elif data_structure in ('tree', 'trees'): + print("Visuals for Trees:\n\n" + f"1. Binary Tree \n{trees.BinaryTree(data)}\n\n" + f"2. Binary Search Tree \n{trees.BinarySearchTree(data)}\n\n" + f"3. AVL Tree \n{trees.AVLTree(data)}\n\n") + else: + print("This module is not available yet") + else: + print("Available modules are:\n" + "1. LinkedLists\n" + "2. Trees\n" + "\nUsage\n" + "$ py datastax [data]\n" + "Data Structures: \n" + " trees Hierarchical DS\n" + " linkedlists Linear DS") + + +if __name__ == '__main__': + main() diff --git a/datastax/linkedlists/__init__.py b/datastax/linkedlists/__init__.py index b991f8f..c0c3fdc 100644 --- a/datastax/linkedlists/__init__.py +++ b/datastax/linkedlists/__init__.py @@ -1,4 +1,11 @@ -from .circular_list import CircularLinkedList +from .circular_linked_list import CircularLinkedList from .doubly_circular_list import DoublyCircularList from .doubly_linked_list import DoublyNode, DoublyLinkedList from .linked_list import LinkedList, Node + +__all__ = [ + 'LinkedList', 'Node', + 'DoublyLinkedList', 'DoublyNode', + 'CircularLinkedList', + 'DoublyCircularList' +] diff --git a/datastax/linkedlists/circular_list.py b/datastax/linkedlists/circular_linked_list.py similarity index 70% rename from datastax/linkedlists/circular_list.py rename to datastax/linkedlists/circular_linked_list.py index 8a84187..3ca053b 100644 --- a/datastax/linkedlists/circular_list.py +++ b/datastax/linkedlists/circular_linked_list.py @@ -25,14 +25,3 @@ def __str__(self, node: Node = None): if ref is head: break string += f"┐\n└{'<'.center(len(string) - 1, '─')}┘" return string - - -if __name__ == '__main__': - CLL = CircularLinkedList([*range(5)]) - CLL.insert(999) - CLL.append("ABQ") - print(CLL.__str__()) - print(CLL.__str__(CLL.head.next)) - print(CLL.__str__(CLL.head.next.next)) - print(CLL.__str__(CLL.head.next.next.next)) - print(CLL.__str__(CLL.head.next.next.next.next)) diff --git a/datastax/linkedlists/doubly_circular_list.py b/datastax/linkedlists/doubly_circular_list.py index 495914e..bfb21d3 100644 --- a/datastax/linkedlists/doubly_circular_list.py +++ b/datastax/linkedlists/doubly_circular_list.py @@ -1,10 +1,9 @@ from typing import Any -from datastax.linkedlists.circular_list import CircularLinkedList from datastax.linkedlists.doubly_linked_list import DoublyLinkedList, DoublyNode -class DoublyCircularList(DoublyLinkedList, CircularLinkedList): +class DoublyCircularList(DoublyLinkedList): def append(self, data: Any) -> None: super().append(data) self.head.prev, self.tail.next = self.tail, self.head @@ -13,7 +12,7 @@ def insert(self, data: Any) -> None: super().insert(data) self.head.prev, self.tail.next = self.tail, self.head - def __str__(self, reverse: bool = False, node: DoublyNode = None): + def __str__(self, reverse=False, node: DoublyNode = None): head = node or (self.tail if reverse else self.head) if not head: return "NULL" string = f"┌->" @@ -24,13 +23,3 @@ def __str__(self, reverse: bool = False, node: DoublyNode = None): if ref is head: break string = f"{string[:-1]}┐\n└{'<-->'.center(len(string) - 2, '─')}┘" return string - - -if __name__ == '__main__': - DCLL = DoublyCircularList([1, 2, 3]) - print(DCLL) - print(DCLL.__str__(True)) - print(DCLL.__str__(False, DCLL.head.next)) - print(DCLL.__str__(False, DCLL.head.next.next)) - print() - print(DCLL.__str__(True, DCLL.head.prev)) diff --git a/datastax/linkedlists/doubly_linked_list.py b/datastax/linkedlists/doubly_linked_list.py index e8b585d..32d6ed7 100644 --- a/datastax/linkedlists/doubly_linked_list.py +++ b/datastax/linkedlists/doubly_linked_list.py @@ -1,13 +1,14 @@ from __future__ import annotations -from typing import Any +from typing import Any, Optional from datastax.linkedlists.linked_list import Node, LinkedList class DoublyNode(Node): - def __init__(self, data: Any, nex: Node = None, prev=None): - super().__init__(data, nex) + def __init__(self, data: Any, nex: DoublyNode = None, prev: DoublyNode = None): + super().__init__(data) + self.next = nex self.prev = prev def __str__(self): @@ -17,6 +18,11 @@ def __str__(self): class DoublyLinkedList(LinkedList): + def __init__(self, array: list[Any], head: DoublyNode = None): + self._head: Optional[DoublyNode] = head + self._tail = head + super().__init__(array, head) + def append(self, data) -> None: node = DoublyNode(data, None, self.tail) if not self.head: self._head = node @@ -32,20 +38,9 @@ def insert(self, data: Any): def __str__(self, reverse=False, node: DoublyNode = None): string = "NULL" if not self.head: return string - node = node or (self.tail if reverse else self.head) - while node: - string += f" <-> Node[{node.data}]" - node = node.prev if reverse else node.next + head = node or (self.tail if reverse else self.head) + while head: + string += f" <-> Node[{head.data}]" + head = head.prev if reverse else head.next string += " <-> NULL" return string - - -# __main__ -if __name__ == '__main__': - D = DoublyLinkedList([*range(5)]) - print("head -> ", D.head) - D.insert(10) - D.insert(20) - D.append(199) - print(D) - print(D.__str__(True)) diff --git a/datastax/linkedlists/linked_list.py b/datastax/linkedlists/linked_list.py index adcf3a8..2031710 100644 --- a/datastax/linkedlists/linked_list.py +++ b/datastax/linkedlists/linked_list.py @@ -10,7 +10,10 @@ def __init__(self, data: Any, nex: Node = None): def __str__(self): return f'Node[{self.data}] -> ' \ - f'Node[{self.next.data}]' if self.next else "NULL" + f"{f'Node[{self.next.data}]' if self.next else 'NULL'}" + + def __repr__(self): + return self.__str__() class LinkedList: @@ -30,7 +33,7 @@ def tail(self): return self._tail def append(self, data: Any) -> None: node = Node(data) if not self.head: self._head = node - else: self._tail.next = node + else: self.tail.next = node self._tail = node def insert(self, data: Any): diff --git a/datastax/trees/__init__.py b/datastax/trees/__init__.py index 141d728..701b442 100644 --- a/datastax/trees/__init__.py +++ b/datastax/trees/__init__.py @@ -1,3 +1,9 @@ -from .avl_tree import AVLTree, AVLTreeNode +from .avl_tree import AVLTree, AVLNode from .binary_search_tree import BinarySearchTree from .binary_tree import BinaryTree, TreeNode + +__all__ = [ + "BinaryTree", "TreeNode", + "BinarySearchTree", + "AVLTree", "AVLNode" +] diff --git a/datastax/trees/avl_tree.py b/datastax/trees/avl_tree.py index 47d3459..402e4cf 100644 --- a/datastax/trees/avl_tree.py +++ b/datastax/trees/avl_tree.py @@ -6,16 +6,25 @@ from datastax.trees.binary_search_tree import BinarySearchTree, TreeNode -class AVLTreeNode(TreeNode): - def __init__(self, data: Any, left: AVLTreeNode = None, right: AVLTreeNode = None, height: int = 1) -> None: +class AVLNode(TreeNode): + def __init__(self, data: Any, + left: AVLNode = None, + right: AVLNode = None, + height: int = 1): super().__init__(data, left, right) + self.left = left + self.right = right self.height = height class AVLTree(BinarySearchTree): - def insert(self, data: Any, root: AVLTreeNode = None) -> None: - def place(parent: Optional[AVLTreeNode]) -> AVLTreeNode: - if not parent: return AVLTreeNode(data) + def __init__(self, array: list[Any] = None, root=None): + self._root: Optional[AVLNode] = root + super().__init__(array, root) + + def insert(self, data: Any, root: AVLNode = None) -> None: + def place(parent: Optional[AVLNode]) -> Optional[AVLNode]: + if not parent: return AVLNode(data) elif parent.data < data: parent.right = place(parent.right) elif data < parent.data: parent.left = place(parent.left) @@ -25,49 +34,52 @@ def place(parent: Optional[AVLTreeNode]) -> AVLTreeNode: root = root or self.root result = place(root) - if result is not root: self._root = result + if result and result is not root: self._root = result - def balance(self, parent: AVLTreeNode, data: Any) -> AVLTreeNode: + def balance(self, parent: Optional[AVLNode], data: Any) -> Optional[AVLNode]: + if not parent: return None balance_factor = self.check_balance_factor(parent) if balance_factor < -1: - if parent.right.data < data: # Perform LL Rotation + if parent.right and parent.right.data < data: # Perform LL Rotation return self.left_rotate(parent) else: - parent.right = self.right_rotate(parent.right) # Perform RL Rotation + if parent.right: parent.right = self.right_rotate(parent.right) # Perform RL Rotation return self.left_rotate(parent) if balance_factor > 1: - if data < parent.left.data: + if parent.left and data < parent.left.data: return self.right_rotate(parent) else: - parent.left = self.left_rotate(parent.left) # Perform LR Rotation + if parent.left: parent.left = self.left_rotate(parent.left) # Perform LR Rotation return self.right_rotate(parent) return parent - def check_balance_factor(self, root: AVLTreeNode = None) -> int: - def balance_factor(parent: Optional[AVLTreeNode]) -> int: + def check_balance_factor(self, root: AVLNode = None) -> int: + def balance_factor(parent: Optional[AVLNode]) -> int: return self.height(parent.left) - self.height(parent.right) if parent else 0 return balance_factor(root or self.root) @staticmethod - def height(node: Optional[AVLTreeNode]) -> int: + def height(node: Optional[AVLNode]) -> int: return node.height if node else 0 - def right_rotate(self, node: AVLTreeNode) -> AVLTreeNode: + def right_rotate(self, node: AVLNode) -> Optional[AVLNode]: left = node.left - temp = left.right - left.right = node - node.left = temp - node.height = 1 + max(self.height(node.left), self.height(node.right)) - left.height = 1 + max(self.height(left.left), self.height(left.right)) + if left: + temp = left.right + left.right = node + node.left = temp + node.height = 1 + max(self.height(node.left), self.height(node.right)) + left.height = 1 + max(self.height(left.left), self.height(left.right)) return left - def left_rotate(self, node: AVLTreeNode) -> AVLTreeNode: + def left_rotate(self, node: AVLNode) -> Optional[AVLNode]: right = node.right - temp = right.left - right.left = node - node.right = temp - node.height = 1 + max(self.height(node.left), self.height(node.right)) - right.height = 1 + max(self.height(right.left), self.height(right.right)) + if right: + temp = right.left + right.left = node + node.right = temp + node.height = 1 + max(self.height(node.left), self.height(node.right)) + right.height = 1 + max(self.height(right.left), self.height(right.right)) return right diff --git a/datastax/trees/binary_search_tree.py b/datastax/trees/binary_search_tree.py index 799401d..7f7f6f2 100644 --- a/datastax/trees/binary_search_tree.py +++ b/datastax/trees/binary_search_tree.py @@ -7,8 +7,8 @@ class BinarySearchTree(BinaryTree): - def _construct(self, array: list[any] = None) -> Optional[BinarySearchTree]: - if not array or array[0] is None: return + def _construct(self, array: list[Any] = None) -> Optional[BinarySearchTree]: + if not array or array[0] is None: return None for item in array: try: self.insert(item) @@ -17,8 +17,8 @@ def _construct(self, array: list[any] = None) -> Optional[BinarySearchTree]: break return self - def insert(self, data: Any, root: TreeNode = None) -> None: - def place(parent: TreeNode) -> TreeNode: + def insert(self, data: Any, root=None) -> None: + def place(parent: Optional[TreeNode]) -> TreeNode: if not parent: return TreeNode(data) elif parent.data < data: parent.right = place(parent.right) elif data < parent.data: parent.left = place(parent.left) diff --git a/datastax/trees/binary_tree.py b/datastax/trees/binary_tree.py index 65e5835..576eef1 100644 --- a/datastax/trees/binary_tree.py +++ b/datastax/trees/binary_tree.py @@ -6,8 +6,8 @@ from typing import Any, Optional -def node_builder(value: str, piece_width: int) -> str: - value: str = value or '' +def node_builder(data: Optional[str], piece_width: int) -> str: + value: str = data or '' gap1 = int(math.ceil(piece_width / 2 - len(value) / 2)) gap2 = int(math.floor(piece_width / 2 - len(value) / 2)) return f"{' ' * gap1}{value}{' ' * gap2}" @@ -15,8 +15,8 @@ def node_builder(value: str, piece_width: int) -> str: class TreeNode: def __init__(self, data: Any, - left: TreeNode = None, - right: TreeNode = None) -> None: + left=None, + right=None) -> None: self.left = left self.data = data self.right = right @@ -58,24 +58,25 @@ def preorder_print(self) -> str: string_builder += f"└─▶ {values[1] or values[2]}" return string_builder + + def __repr__(self): return self.__str__() class BinaryTree: - def __init__(self, array: list[Any] = None, root: TreeNode = None): + def __init__(self, array: list[Any] = None, root=None): self._root = root self._construct(array) - self.__string = None + self.__string: Optional[str] = None @property - def root(self) -> Optional[TreeNode]: + def root(self): return self._root @property # Level Order Traversal -> Tree to array - def array_repr(self, root: TreeNode = None) -> list[Any]: + def array_repr(self) -> list[Any]: array = [] - queue = Queue() - root = root or self._root - if root: queue.put(root) + queue: Queue[TreeNode] = Queue() + if self.root: queue.put(self.root) while not queue.empty(): node = queue.get() array.append(node.data) @@ -84,7 +85,7 @@ def array_repr(self, root: TreeNode = None) -> list[Any]: return array - def insert(self, data: Any, path: list[str] = None) -> None: + def insert_path(self, data: Any, path: list[str] = None) -> None: node = TreeNode(data) if not self._root: self._root = node @@ -107,7 +108,7 @@ def insert(self, data: Any, path: list[str] = None) -> None: # Helper function to construct tree by level order -> Array to tree def _construct(self, array: list[Any] = None) -> Optional[BinaryTree]: - if not array or array[0] is None: return + if not array or array[0] is None: return None queue: Queue[TreeNode] = Queue(len(array)) current = 1 @@ -131,13 +132,13 @@ def _construct(self, array: list[Any] = None) -> Optional[BinaryTree]: def __str__(self, root: TreeNode = None): root = root or self.root if not root: return " NULL" - lines: list[list[str]] = [] - level: list[TreeNode] = [root] + lines: list[list[Optional[str]]] = [] + level: list[Optional[TreeNode]] = [root] nodes: int = 1 max_width: int = 0 while nodes: line: list[Optional[str]] = [] - next_level: list[TreeNode] = [] + next_level: list[Optional[TreeNode]] = [] nodes = 0 for node in level: if node: @@ -181,9 +182,9 @@ def __str__(self, root: TreeNode = None): # Pre Order Traversal of Tree def preorder_print(self, root: TreeNode = None) -> str: - def string_builder(parent: TreeNode, has_right_child: bool, padding="", component="") -> None: + def string_builder(parent: Optional[TreeNode], has_right_child: bool, padding="", component="") -> None: if not parent: return - self.__string += f"\n{padding}{component}{parent.data}" + if self.__string is not None: self.__string += f"\n{padding}{component}{parent.data}" if parent is not root: padding += "│ " if has_right_child else " " left_pointer, right_pointer = "├─▶ " if parent.right else "└─▶ ", "└─▶ " string_builder(parent.left, bool(parent.right), padding, left_pointer) diff --git a/desktop.ini b/desktop.ini new file mode 100644 index 0000000..3a8f04c --- /dev/null +++ b/desktop.ini @@ -0,0 +1,2 @@ +[.ShellClassInfo] +IconResource=D:\Programs\Python\datastax\assets\datastax.ico,0 diff --git a/setup.py b/setup.py index de758fe..b20d895 100644 --- a/setup.py +++ b/setup.py @@ -1,18 +1,22 @@ from setuptools import setup setup(name='datastax', - version='0.0.1', - description='A python package to handle dataStructures', - url='#', + version='0.0.2', + packages=['datastax', 'datastax/linkedlists', 'datastax/trees'], + license='MIT', + description='A python library to handle dataStructures', + long_description='This library which supports ADTs like Linkedlists and Trees and its types. This instant ' + 'library is solely written from scratch and requires no additional libraries to be installed. ' + 'It solves the purpose of writing programs for complex data structures from scratch, ' + 'visualizing ADTs and simplify writing its inner architectures', + url='https://github.com/warmachine028/datastax', author='Pritam K', author_email='pritamkundu771@gmail.com', - license='MIT', - packages=['datastax', 'datastax/linkedlists', 'datastax/trees'], zip_safe=False, classifiers=[ "Programming Language :: Python :: 3.10", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Software Development :: Documentation" + "Topic :: Software Development :: Documentation", + "Topic :: Software Development :: Libraries :: Python Modules" ]) diff --git a/tests/Trees/AVLTree.py b/tests/Trees/AVLTree.py deleted file mode 100644 index 9945e8c..0000000 --- a/tests/Trees/AVLTree.py +++ /dev/null @@ -1,8 +0,0 @@ -from datastax.trees import AVLTree - -avl = AVLTree() -for item in [*range(10)]: - avl.insert(item) - print(avl) -# print(avl) -print(AVLTree([10, 9, 8, 7, 2, 1, 99, 18, 17, 25, 23])) diff --git a/tests/linkedlists_tests/__init__.py b/tests/linkedlists_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/linkedlists_tests/circular_list_test.py b/tests/linkedlists_tests/circular_list_test.py new file mode 100644 index 0000000..f5680f3 --- /dev/null +++ b/tests/linkedlists_tests/circular_list_test.py @@ -0,0 +1,10 @@ +from datastax.linkedlists import CircularLinkedList + +CLL = CircularLinkedList([*range(5)]) +CLL.insert(999) +CLL.append("ABQ") +print(CLL.__str__()) +print(CLL.__str__(CLL.head.next)) +print(CLL.__str__(CLL.head.next.next)) +print(CLL.__str__(CLL.head.next.next.next)) +print(CLL.__str__(CLL.head.next.next.next.next)) diff --git a/tests/linkedlists_tests/doubly_circular_list_test.py b/tests/linkedlists_tests/doubly_circular_list_test.py new file mode 100644 index 0000000..3eb2b43 --- /dev/null +++ b/tests/linkedlists_tests/doubly_circular_list_test.py @@ -0,0 +1,9 @@ +from datastax.linkedlists import DoublyCircularList + +DCLL = DoublyCircularList([1, 2, 3]) +print(DCLL) +print(DCLL.__str__(True)) +print(DCLL.__str__(False, DCLL.head.next)) +print(DCLL.__str__(False, DCLL.head.next.next)) +print() +print(DCLL.__str__(True, DCLL.head.prev)) diff --git a/tests/linkedlists_tests/doubly_linked_list_test.py b/tests/linkedlists_tests/doubly_linked_list_test.py new file mode 100644 index 0000000..e8722c8 --- /dev/null +++ b/tests/linkedlists_tests/doubly_linked_list_test.py @@ -0,0 +1,12 @@ +from datastax.linkedlists import DoublyLinkedList + +DLL = DoublyLinkedList([*range(5)]) +print("head -> ", DLL.head) # head -> NULL ⟺ Node[0] ⟺ Node[1] + +DLL.insert(10) +DLL.insert(20) +DLL.append(199) +print(DLL) +# NULL <-> Node[20] <-> Node[10] <-> Node[0] <-> Node[1] <-> Node[2] <-> Node[3] <-> Node[4] <-> Node[199] <-> NULL +print(DLL.__str__(True)) +# NULL <-> Node[199] <-> Node[4] <-> Node[3] <-> Node[2] <-> Node[1] <-> Node[0] <-> Node[10] <-> Node[20] <-> NULL diff --git a/tests/LinkedLists/LinkedList.py b/tests/linkedlists_tests/linked_list_test.py similarity index 63% rename from tests/LinkedLists/LinkedList.py rename to tests/linkedlists_tests/linked_list_test.py index ec8dc11..4d1b6ad 100644 --- a/tests/LinkedLists/LinkedList.py +++ b/tests/linkedlists_tests/linked_list_test.py @@ -15,12 +15,12 @@ def test(array: list[Any] = None) -> None: test([None]) # constructing wih a null value test([None, 1, 2, 3, 4, 5]) # constructing with values where first item being NULL ######################### -L = LinkedList([1, 2, 3, 4, 5, 6]) # Insertion inside filled list -L.insert(10) # Insertion at the front -L.append(100) # Insertion at the back -print(L) +LL = LinkedList([1, 2, 3, 4, 5, 6]) # Insertion inside filled list +LL.insert(10) # Insertion at the front +LL.append(100) # Insertion at the back +print(LL) ###################### -L = LinkedList() # Insertion inside empty list -L.insert(1) # Insertion at the front -L.append(2) # Insertion at the back -print(L) +LL = LinkedList() # Insertion inside empty list +LL.insert(1) # Insertion at the front +LL.append(2) # Insertion at the back +print(LL) diff --git a/tests/trees_tests/__init__.py b/tests/trees_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/trees_tests/avl_tree_test.py b/tests/trees_tests/avl_tree_test.py new file mode 100644 index 0000000..2f0b4ad --- /dev/null +++ b/tests/trees_tests/avl_tree_test.py @@ -0,0 +1,18 @@ +from datastax.trees import AVLTree + +avl = AVLTree() +for item in [*range(10)]: + avl.insert(item) + print(avl) +# print(avl) +print(AVLTree([10, 9, 8, 7, 2, 1, 99, 18, 17, 25, 23])) +print(AVLTree([10, [1, 2, 3]])) +print(AVLTree([[2, 3], [1, 2, 3], [1, 3, 2]])) +print(AVLTree([1, 1, 1])) + +avt = AVLTree([*range(1, 8)]) +avt.insert(9) +avt.insert(7.5) +avt.insert(8.5) +print(avt) +print(avt.array_repr) diff --git a/tests/Trees/BinarySeaarchTree.py b/tests/trees_tests/binary_search_tree_test.py similarity index 96% rename from tests/Trees/BinarySeaarchTree.py rename to tests/trees_tests/binary_search_tree_test.py index 0c59262..e3580e8 100644 --- a/tests/Trees/BinarySeaarchTree.py +++ b/tests/trees_tests/binary_search_tree_test.py @@ -11,6 +11,7 @@ def test(array: list[Any]): test([None, 1]) +test([1, 1, 1]) test([1, 2, 3, None, 5]) test([1, 2, 3, 4]) test([4, 4, 4, 4, 3, ['1']]) diff --git a/tests/trees_tests/binary_tree_test.py b/tests/trees_tests/binary_tree_test.py new file mode 100644 index 0000000..206645b --- /dev/null +++ b/tests/trees_tests/binary_tree_test.py @@ -0,0 +1,22 @@ +from typing import Any + +from datastax.trees import BinaryTree + + +def test(array: list[Any]): + bst = BinaryTree(array) + print(bst) + print(bst.preorder_print()) + print(bst.array_repr) + + +test([None, 1]) +test([1, 2, 3, None, 5]) +test([1, 2, 3, 4]) +test([4, 4, 4, 4, 3, ['1']]) +test([4, 3, 1, 8, 9, 10]) +test(["1", "B", "Baxy", "D"]) +test([BinaryTree([10, 20, 30]), BinaryTree([10])]) +test([(10, 20), [10, 20]]) +test([{1, 2, 3}, {2, 3}, {4, 6, 5}]) +test([3, 1, 2, 4, 5, 9, 0, -4, -3])