-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlinked_stack.py
More file actions
69 lines (55 loc) · 2.64 KB
/
linked_stack.py
File metadata and controls
69 lines (55 loc) · 2.64 KB
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
"""Code Fragment 7.5: Implementation of a stack ADT using a singly linked list."""
from typing import Union
class EmptyError(Exception):
...
class LinkedStack:
"""LIFO ``Stack`` implementation using a singly linked list for storage."""
# Nested _Node class -----------------------------------------------------------------
class _Node:
"""Lightweight, nonpublic class for storing a singly linked node."""
__slots__ = "_element", "_next" # Streamline memory usage.
# noinspection PyShadowsBuiltInName
def __init__(self, element, next): # Initialize node's fields.
self._element = element # Reference to user's element.
self._next = next # Reference to next node.
@property
def __element(self):
return self._element
@property
def __next(self):
return self._next
# Stack methods ----------------------------------------------------------------------
def __init__(self):
"""Create an empty stack."""
self._head: Union[LinkedStack._Node, None] = None # Reference to the head node.
self._size = 0 # Number of stack elements.
def __len__(self):
"""Return the number of elements in the stack."""
return self._size
def is_empty(self):
"""Return ``True`` if the stack is empty."""
return self._size == 0
def push(self, e):
"""Add element ``e`` to the top of the stack.\n
- New element is stored as new head node.
- Old head nodes becomes the next node.
- New head node points to old head node.
- First invocation sets next pointer to ``None`` as it's also the tail node.
"""
self._head = self._Node(element=e, next=self._head) # Create and link a new node.
self._size += 1
def top(self):
"""Return (but do not remove) the element at the top of the stack.\n
:raises EmptyError: if the stack is empty."""
if self.is_empty():
raise EmptyError("Stack is empty")
return self._head.__element # Top of stack is at head of list.
def pop(self):
"""Remove and return the element from the top of the stack (i.e. LIFO)\n
:raises EmptyError: if the stack is empty."""
if self.is_empty():
raise EmptyError("Stack is empty")
answer = self._head.__element
self._head = self._head.__next # Bypass the former top node.
self._size -= 1
return answer