-
Notifications
You must be signed in to change notification settings - Fork 0
Stack #2
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
base: master
Are you sure you want to change the base?
Stack #2
Changes from all commits
d44d98f
34e4d4a
d144503
c306cb1
319d906
3cf09b7
d8fe873
9682aac
3de31ae
62beee9
5d9137c
eab1059
c3eb6dd
c2f92af
52fc1de
f5783ff
5742fe7
ef25a88
f816975
127fd29
974cbd8
ea3d759
1e1b711
4278df6
98b492e
5e5f97b
35ca79d
d52fc51
abd7ea5
50a6f30
92527b8
6ed3652
e085be0
68e2840
fdf4a2c
54961fb
7f6b816
dc108d4
864cf8e
d7e3e24
8d9aa05
2eccafd
de9835c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,9 @@ | ||
| # data_structures | ||
| # data_structures | ||
|
|
||
| ##### This repository contains python implementations of various fundamental abstract data structures. These include: | ||
|
|
||
|
|
||
| ##### 1. Linked List (src/linked_list.py) | ||
|
|
||
| ##### 2. Stack (src/stack.py) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| """The setup for Mailroom distribution.""" | ||
|
|
||
| from setuptools import setup | ||
|
|
||
| setup( | ||
| name='data_structures', | ||
| description='Implementation of Data Structures.', | ||
| version=0.1, | ||
| author='Jordan Schatzman, Julien Wilson', | ||
| author_email='j.schatzman@outlook.com, julienawilson@gmail.com', | ||
| license='MIT', | ||
| package_dir={'': 'src'}, | ||
| py_modules=['linked_list', 'stack'], | ||
| extras_require={'test': ['pytest', 'pytest-watch', 'pytest-cov', 'tox']}, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| """Implementation of Doubly Linked List data type.""" | ||
|
|
||
|
|
||
| class DoublyLinkedList(object): | ||
| """Class representation of doubly linked list.""" | ||
|
|
||
| def __init__(self, iterable=None): | ||
| """Instantiate linked list.""" | ||
| self.head_node = None | ||
| self.tail_node = None | ||
| self.length = 0 | ||
| try: | ||
| for item in iterable: | ||
| self.push(item) | ||
| except TypeError: | ||
| if iterable: | ||
| print("Please only enter iterable values") | ||
|
|
||
| def push(self, contents): | ||
| """Add node to this dll.""" | ||
| if self.length == 0: | ||
| self.head_node = Node(contents, None, None) | ||
| self.tail_node = self.head_node | ||
| else: | ||
| self.head_node = Node(contents, self.head_node, None) | ||
| self.length += 1 | ||
|
|
||
| def append(self, contents): | ||
| """Add node to this dll.""" | ||
| if self.length == 0: | ||
| self.tail_node = Node(contents, None, None) | ||
| self.head_node = self.tail_node | ||
| else: | ||
| self.tail_node = Node(contents, None, self.tail_node) | ||
| self.length += 1 | ||
|
|
||
| def pop(self): | ||
| """Remove and return the current head node.""" | ||
| if not self.head_node: | ||
| print("Linked list is already empty") | ||
| return | ||
| old_head_node = self.head_node | ||
| self.head_node = self.head_node.next_node | ||
| self.length -= 1 | ||
| return old_head_node | ||
|
|
||
| def shift(self): | ||
| """Remove the end of the dll.""" | ||
| if not self.tail_node: | ||
| print("Linked list is already empty") | ||
| return | ||
| old_tail_node = self.tail_node | ||
| self.tail_node = self.tail_node.previous_node | ||
| self.length -= 1 | ||
| return old_tail_node | ||
|
|
||
| def remove(self, contents): | ||
| """Remove the first node with input contents if it exists.""" | ||
| if not self.length: | ||
| raise NameError('This dll is empty.') | ||
| if self.head_node.contents == contents: | ||
| if self.length == 1: | ||
| self.head_node = None | ||
| self.tail_node = None | ||
| else: | ||
| self.head_node = self.head_node.next_node | ||
| self.head_node.previous_node = None | ||
| self.length -= 1 | ||
| return | ||
| test_node = self.head_node | ||
| while test_node.contents != contents and test_node.next_node: | ||
| last_node = test_node | ||
| test_node = test_node.next_node | ||
| if test_node.contents == contents and not test_node.next_node: | ||
| last_node.next_node = None | ||
| self.tail_node = last_node | ||
| self.length -= 1 | ||
| return | ||
| elif test_node.contents == contents: | ||
| last_node.next_node = test_node.next_node | ||
| test_node.next_node.previous_node = last_node | ||
| self.length -= 1 | ||
| return | ||
| raise NameError('{0} is not in the dll'.format(contents)) | ||
|
|
||
|
|
||
| class Node(object): | ||
| """Class representation of doubly linked list node.""" | ||
|
|
||
| def __init__(self, contents, next_node, previous_node): | ||
| """Instantiate doubly linked list node.""" | ||
| self.contents = contents | ||
| self.next_node = next_node | ||
| self.previous_node = previous_node |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| """Implementation of Linked_List data type.""" | ||
|
|
||
|
|
||
| class LinkedList(object): | ||
| """Class representation of linked list.""" | ||
|
|
||
| def __init__(self, iterable=None): | ||
| """Instantiate linked list.""" | ||
| self.head_node = None | ||
| self.length = 0 | ||
| try: | ||
| for item in iterable: | ||
| self.push(item) | ||
| except TypeError: | ||
| if iterable: | ||
| raise TypeError("Please only enter iterable values") | ||
|
|
||
| def push(self, contents): | ||
| """Add node to this linked list.""" | ||
| self.head_node = Node(contents, self.head_node) | ||
| self.length += 1 | ||
|
|
||
| def pop(self): | ||
| """Remove and return the current head node.""" | ||
| if not self.head_node: | ||
| raise IndexError("List is already empty") | ||
| old_head_node = self.head_node | ||
| self.head_node = self.head_node.next_node | ||
| self.length -= 1 | ||
| return old_head_node.contents | ||
|
|
||
| def size(self): | ||
| """Return the current size of this linked list.""" | ||
| return self.length | ||
|
|
||
| def search(self, search_value): | ||
| """Return the node with the searched contents if found.""" | ||
| if self.length: | ||
| if search_value == self.head_node.contents: | ||
| return self.head_node | ||
| current_node = self.head_node | ||
| while current_node.contents != search_value: | ||
| if current_node.next_node is None: | ||
| return None | ||
| current_node = current_node.next_node | ||
| return current_node | ||
| else: | ||
| return None | ||
|
|
||
| def remove(self, remove_value): | ||
| """Remove a node from linked list.""" | ||
| last_node = None | ||
| current_node = self.head_node | ||
| while current_node: | ||
| if current_node.contents == remove_value: | ||
| if last_node: | ||
| last_node.next_node = current_node.next_node | ||
| else: | ||
| self.head_node = current_node.next_node | ||
| self.length -= 1 | ||
| return | ||
| last_node = current_node | ||
| current_node = current_node.next_node | ||
|
|
||
| def display(self): | ||
| """Return the tuple of all values in linked list.""" | ||
| if self.length == 0: | ||
| return None | ||
| else: | ||
| new_list = [self.head_node.contents] | ||
| current_node = self.head_node | ||
| while current_node.next_node is not None: | ||
| current_node = current_node.next_node | ||
| new_list.append(current_node.contents) | ||
| return str(tuple(new_list)) | ||
|
|
||
|
|
||
| class Node(object): | ||
| """Class representation of linked list node.""" | ||
|
|
||
| def __init__(self, contents, next_node): | ||
| """Instantiate linked list node.""" | ||
| self.contents = contents | ||
| self.next_node = next_node |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| """Implementation of Stack data type.""" | ||
|
|
||
| from linked_list import LinkedList | ||
|
|
||
|
|
||
| class Stack(object): | ||
| """Class representation of a stack.""" | ||
|
|
||
| def __init__(self, iterable=None): | ||
| """Instantiate stack.""" | ||
| self.linked_list = LinkedList(iterable) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good use of composition! |
||
| self.length = self.linked_list.length | ||
| self.head_node = self.linked_list.head_node | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. However, since you have all of the linked lists's functionality here, do you really need to assign a head_node variable? What purpose is it serving?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to check the value of the head node, we need to assign it in the Stack, correct? I suppose we could get it using my_stack.linked_list.headnode, but isnt that kind of ugly? |
||
|
|
||
| def push(self, contents): | ||
| """Add node to this stack.""" | ||
| self.linked_list.push(contents) | ||
| self.head_node = self.linked_list.head_node | ||
|
|
||
| def pop(self): | ||
| """Remove and return the current head node.""" | ||
| old_head_node_value = self.linked_list.pop() | ||
| self.head_node = self.linked_list.head_node | ||
| return old_head_node_value | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| """Tests for dll.py.""" | ||
|
|
||
| import pytest | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def sample_dll(): | ||
| """Create testing dlls.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll = DoublyLinkedList([1]) | ||
| empty_dll = DoublyLinkedList() | ||
| new_dll = DoublyLinkedList([1, 2, 3, 4, 5]) | ||
| return one_dll, empty_dll, new_dll | ||
|
|
||
|
|
||
| def test_node_init(): | ||
| """Test node class init.""" | ||
| from dll import Node | ||
| new_node = Node(0, None, None) | ||
| assert new_node.contents == 0 | ||
| assert new_node.next_node is None | ||
| assert new_node.previous_node is None | ||
|
|
||
|
|
||
| def test_dll_init(): | ||
| """Test for dll init.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll, empty_dll, new_dll = sample_dll() | ||
| assert empty_dll.length == 0 | ||
| assert empty_dll.head_node is None | ||
| assert empty_dll.tail_node is None | ||
|
|
||
|
|
||
| def test_dll_push(): | ||
| """Test for dll push.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll, empty_dll, new_dll = sample_dll() | ||
| new_dll.push("new") | ||
| assert new_dll.length == 6 | ||
| assert new_dll.head_node.contents == "new" | ||
| empty_dll.push("second") | ||
| assert empty_dll.length == 1 | ||
| assert empty_dll.head_node.contents == "second" | ||
|
|
||
|
|
||
| def test_dll_append(): | ||
| """Test for dll push.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll, empty_dll, new_dll = sample_dll() | ||
| empty_dll.append("new") | ||
| assert empty_dll.length == 1 | ||
| assert empty_dll.tail_node.contents == "new" | ||
| assert empty_dll.head_node.contents == "new" | ||
| new_dll.append("second") | ||
| assert new_dll.length == 6 | ||
| assert new_dll.tail_node.contents == "second" | ||
| one_dll.append('2') | ||
| assert one_dll.length == 2 | ||
| assert one_dll.tail_node.contents == '2' | ||
| assert one_dll.head_node.contents == 1 | ||
|
|
||
|
|
||
| def test_dll_pop(): | ||
| """Test for dll pop.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll, empty_dll, new_dll = sample_dll() | ||
| assert new_dll.pop().contents == 5 | ||
| assert new_dll.length == 4 | ||
| assert one_dll.pop().contents == 1 | ||
| assert one_dll.length == 0 | ||
|
|
||
|
|
||
| def test_dll_shift(): | ||
| """Test for dll shift.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll, empty_dll, new_dll = sample_dll() | ||
| assert new_dll.shift().contents == 1 | ||
| assert empty_dll.shift() is None | ||
| assert one_dll.shift().contents == 1 | ||
| assert one_dll.length == 0 | ||
|
|
||
|
|
||
| def test_dll_remove(): | ||
| """Test for dll remove.""" | ||
| from dll import DoublyLinkedList | ||
| one_dll, empty_dll, new_dll = sample_dll() | ||
| new_dll.remove(3) | ||
| assert new_dll.length == 4 | ||
| assert new_dll.head_node.next_node.next_node.contents == 2 | ||
| assert new_dll.head_node.next_node.next_node.previous_node.contents == 4 | ||
| try: | ||
| new_dll.remove(10) | ||
| except NameError: | ||
| assert True | ||
| new_dll.remove(5) | ||
| assert new_dll.head_node.contents == 4 | ||
| new_dll.remove(1) | ||
| assert new_dll.tail_node.contents == 2 | ||
| empty_dll = DoublyLinkedList() | ||
| try: | ||
| empty_dll.remove(100) | ||
| except NameError: | ||
| assert True | ||
| one_dll = DoublyLinkedList([1]) | ||
| one_dll.remove(1) | ||
| assert one_dll.head_node is None | ||
| assert one_dll.tail_node is None | ||
| assert one_dll.length == 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mailroom? I just wanted my fancy data structures!