Skip to content

Instantly share code, notes, and snippets.

@santosh
Created June 1, 2019 06:02
Show Gist options
  • Save santosh/d7d75ea97bd03d09b32ce72af14f7ab8 to your computer and use it in GitHub Desktop.
Save santosh/d7d75ea97bd03d09b32ce72af14f7ab8 to your computer and use it in GitHub Desktop.
Stack implementation in Python. #DataStructure
class Node:
""" This Node class has been created for you.
It contains the necessary properties for the solution, which are:
- text
- next
"""
def __init__(self, name):
self.name = name
self.__next = None
def set_next(self, node):
if isinstance(node, Node) or node is None:
self.__next = node
else:
raise TypeError("The 'next' node must be of type Node or None.")
def get_next(self):
return self.__next
def print_details(self):
print("{}".format(self.name))
class LinkedList:
def __init__(self):
self.__root = None
def get_root(self):
return self.__root
def add_start_to_list(self, node):
"""Adds node to the beginning of the list.
:param Node node: Node to be added to the linked list."""
if self.__root:
# Sets the next node of the new node to be __root of LinkedList
node.set_next(self.__root)
self.__root = node
def remove_start_from_list(self):
"""This method:
- If self.__root is None, raise a RuntimeError as the list is already empty
- Create a variable which stores the root
- Set self.__root to be equal to the root's next node
- Return the variable created previously
:return:
"""
if not self.__root:
raise ValueError("List is already empty")
removed_node = self.__root
self.__root = self.__root.get_next()
return removed_node
def print_list(self):
marker = self.__root
while marker:
marker.print_details()
marker = marker.get_next()
def find(self, name):
"""Finds a node in the linked list with a given name.
:param name: the name of the node to find in this list.
:return: Found Node object, or else raises a LookupError."""
marker = self.__root
while marker:
if marker.name == name:
return marker
marker = marker.get_next()
raise LookupError("Name {} not in the linked list.".format(name))
def size(self):
"""Returns the amount of Nodes in the list.
:return: the amount of nodes in this list."""
marker = self.get_root()
count = 0
while marker:
count += 1
marker = marker.get_next()
return count
class LinkedStack:
"""This class is a stack wrapper around a LinkedList.
This means that methods like `add_to_list_start` should now be called `push`, for example.
Don't modify class or method names, just implement methods that currently raise
a NotImplementedError!
"""
def __init__(self):
self.__linked_list = LinkedList()
def push(self, node):
"""Adds node to the start of the linked list property.
:param node: The Node to add
:return: None
"""
self.__linked_list.add_start_to_list(node)
def pop(self):
"""Removes a node from the start of the linked list, and return
the removed node.
:return: Node, the last node of the linked list after being removed.
"""
return self.__linked_list.remove_start_from_list()
def print_details(self):
self.__linked_list.print_list()
def __len__(self):
"""Returns the amount of Nodes in the linked list.
:return: size of stack
"""
return self.__linked_list.size()
# See also:
# https://gist.github.com/santosh/d175565ec09abdea35c038cd513da6ca
# https://gist.github.com/santosh/0c3f4d6c7d9382edaae7094048d71819
from unittest import TestCase
from stack import Node, LinkedList, LinkedStack
class TestLinkedList(TestCase):
"""
This class tests that your LinkedList class was implemented correctly.
All you have to do is run this file.
To do so, right click the file name in your PyCharm project and select the option
Run 'Unittests in tests'
If any tests fail, then you are not done yet.
If all tests pass, good job! You can move on to the next challenge.
"""
def test_node_creation(self):
name = "Jose"
node = Node(name)
self.assertEqual(name, node.name)
def test_list_creation(self):
linked_list = LinkedList()
self.assertIsNone(linked_list.get_root())
def test_add_to_list_start(self):
name = "Jose"
node = Node(name)
linked_list = LinkedList()
linked_list.add_start_to_list(node)
self.assertEqual(linked_list.get_root(), node)
def test_add_many_to_list_start(self):
names = ("Jose", "Rolf", "Anna")
nodes = [Node(name) for name in names]
linked_list = LinkedList()
for node in nodes:
linked_list.add_start_to_list(node)
marker = linked_list.get_root()
for i in range(len(nodes)-1, -1, -1):
self.assertEqual(marker, nodes[i])
marker = marker.get_next()
def test_remove_start_from_list(self):
names = ("Jose", "Rolf", "Anna")
nodes = [Node(name) for name in names]
linked_list = LinkedList()
for node in nodes:
linked_list.add_start_to_list(node)
self.assertIsNotNone(linked_list.find("Jose"))
popped_node = linked_list.remove_start_from_list()
self.assertEqual(popped_node, nodes[len(nodes) - 1])
with self.assertRaises(LookupError):
linked_list.find("Anna")
def test_find_in_list(self):
names = ("Jose", "Rolf", "Anna")
nodes = [Node(name) for name in names]
linked_list = LinkedList()
for node in nodes:
linked_list.add_start_to_list(node)
marker = linked_list.get_root()
for i in range(len(nodes) - 1, -1, -1):
self.assertEqual(linked_list.find(marker.name), nodes[i])
marker = marker.get_next()
def test_find_missing_in_list(self):
linked_list = LinkedList()
with self.assertRaises(LookupError):
linked_list.find("Smith")
class TestStack(TestCase):
def test_push_to_stack(self):
name = "Jose"
node = Node(name)
stack = LinkedStack()
stack.push(node)
self.assertEqual(len(stack), 1)
def test_pop_from_stack(self):
name = "Jose"
node = Node(name)
stack = LinkedStack()
stack.push(node)
self.assertEqual(len(stack), 1)
popped = stack.pop()
self.assertEqual(popped, node)
self.assertEqual(len(stack), 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment