-
Notifications
You must be signed in to change notification settings - Fork 101
/
Copy pathlinkedlist.py
118 lines (94 loc) · 4.48 KB
/
linkedlist.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!python
class Node(object):
def __init__(self, data):
"""Initialize this node with the given data."""
self.data = data
self.next = None
def __repr__(self):
"""Return a string representation of this node."""
return 'Node({!r})'.format(self.data)
class LinkedList(object):
def __init__(self, items=None):
"""Initialize this linked list and append the given items, if any."""
self.head = None # First node
self.tail = None # Last node
# Append given items
if items is not None:
for item in items:
self.append(item)
def __str__(self):
"""Return a formatted string representation of this linked list."""
items = ['({!r})'.format(item) for item in self.items()]
return '[{}]'.format(' -> '.join(items))
def __repr__(self):
"""Return a string representation of this linked list."""
return 'LinkedList({!r})'.format(self.items())
def items(self):
"""Return a list (dynamic array) of all items in this linked list.
Best and worst case running time: O(n) for n items in the list (length)
because we always need to loop through all n nodes to get each item."""
items = [] # O(1) time to create empty list
# Start at head node
node = self.head # O(1) time to assign new variable
# Loop until node is None, which is one node too far past tail
while node is not None: # Always n iterations because no early return
items.append(node.data) # O(1) time (on average) to append to list
# Skip to next node to advance forward in linked list
node = node.next # O(1) time to reassign variable
# Now list contains items from all nodes
return items # O(1) time to return list
def is_empty(self):
"""Return a boolean indicating whether this linked list is empty."""
return self.head is None
def length(self):
"""Return the length of this linked list by traversing its nodes.
TODO: Running time: O(???) Why and under what conditions?"""
# TODO: Loop through all nodes and count one for each
def append(self, item):
"""Insert the given item at the tail of this linked list.
TODO: Running time: O(???) Why and under what conditions?"""
# TODO: Create new node to hold given item
# TODO: Append node after tail, if it exists
def prepend(self, item):
"""Insert the given item at the head of this linked list.
TODO: Running time: O(???) Why and under what conditions?"""
# TODO: Create new node to hold given item
# TODO: Prepend node before head, if it exists
def find(self, quality):
"""Return an item from this linked list satisfying the given quality.
TODO: Best case running time: O(???) Why and under what conditions?
TODO: Worst case running time: O(???) Why and under what conditions?"""
# TODO: Loop through all nodes to find item where quality(item) is True
# TODO: Check if node's data satisfies given quality function
def delete(self, item):
"""Delete the given item from this linked list, or raise ValueError.
TODO: Best case running time: O(???) Why and under what conditions?
TODO: Worst case running time: O(???) Why and under what conditions?"""
# TODO: Loop through all nodes to find one whose data matches given item
# TODO: Update previous node to skip around node with matching data
# TODO: Otherwise raise error to tell user that delete has failed
# Hint: raise ValueError('Item not found: {}'.format(item))
def test_linked_list():
ll = LinkedList()
print('list: {}'.format(ll))
print('\nTesting append:')
for item in ['A', 'B', 'C']:
print('append({!r})'.format(item))
ll.append(item)
print('list: {}'.format(ll))
print('head: {}'.format(ll.head))
print('tail: {}'.format(ll.tail))
print('length: {}'.format(ll.length()))
# Enable this after implementing delete method
delete_implemented = False
if delete_implemented:
print('\nTesting delete:')
for item in ['B', 'C', 'A']:
print('delete({!r})'.format(item))
ll.delete(item)
print('list: {}'.format(ll))
print('head: {}'.format(ll.head))
print('tail: {}'.format(ll.tail))
print('length: {}'.format(ll.length()))
if __name__ == '__main__':
test_linked_list()