Bases: IQueue
, Generic[Elem]
A generic unbounded queue -- an implementation of the Queue ADT using
circular array with a dynamic resizing scheme.
Source code in pydsa/queue/circ_array_queue.py
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 | class CircArrayQueue(IQueue, Generic[Elem]):
"""
A generic unbounded queue -- an implementation of the Queue ADT using
circular array with a dynamic resizing scheme.
"""
def __init__(self, init_cap: int, elem_type: ElemTypeName) -> None:
"""Creates an empty queue that can initially store `init_cap` number of
elements of `elem_type`.
Args:
init_cap (int): Initial capacity of the queue.
elem_type (ElemTypeName): Element type.
Raises:
ValueError: If `init_cap` is not a positive integer.
"""
if init_cap <= 0:
raise ValueError(
f'init_cap ({init_cap}) must be a positive integer')
self._elems = py_obj_array_type(init_cap, elem_type)()
self._elem_type = elem_type
self._start_idx = 0
self._num_elems = 0
def __len__(self) -> int:
"""Returns the number of elements in the queue.
Returns:
int: Queue size.
"""
return self._num_elems
def __iter__(self) -> Generator[Elem, None, None]:
"""Iterates over all elements from the front to the end of the queue.
Yields:
The next unprocessed element.
"""
for i in range(len(self)):
idx = (self._start_idx + i) % self._capacity
yield self._elems[idx]
@property
def element_type(self) -> ElemTypeName:
"""Name of the type of each element in the queue.
"""
return self._elem_type
@property
def _capacity(self) -> int:
# Returns the maximum number of elements that the queue can store.
return len(self._elems)
@property
def _end_idx(self) -> int:
# Returns the one-past-the-end position of the queue.
return (self._start_idx + len(self)) % self._capacity
def front(self) -> Elem:
"""Gets the element at the front of the queue if it is not empty.
Returns:
Elem: The front element.
Raises:
RuntimeError: If the queue is empty.
"""
if self.empty:
raise RuntimeError('cannot peek front element from empty queue')
return self._elems[self._start_idx]
def _resize(self, kind: Literal['grow', 'shrink']) -> None:
# Realizes the dynamic resizing scheme.
curr_sz = len(self)
arr = None
# Double underlying array if queue is full.
if kind == 'grow' and curr_sz == self._capacity:
arr = py_obj_array_type(curr_sz * 2, self._elem_type)()
for i, elem in enumerate(self):
arr[i] = elem
# Shrink underlying array by half if size is no greater than a quarter
# of the queue's capacity.
elif (kind == 'shrink'
and self._capacity >= 2 and curr_sz * 4 < self._capacity):
arr = py_obj_array_type(self._capacity // 2, self._elem_type)()
for i, elem in enumerate(self):
arr[i] = elem
if arr:
del self._elems
self._elems = arr
self._start_idx = 0
def enqueue(self, elem: Elem) -> None:
"""Inserts an element at the end of the queue.
Args:
elem (Elem): The element to insert.
"""
self._resize('grow')
self._elems[self._end_idx] = elem
self._num_elems += 1
def dequeue(self) -> Elem:
"""Removes the front element from the queue if it is not empty.
Returns:
Elem: The front element removed from the queue.
Raises:
RuntimeError: If the queue is empty.
"""
if self.empty:
raise RuntimeError('cannot dequeue from an empty queue')
elem = self._elems[self._start_idx]
self._num_elems -= 1
self._start_idx = (self._start_idx + 1) % self._capacity
self._resize('shrink')
return elem
|
__init__(init_cap, elem_type)
Creates an empty queue that can initially store init_cap
number of
elements of elem_type
.
Parameters:
Name |
Type |
Description |
Default |
init_cap |
int
|
Initial capacity of the queue. |
required
|
elem_type |
ElemTypeName
|
Element type. |
required
|
Raises:
Type |
Description |
ValueError
|
If init_cap is not a positive integer. |
Source code in pydsa/queue/circ_array_queue.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | def __init__(self, init_cap: int, elem_type: ElemTypeName) -> None:
"""Creates an empty queue that can initially store `init_cap` number of
elements of `elem_type`.
Args:
init_cap (int): Initial capacity of the queue.
elem_type (ElemTypeName): Element type.
Raises:
ValueError: If `init_cap` is not a positive integer.
"""
if init_cap <= 0:
raise ValueError(
f'init_cap ({init_cap}) must be a positive integer')
self._elems = py_obj_array_type(init_cap, elem_type)()
self._elem_type = elem_type
self._start_idx = 0
self._num_elems = 0
|
__iter__()
Iterates over all elements from the front to the end of the queue.
Yields:
Type |
Description |
Generator[Elem, None, None]
|
The next unprocessed element. |
Source code in pydsa/queue/circ_array_queue.py
49
50
51
52
53
54
55
56
57 | def __iter__(self) -> Generator[Elem, None, None]:
"""Iterates over all elements from the front to the end of the queue.
Yields:
The next unprocessed element.
"""
for i in range(len(self)):
idx = (self._start_idx + i) % self._capacity
yield self._elems[idx]
|
__len__()
Returns the number of elements in the queue.
Returns:
Name | Type |
Description |
int |
int
|
Queue size. |
Source code in pydsa/queue/circ_array_queue.py
| def __len__(self) -> int:
"""Returns the number of elements in the queue.
Returns:
int: Queue size.
"""
return self._num_elems
|
dequeue()
Removes the front element from the queue if it is not empty.
Returns:
Name | Type |
Description |
Elem |
Elem
|
The front element removed from the queue. |
Raises:
Type |
Description |
RuntimeError
|
If the queue is empty. |
Source code in pydsa/queue/circ_array_queue.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 | def dequeue(self) -> Elem:
"""Removes the front element from the queue if it is not empty.
Returns:
Elem: The front element removed from the queue.
Raises:
RuntimeError: If the queue is empty.
"""
if self.empty:
raise RuntimeError('cannot dequeue from an empty queue')
elem = self._elems[self._start_idx]
self._num_elems -= 1
self._start_idx = (self._start_idx + 1) % self._capacity
self._resize('shrink')
return elem
|
element_type()
property
Name of the type of each element in the queue.
Source code in pydsa/queue/circ_array_queue.py
| @property
def element_type(self) -> ElemTypeName:
"""Name of the type of each element in the queue.
"""
return self._elem_type
|
enqueue(elem)
Inserts an element at the end of the queue.
Parameters:
Name |
Type |
Description |
Default |
elem |
Elem
|
The element to insert. |
required
|
Source code in pydsa/queue/circ_array_queue.py
110
111
112
113
114
115
116
117
118 | def enqueue(self, elem: Elem) -> None:
"""Inserts an element at the end of the queue.
Args:
elem (Elem): The element to insert.
"""
self._resize('grow')
self._elems[self._end_idx] = elem
self._num_elems += 1
|
front()
Gets the element at the front of the queue if it is not empty.
Returns:
Name | Type |
Description |
Elem |
Elem
|
The front element. |
Raises:
Type |
Description |
RuntimeError
|
If the queue is empty. |
Source code in pydsa/queue/circ_array_queue.py
75
76
77
78
79
80
81
82
83
84
85
86 | def front(self) -> Elem:
"""Gets the element at the front of the queue if it is not empty.
Returns:
Elem: The front element.
Raises:
RuntimeError: If the queue is empty.
"""
if self.empty:
raise RuntimeError('cannot peek front element from empty queue')
return self._elems[self._start_idx]
|