Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
71 changes: 43 additions & 28 deletions src/linked_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
class LinkedList(object):
"""Class representation of linked list."""

def __init__(self, head_node):
def __init__(self, iterable=None):
"""Instantiate linked list."""
self.head_node = head_node
self.length = 1
self.head_node = None
self.length = 0
try:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good! You probably want to go ahead and raise an exception instead of just printing a message. Raising an exception is the best way to let users know that they done fucked up.

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."""
Expand All @@ -16,48 +22,57 @@ def push(self, contents):

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pop should return the value/contents, not the node itself!

return old_head_node
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 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
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_node):
def remove(self, remove_value):
"""Remove a node from linked list."""

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove method is still throwing errors when trying to remove from an empty LinkedList.

if remove_node == self.head_node:
self.head_node = self.head_node.next_node
self.length -= 1
return None
elif remove_node is None:
raise ValueError("Provided value not in list.")
last_node = None
current_node = self.head_node
while current_node.next_node != remove_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
current_node.next_node = current_node.next_node.next_node
self.length -= 1

def display(self):
"""Return the tuple of all values in linked list."""
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 tuple(new_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):
Expand Down
229 changes: 127 additions & 102 deletions src/test_linked_list.py
Original file line number Diff line number Diff line change
@@ -1,108 +1,133 @@
"""Tests for linked_list.py."""

import pytest


@pytest.fixture
def sample_linked_list():
"""Create testing linked list."""
from linked_list import LinkedList
one_llist = LinkedList([1])
empty_llist = LinkedList()
new_llist = LinkedList([1, 2, 3, 4, 5])
return (empty_llist, one_llist, new_llist)


def test_node_init():
"""Test node class init."""
from linked_list import Node
new_node = Node(1, None)
assert new_node.contents == 1 and new_node.next_node is None


def test_linkedlist_init():
"""Test for LinkedList init."""
from linked_list import Node, LinkedList
new_node = Node(34, None)
new_llist = LinkedList(new_node)
assert new_llist.length == 1
assert new_llist.head_node == new_node


def test_linkedlist_push():
"""Test for LinkedList push."""
from linked_list import Node, LinkedList
new_node = Node(34, None)
new_llist = LinkedList(new_node)
new_llist.push(1)
assert new_llist.length == 2
assert new_llist.head_node.contents == 1


def test_linkedlist_pop():
"""Test for LinkedList pop."""
from linked_list import Node, LinkedList
new_node = Node(34, None)
new_llist = LinkedList(new_node)
new_llist.push(1)
new_llist.pop()
assert new_llist.head_node.contents == 34
assert new_llist.length == 1


def test_linkedlist_size():
"""Test for LinkedList size."""
from linked_list import Node, LinkedList
new_node = Node(34, None)
new_llist = LinkedList(new_node)
new_llist.push(1)
new_llist.pop()
new_llist.push('test1')
new_llist.push('test2')
new_llist.push('test3')
new_llist.push('test4')
assert new_llist.size() == 5


def test_linkedlist_search():
"""Test for LinkedList search."""
from linked_list import Node, LinkedList
new_node = Node(34, None)
new_llist = LinkedList(new_node)
new_llist.push(1)
new_llist.pop()
new_llist.push('test1')
new_llist.push('test2')
new_llist.push('test3')
new_llist.push('test4')
assert new_llist.search('test4').contents == 'test4'
assert new_llist.search('test2').contents == 'test2'
assert new_llist.search('test100') is None


def test_linkedlist_remove():
"""Test for LinkedList remove."""
from linked_list import Node, LinkedList
new_node = Node('Test5', None)
new_llist = LinkedList(new_node)
new_llist.push('test4')
new_llist.push('test3')
new_llist.push('test2')
new_llist.push('test1')
new_llist.remove(new_llist.search('test2'))
assert new_llist.size() == 4
assert new_llist.search('test1').next_node.contents == 'test3'
new_node2 = Node('Test5', None)
new_llist2 = LinkedList(new_node2)
new_llist2.push('test4')
new_llist2.push('test3')
new_llist2.push('test2')
new_llist2.push('test1')
new_llist2.remove(new_llist2.search('test1'))
assert new_llist2.head_node.contents == 'test2'
try:
new_llist.remove(new_llist.search('blah'))
except ValueError:
assert True


def test_linkedlist_display():
"""Test for LinkedList remove."""
from linked_list import Node, LinkedList
new_node = Node('test5', None)
new_llist = LinkedList(new_node)
new_llist.push('test4')
new_llist.push('test3')
new_llist.push('test2')
new_llist.push('test1')
new_llist2 = LinkedList(new_node)
assert new_llist.display() == ('test1', 'test2', 'test3', 'test4', 'test5')
assert new_llist2.display() == ('test5',)
new_node = Node(0, None)
assert new_node.contents == 0 and new_node.next_node is None


def test_linkedlist_init_empty_size(sample_linked_list):
"""Test for empty LinkedList init."""
assert sample_linked_list[0].length == 0


def test_linkedlist_init_empty_head(sample_linked_list):
"""Test head in empty LinkedList init."""
assert sample_linked_list[0].head_node is None


def test_linkedlist_init_one_size(sample_linked_list):
"""Test for LinkedList init single item."""
assert sample_linked_list[1].length == 1


def test_linkedlist_init_one_head(sample_linked_list):
"""Test head in LinkedList init single item."""
assert sample_linked_list[1].head_node.contents == 1


def test_linkedlist_init_list_size(sample_linked_list):
"""Test for LinkedList init with list."""
assert sample_linked_list[2].length == 5


def test_linkedlist_init_list_head(sample_linked_list):
"""Test head in LinkedList init with list."""
assert sample_linked_list[2].head_node.contents == 5


def test_linkedlist_push_size(sample_linked_list):
"""Test for LinkedList size after push."""
test_linkedlist = sample_linked_list[2]
test_linkedlist.push("new")
assert test_linkedlist.length == 6


def test_linkedlist_push_val(sample_linked_list):
"""Test for LinkedList head value after push."""
test_linkedlist = sample_linked_list[2]
test_linkedlist.push("new")
assert test_linkedlist.head_node.contents == 'new'


def test_linkedlist_pop_empty(sample_linked_list):
"""Test for Linked List pop on empty."""
with pytest.raises(IndexError):
sample_linked_list[0].pop()


def test_linkedlist_pop_one(sample_linked_list):
"""Test for Linked List pop on list with one item."""
assert sample_linked_list[1].pop() == 1


def test_linkedlist_pop_list(sample_linked_list):
"""Test for Linked List pop on multi-item list."""
assert sample_linked_list[2].pop() == 5


def test_linkedlist_search_list(sample_linked_list):
"""Test for LinkedList search list."""
assert sample_linked_list[2].search(2).contents == 2


def test_linkedlist_search_empty(sample_linked_list):
"""Test for LinkedList search empty list."""
assert sample_linked_list[1].search(2) is None


def test_linkedlist_search_list_false(sample_linked_list):
"""Test for LinkedList search list when search value is not in list."""
assert sample_linked_list[2].search(100) is None


def test_linkedlist_remove(sample_linked_list):
"""Test that removed value is gone after remove()."""
sample_linked_list[2].remove(3)
assert sample_linked_list[2].search(3) is None


def test_linkedlist_remove_pointers(sample_linked_list):
"""Test that previous node points to correct node after remove()."""
sample_linked_list[2].remove(3)
assert sample_linked_list[2].search(4).next_node.contents == 2


def test_linkedlist_remove_head(sample_linked_list):
"""Test LinkedList remove() the head on a list."""
sample_linked_list[2].remove(5)
assert sample_linked_list[2].head_node.contents == 4


def test_linkedlist_remove_empty(sample_linked_list):
"""Test LinkedList remove() on an empty linked list."""
sample_linked_list[1].remove(5) is None


def test_linkedlist_display(sample_linked_list):
"""Test for LinkedList display."""
assert sample_linked_list[2].display() == '(5, 4, 3, 2, 1)'


def test_linkedlist_display_one(sample_linked_list):
"""Test for LinkedList display on single item list."""
assert sample_linked_list[1].display() == '(1,)'


def test_linkedlist_display_empty(sample_linked_list):
"""Test for LinkedList display on empty list."""
assert sample_linked_list[0].display() is None