Skip to content

Commit 6712ddc

Browse files
committed
Completed Reinforcement section of Exercises
1 parent 00b074f commit 6712ddc

File tree

12 files changed

+1019
-139
lines changed

12 files changed

+1019
-139
lines changed

.idea/workspace.xml

Lines changed: 258 additions & 139 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
class Empty(Exception):
2+
"""Error attempting to access an element from an empty container"""
3+
pass
4+
5+
class LinkedQueue:
6+
"""FIFO Queue implementation using a singly linked list for storage"""
7+
8+
# --------------- nested _Node class -----------------
9+
class _Node:
10+
"""Lightweight, nonpublic class for storing a singly linked node."""
11+
__slots__ = '_element', '_next'
12+
13+
def __init__(self, element, next):
14+
self._element = element
15+
self._next = next
16+
17+
18+
# -------------------- queue methods ------------------
19+
20+
def __init__(self):
21+
"""Create an empty queue."""
22+
23+
self._head = None
24+
self._tail = None
25+
self._size = 0
26+
27+
def __len__(self):
28+
"""Return the size of queue."""
29+
return self._size
30+
31+
def is_empty(self):
32+
"""Return True if queue is empty."""
33+
return self._size == 0
34+
35+
def first(self):
36+
"""Return the first element of the queue.
37+
38+
Raise Empty exception if stack is empty.
39+
"""
40+
if self.is_empty():
41+
raise Empty('Queue is empty')
42+
return self._head._element
43+
44+
def enqueue(self,e):
45+
"""Add an element at the back of the queue"""
46+
newest = self._Node(e, None)
47+
if self.is_empty():
48+
self._head = newest
49+
else:
50+
self._tail._next = newest
51+
self._tail = newest
52+
self._size += 1
53+
54+
def dequeue(self):
55+
""" Return and remove the element at the front of the queue.
56+
57+
Raise empty exception if queue is empty.
58+
"""
59+
if self.is_empty():
60+
raise Empty('Queue is empty.')
61+
answer = self._head._element
62+
self._head = self._head._next
63+
if self.is_empty():
64+
self._tail = None
65+
return answer
66+
67+
def rotate(self):
68+
"""Rotate the front element to the back of the queue"""
69+
if self.is_empty():
70+
raise Empty('Queue is empty.')
71+
print(self._tail._element)
72+
answer = self._head._element
73+
self._head = self._head._next
74+
new_node = self._Node(answer, None)
75+
self._tail._next = new_node
76+
self._tail = new_node
77+
78+
def __str__(self):
79+
"""Return the string representation of string"""
80+
elements = []
81+
walk = self._head
82+
while walk is not None:
83+
elements.append(str(walk._element) + ' ')
84+
walk = walk._next
85+
return ''.join(elements)
86+
87+
# Testing
88+
if __name__ == "__main__":
89+
queue = LinkedQueue()
90+
91+
queue.enqueue(10)
92+
queue.enqueue(20)
93+
queue.enqueue(30)
94+
print(queue.first())
95+
queue.enqueue(40)
96+
print(queue.dequeue())
97+
print(queue)
98+
queue.rotate()
99+
print(queue)
100+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import doubly_linked_list as DLL
2+
3+
4+
class Empty(Exception):
5+
"""Error attempting to access an element from an empty container"""
6+
pass
7+
8+
9+
class LinkedDeque(DLL._DoublyLinkedBase):
10+
"""Double-ended queue implementation based on doubly linked list."""
11+
12+
def first(self):
13+
"""Return the element at the front of deque"""
14+
if self.is_empty():
15+
raise Empty('Deque is empty.')
16+
return self._header._next._element
17+
18+
def last(self):
19+
"""Return the element at the end of the deque"""
20+
if self.is_empty():
21+
raise Empty('Deque is empty')
22+
return self._trailer._prev._element
23+
24+
def insert_first(self, e):
25+
"""Add an element e to the front of the deque"""
26+
self._insert_between(e, self._header, self._header._next)
27+
28+
def insert_last(self, e):
29+
"""Add an element e to the end of the deque"""
30+
self._insert_between(e, self._trailer._prev, self._trailer)
31+
32+
def delet_first(self):
33+
"""Remove and the return the first element of deque.
34+
35+
Raise Empty exception if the deque is empty.
36+
"""
37+
if self.is_empty():
38+
raise Empty('Deque is empty')
39+
return self._delete_node(self._header._next)
40+
41+
def delet_last(self):
42+
"""Remove and the return the first element of deque.
43+
44+
Raise Empty exception if the deque is empty.
45+
"""
46+
if self.is_empty():
47+
raise Empty('Deque is empty')
48+
return self._delete_node(self._trailer._prev)
49+
50+
51+
def middle_node(doubly_list):
52+
"""Return the element at the middle node"""
53+
walk_right = doubly_list._header
54+
walk_left = doubly_list._trailer
55+
while walk_right._next != walk_left._prev:
56+
walk_right = walk_right._next
57+
walk_left = walk_left._prev
58+
return walk_right._next._element
59+
60+
# Testing
61+
if __name__ == "__main__":
62+
double_list = LinkedDeque()
63+
double_list.insert_first(20)
64+
double_list.insert_first(30)
65+
double_list.insert_first(40)
66+
double_list.insert_first(50)
67+
double_list.insert_first(60)
68+
print(middle_node(double_list))
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import positional_list as PL
2+
3+
def max(positional_list):
4+
"""Return the maximum"""
5+
max = positional_list.first().element()
6+
for item in positional_list:
7+
if item > max:
8+
max = item
9+
return max
10+
11+
# Testing
12+
if __name__ == "__main__":
13+
pos_list = PL.PositionalList()
14+
pos_list.add_first(20)
15+
pos_list.add_first(30)
16+
pos_list.add_first(50)
17+
pos_list.add_first(40)
18+
pos_list.add_first(10)
19+
print(max(pos_list))
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import doubly_linked_list as DLL
2+
3+
4+
class Empty(Exception):
5+
"""Error attempting to access an element from an empty container"""
6+
pass
7+
8+
9+
class PositionalList(DLL._DoublyLinkedBase):
10+
"""A sequential container of elements allowing positional access."""
11+
12+
# ------------- nested Position Class --------------
13+
class Position:
14+
"""An abstraction representing the location of a single element."""
15+
16+
def __init__(self, container, node):
17+
"""Constructor should not be invoked by user."""
18+
self._container = container
19+
self._node = node
20+
21+
def element(self):
22+
"""Return the element stored at this Position."""
23+
return self._node._element
24+
25+
def __eq__(self, other):
26+
"""Return True if other is a Position representing the same location."""
27+
return type(other) is type(self) and other._node is self._node
28+
29+
def __ne__(self, other):
30+
"""Return True if other does not represent the same location."""
31+
return not (self == other)
32+
33+
# ------------- utility methods --------------------------
34+
35+
def _validate(self, p):
36+
"""Return position's node, or raise appropriate error if invalid."""
37+
if not isinstance(p, self.Position):
38+
raise TypeError('p must be proper Position type.')
39+
if p._container is not self:
40+
raise ValueError('p does not belong to this container.')
41+
if p._node._next is None: # deprecated nodes
42+
raise ValueError('p is no longer valid.')
43+
return p._node
44+
45+
def _make_position(self, node):
46+
"""Return position instance for given node."""
47+
if node is self._header or node is self._trailer:
48+
return None
49+
else:
50+
return self.Position(self, node)
51+
52+
# ------------------- accessors --------------------------
53+
54+
def first(self):
55+
"""Return the first position in the list."""
56+
return self._make_position(self._header._next)
57+
58+
def last(self):
59+
"""Return the last position in the list."""
60+
return self._make_position(self._trailer._prev)
61+
62+
def before(self, p):
63+
"""Return the position just before Position p"""
64+
node = self._validate(p)
65+
return self._make_position(node._prev)
66+
67+
def after(self, p):
68+
"""Return the position just after Position p"""
69+
node = self._validate(p)
70+
return self._make_position(node._next)
71+
72+
def __iter__(self):
73+
"""Generate a forward iteration of elements in the list."""
74+
cursor = self.first()
75+
while cursor is not None:
76+
yield cursor.element()
77+
cursor = self.after(cursor)
78+
79+
# ----------------------- mutators ---------------------------
80+
81+
# override to return Position instead of node
82+
def _insert_between(self, e, predecessor, successor):
83+
"""Add an element e between two existing nodes and return Position of new node"""
84+
node = super()._insert_between(e, predecessor, successor)
85+
return self._make_position(node)
86+
87+
def add_first(self, e):
88+
"""Insert element at the front of the list and return new Position"""
89+
return self._insert_between(e, self._header, self._header._next)
90+
91+
def add_last(self, e):
92+
"""Insert element at the last of the list and return new Position"""
93+
return self._insert_between(e, self._trailer._prev, self._trailer)
94+
95+
def add_before(self, p, e):
96+
"""Insert element into list before Postion p and return new Position"""
97+
original = self._validate(p)
98+
return self._insert_between(e, original._prev, original)
99+
100+
def add_after(self, p, e):
101+
"""Insert element into list after Postion p and return new Position"""
102+
original = self._validate(p)
103+
return self._insert_between(e, original, original._next)
104+
105+
def delete(self, p):
106+
"""Remove and return the element at position P"""
107+
original = self._validate(p)
108+
return self._delete_node(original)
109+
110+
def replace(self, p, e):
111+
"""Replace the element at positon p with e
112+
113+
Return the element formerly at position p
114+
"""
115+
original = self._validate(p)
116+
old_value = original._element
117+
original._element = e
118+
return old_value
119+
120+
def find(self, e):
121+
"""Find the first position of element if in the list"""
122+
cursor = self.first()
123+
position = 1
124+
while cursor is not None:
125+
if cursor.element() == e:
126+
return position
127+
cursor = self.after(cursor)
128+
position += 1
129+
return None
130+
131+
132+
# Testing
133+
if __name__ == "__main__":
134+
position_list = PositionalList()
135+
136+
position_list.add_last(8)
137+
for element in position_list:
138+
print(element)
139+
140+
pos = position_list.first()
141+
pos2 = position_list.add_after(pos, 5)
142+
for element in position_list:
143+
print(element, end=' ')
144+
145+
print()
146+
pos3 = position_list.add_before(pos2, 3)
147+
for element in position_list:
148+
print(element, end=' ')
149+
150+
print()
151+
print(pos3.element())
152+
print(position_list.after(pos) == pos3)
153+
print(position_list.find(3))
154+
155+
156+

0 commit comments

Comments
 (0)