Module grscheller.datastructures.queues
Module grscheller.datastructure.queues - queue based datastructures
Module implementing stateful queue data structures with amortized O(1) pushing and popping from the queue. Obtaining length (number of elements) of a queue is an O(1) operation. Implemented with a Python List based circular array, these data structures will resize themselves as needed. Does not store None as a value.
Expand source code
# Copyright 2023-2024 Geoffrey R. Scheller
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Module grscheller.datastructure.queues - queue based datastructures
Module implementing stateful queue data structures with amortized O(1) pushing and
popping from the queue. Obtaining length (number of elements) of a queue is an O(1)
operation. Implemented with a Python List based circular array, these data structures
will resize themselves as needed. Does not store None as a value.
"""
from __future__ import annotations
__all__ = ['CircularArray', 'DoubleQueue', 'FIFOQueue', 'LIFOQueue']
__author__ = "Geoffrey R. Scheller"
__copyright__ = "Copyright (c) 2023 Geoffrey R. Scheller"
__license__ = "Appache License 2.0"
from typing import Any, Callable
from .core.fp import FP
class CircularArray:
"""Implements an auto-resizing, indexable, double sided queue data
structure. O(1) indexing and O(1) pushes and pops either end. Mainly used to
implement other grscheller.datastructure classes in a has-a relationship
where its functionality is more likely restricted than augmented. This class
is not opinionated regarding None as a value. It freely stores and returns
None values. Can be use in a boolean context to determine if empty.
"""
__slots__ = '_count', '_capacity', '_front', '_rear', '_list'
def __init__(self, *data):
"""Construct a double sided queue"""
size = len(data)
capacity = size + 2
self._count = size
self._capacity = capacity
self._front = 0
self._rear = (size - 1) % capacity
self._list = list(data)
self._list.append(None)
self._list.append(None)
def __iter__(self):
"""Generator yielding the cached contents of the current state of
the CircularArray.
"""
if self._count > 0:
cap = self._capacity
rear = self._rear
pos = self._front
currList = self._list.copy()
while pos != rear:
yield currList[pos]
pos = (pos + 1) % cap
yield currList[pos]
def __reversed__(self):
"""Generator yielding the cached contents of the current state of
the CircularArray in reversed order.
"""
if self._count > 0:
cap = self._capacity
front = self._front
pos = self._rear
currList = self._list.copy()
while pos != front:
yield currList[pos]
pos = (pos - 1) % cap
yield currList[pos]
def __repr__(self):
return f'{self.__class__.__name__}(' + ', '.join(map(repr, self)) + ')'
def __str__(self):
return "(|" + ", ".join(map(repr, self)) + "|)"
def __bool__(self):
"""Returns true if circular array is not empty"""
return self._count > 0
def __len__(self):
"""Returns current number of values in the circlular array"""
return self._count
def __getitem__(self, index: int) -> Any:
"""Get value at a valid index, otherwise raise IndexError"""
cnt = self._count
if 0 <= index < cnt:
return self._list[(self._front + index) % self._capacity]
elif -cnt <= index < 0:
return self._list[(self._front + cnt + index) % self._capacity]
else:
low = -cnt
high = cnt - 1
msg = f'Out of bounds: index = {index} not between {low} and {high}'
msg += 'while getting value.'
msg0 = 'Trying to get value from an empty data structure.'
if cnt > 0:
raise IndexError(msg)
else:
raise IndexError(msg0)
def __setitem__(self, index: int, value: Any) -> Any:
"""Set value at a valid index, otherwise raise IndexError"""
cnt = self._count
if 0 <= index < cnt:
self._list[(self._front + index) % self._capacity] = value
elif -cnt <= index < 0:
self._list[(self._front + cnt + index) % self._capacity] = value
else:
low = -cnt
high = cnt - 1
msg = f'Out of bounds: index = {index} not between {low} and {high}'
msg += 'while setting value.'
msg0 = 'Trying to get value from an empty data structure.'
if cnt > 0:
raise IndexError(msg)
else:
raise IndexError(msg0)
def __eq__(self, other):
"""Returns True if all the data stored in both compare as equal.
Worst case is O(n) behavior for the true case.
"""
if not isinstance(other, type(self)):
return False
if self._count != other._count:
return False
left, frontL, capL, cnt = self, self._front, self._capacity, self._count
right, frontR, capR = other, other._front, other._capacity
nn = 0
while nn < cnt:
if left._list[(frontL+nn)%capL] != right._list[(frontR+nn)%capR]:
return False
nn += 1
return True
def _double(self) -> None:
"""Double capacity of circular array"""
if self._front > self._rear:
data = self._list[self._front:]
data += self._list[:self._rear+1]
data += [None]*(self._capacity)
else:
data = self._list
data += [None]*(self._capacity)
self._list, self._capacity, self._front, self._rear = \
data, 2 * self._capacity, 0, self._count - 1
def compact(self) -> None:
"""Compact the datastructure as much as possible"""
match self._count:
case 0:
self._list, self._capacity, self._front, self._rear = [None]*2, 2, 0, 1
case 1:
data = [self._list[self._front], None]
self._list, self._capacity, self._front, self._rear = data, 2, 0, 0
case _:
if self._front > self._rear:
data = self._list[self._front:]
data += self._list[:self._rear+1]
else:
data = self._list[self._front:self._rear+1]
self._list, self._capacity, self._front, self._rear = data, self._count, 0, self._capacity - 1
def copy(self) -> CircularArray:
return CircularArray(*self)
def reverse(self) -> CircularArray:
return CircularArray(*reversed(self))
def pushR(self, d: Any) -> None:
"""Push data on rear of circle"""
if self._count == self._capacity:
self._double()
self._rear = (self._rear + 1) % self._capacity
self._list[self._rear] = d
self._count += 1
def pushL(self, d: Any) -> None:
"""Push data on front of circle"""
if self._count == self._capacity:
self._double()
self._front = (self._front - 1) % self._capacity
self._list[self._front] = d
self._count += 1
def popR(self) -> Any:
"""Pop data off rear of circle array, returns None if empty"""
if self._count == 0:
return None
else:
d = self._list[self._rear]
self._count, self._list[self._rear], self._rear = \
self._count-1, None, (self._rear - 1) % self._capacity
return d
def popL(self) -> Any:
"""Pop data off front of circle array, returns None if empty"""
if self._count == 0:
return None
else:
d = self._list[self._front]
self._count, self._list[self._front], self._front = \
self._count-1, None, (self._front+1) % self._capacity
return d
def empty(self) -> None:
"""Empty circular array, keep current capacity"""
self._list, self._front, self._rear = \
[None]*self._capacity, 0, self._capacity-1
def capacity(self) -> int:
"""Returns current capacity of circle array"""
return self._capacity
def fractionFilled(self) -> float:
"""Returns current capacity of circle array"""
return self._count/self._capacity
def resize(self, addCapacity = 0) -> None:
"""Compact circle array and add extra capacity"""
self.compact()
if addCapacity > 0:
self._list = self._list + [None]*addCapacity
self._capacity += addCapacity
if self._count == 0:
self._rear = self._capacity - 1
def map(self, f: Callable[[Any], Any]) -> CircularArray:
"""Apply function over the circular array's contents and return new
circular array.
"""
return CircularArray(*map(f, self))
def mapSelf(self, f: Callable[[Any], Any]) -> None:
"""Apply function over the circular array's contents mutatng the
circular array, don't return anything.
"""
ca = CircularArray(*map(f, self))
self._count, self._capacity, self._front, self._rear, self._list = \
ca._count, ca._capacity, ca._front, ca._rear, ca._list
class QueueBase():
"""Abstract base class for the purposes of DRY inheritance of classes
implementing queue type data structures with a list based circular array.
Each queue object "has-a" (contains) a circular array to store its data. The
circular array used will resize itself as needed. Each QueueBase subclass
must ensure that None values do not get pushed onto the circular array.
"""
__slots__ = '_ca',
def __init__(self, *ds):
"""Construct a queue data structure. Cull None values."""
self._ca = CircularArray()
for d in ds:
if d is not None:
self._ca.pushR(d)
def __iter__(self):
"""Iterator yielding data currently stored in queue. Data yielded in
natural FIFO order.
"""
cached = self._ca.copy()
for pos in range(len(cached)):
yield cached[pos]
def __reversed__(self):
"""Reverse iterate over the current state of the queue."""
cached = self._ca.copy()
for pos in range(len(cached)-1, -1, -1):
yield cached[pos]
def __repr__(self):
return f'{self.__class__.__name__}(' + ', '.join(map(repr, self)) + ')'
def __bool__(self):
"""Returns true if queue is not empty."""
return len(self._ca) > 0
def __len__(self):
"""Returns current number of values in queue."""
return len(self._ca)
def __eq__(self, other):
"""Returns True if all the data stored in both compare as equal.
Worst case is O(n) behavior for the true case.
"""
if not isinstance(other, type(self)):
return False
return self._ca == other._ca
def map(self, f: Callable[[Any], Any]) -> None:
"""Apply function over the queue's contents. Suppress any None values
returned by f.
"""
self._ca = QueueBase(*map(f, self))._ca
def reverse(self):
"""Reverse the elements in the Queue"""
self._ca = self._ca.reverse()
class FIFOQueue(QueueBase, FP):
"""Stateful single sided FIFO data structure. Will resize itself as needed.
None represents the absence of a value and ignored if pushed onto an FIFOQueue.
"""
__slots__ = ()
def __str__(self):
return "<< " + " < ".join(map(str, self)) + " <<"
def copy(self) -> FIFOQueue:
"""Return shallow copy of the FIFOQueue in O(n) time & space complexity."""
fifoqueue = FIFOQueue()
fifoqueue._ca = self._ca.copy()
return fifoqueue
def push(self, *ds: Any) -> None:
"""Push data on rear of the FIFOQueue & no return value."""
for d in ds:
if d != None:
self._ca.pushR(d)
def pop(self) -> Any:
"""Pop data off front of the FIFOQueue."""
return self._ca.popL()
def peakLastIn(self) -> Any:
"""Return last element pushed to the FIFOQueue without consuming it"""
if self._ca:
return self._ca[-1]
else:
return None
def peakNextOut(self) -> Any:
"""Return next element ready to pop from the FIFOQueue."""
if self._ca:
return self._ca[0]
else:
return None
class LIFOQueue(QueueBase, FP):
"""Stateful single sided LIFO data structure. Will resize itself as needed.
None represents the absence of a value and ignored if pushed onto an FIFOQueue.
"""
__slots__ = ()
def __str__(self):
return "|| " + " > ".join(map(str, self)) + " ><"
def copy(self) -> LIFOQueue:
"""Return shallow copy of the FIFOQueue in O(n) time & space complexity."""
lifoqueue = LIFOQueue()
lifoqueue._ca = self._ca.copy()
return lifoqueue
def push(self, *ds: Any) -> None:
"""Push data on rear of the LIFOQueue & no return value."""
for d in ds:
if d != None:
self._ca.pushR(d)
def pop(self) -> Any:
"""Pop data off rear of the LIFOQueue."""
return self._ca.popR()
def peak(self) -> Any:
"""Return last element pushed to the LIFOQueue without consuming it"""
if self._ca:
return self._ca[-1]
else:
return None
class DoubleQueue(QueueBase, FP):
"""Stateful double sided queue datastructure. Will resize itself as needed.
None represents the absence of a value and ignored if pushed onto a DoubleQueue.
"""
__slots__ = ()
def __str__(self):
return ">< " + " | ".join(map(str, self)) + " ><"
def copy(self) -> DoubleQueue:
"""Return shallow copy of the DoubleQueue in O(n) time & space complexity."""
dqueue = DoubleQueue()
dqueue._ca = self._ca.copy()
return dqueue
def pushR(self, *ds: Any) -> None:
"""Push data left to right onto rear of the DoubleQueue."""
for d in ds:
if d != None:
self._ca.pushR(d)
def pushL(self, *ds: Any) -> None:
"""Push data left to right onto front of DoubleQueue."""
for d in ds:
if d != None:
self._ca.pushL(d)
def popR(self) -> Any:
"""Pop data off rear of the DoubleQueue"""
return self._ca.popR()
def popL(self) -> Any:
"""Pop data off front of the DoubleQueue"""
return self._ca.popL()
def peakR(self) -> Any:
"""Return right-most element of the DoubleQueue if it exists."""
if self._ca:
return self._ca[-1]
else:
return None
def peakL(self) -> Any:
"""Return left-most element of the DoubleQueue if it exists."""
if self._ca:
return self._ca[0]
else:
return None
def __getitem__(self, index: int) -> Any:
return self._ca[index]
def __setitem__(self, index: int, value):
self._ca[index] = value
if __name__ == "__main__":
pass
Classes
class CircularArray (*data)
-
Implements an auto-resizing, indexable, double sided queue data structure. O(1) indexing and O(1) pushes and pops either end. Mainly used to implement other grscheller.datastructure classes in a has-a relationship where its functionality is more likely restricted than augmented. This class is not opinionated regarding None as a value. It freely stores and returns None values. Can be use in a boolean context to determine if empty.
Construct a double sided queue
Expand source code
class CircularArray: """Implements an auto-resizing, indexable, double sided queue data structure. O(1) indexing and O(1) pushes and pops either end. Mainly used to implement other grscheller.datastructure classes in a has-a relationship where its functionality is more likely restricted than augmented. This class is not opinionated regarding None as a value. It freely stores and returns None values. Can be use in a boolean context to determine if empty. """ __slots__ = '_count', '_capacity', '_front', '_rear', '_list' def __init__(self, *data): """Construct a double sided queue""" size = len(data) capacity = size + 2 self._count = size self._capacity = capacity self._front = 0 self._rear = (size - 1) % capacity self._list = list(data) self._list.append(None) self._list.append(None) def __iter__(self): """Generator yielding the cached contents of the current state of the CircularArray. """ if self._count > 0: cap = self._capacity rear = self._rear pos = self._front currList = self._list.copy() while pos != rear: yield currList[pos] pos = (pos + 1) % cap yield currList[pos] def __reversed__(self): """Generator yielding the cached contents of the current state of the CircularArray in reversed order. """ if self._count > 0: cap = self._capacity front = self._front pos = self._rear currList = self._list.copy() while pos != front: yield currList[pos] pos = (pos - 1) % cap yield currList[pos] def __repr__(self): return f'{self.__class__.__name__}(' + ', '.join(map(repr, self)) + ')' def __str__(self): return "(|" + ", ".join(map(repr, self)) + "|)" def __bool__(self): """Returns true if circular array is not empty""" return self._count > 0 def __len__(self): """Returns current number of values in the circlular array""" return self._count def __getitem__(self, index: int) -> Any: """Get value at a valid index, otherwise raise IndexError""" cnt = self._count if 0 <= index < cnt: return self._list[(self._front + index) % self._capacity] elif -cnt <= index < 0: return self._list[(self._front + cnt + index) % self._capacity] else: low = -cnt high = cnt - 1 msg = f'Out of bounds: index = {index} not between {low} and {high}' msg += 'while getting value.' msg0 = 'Trying to get value from an empty data structure.' if cnt > 0: raise IndexError(msg) else: raise IndexError(msg0) def __setitem__(self, index: int, value: Any) -> Any: """Set value at a valid index, otherwise raise IndexError""" cnt = self._count if 0 <= index < cnt: self._list[(self._front + index) % self._capacity] = value elif -cnt <= index < 0: self._list[(self._front + cnt + index) % self._capacity] = value else: low = -cnt high = cnt - 1 msg = f'Out of bounds: index = {index} not between {low} and {high}' msg += 'while setting value.' msg0 = 'Trying to get value from an empty data structure.' if cnt > 0: raise IndexError(msg) else: raise IndexError(msg0) def __eq__(self, other): """Returns True if all the data stored in both compare as equal. Worst case is O(n) behavior for the true case. """ if not isinstance(other, type(self)): return False if self._count != other._count: return False left, frontL, capL, cnt = self, self._front, self._capacity, self._count right, frontR, capR = other, other._front, other._capacity nn = 0 while nn < cnt: if left._list[(frontL+nn)%capL] != right._list[(frontR+nn)%capR]: return False nn += 1 return True def _double(self) -> None: """Double capacity of circular array""" if self._front > self._rear: data = self._list[self._front:] data += self._list[:self._rear+1] data += [None]*(self._capacity) else: data = self._list data += [None]*(self._capacity) self._list, self._capacity, self._front, self._rear = \ data, 2 * self._capacity, 0, self._count - 1 def compact(self) -> None: """Compact the datastructure as much as possible""" match self._count: case 0: self._list, self._capacity, self._front, self._rear = [None]*2, 2, 0, 1 case 1: data = [self._list[self._front], None] self._list, self._capacity, self._front, self._rear = data, 2, 0, 0 case _: if self._front > self._rear: data = self._list[self._front:] data += self._list[:self._rear+1] else: data = self._list[self._front:self._rear+1] self._list, self._capacity, self._front, self._rear = data, self._count, 0, self._capacity - 1 def copy(self) -> CircularArray: return CircularArray(*self) def reverse(self) -> CircularArray: return CircularArray(*reversed(self)) def pushR(self, d: Any) -> None: """Push data on rear of circle""" if self._count == self._capacity: self._double() self._rear = (self._rear + 1) % self._capacity self._list[self._rear] = d self._count += 1 def pushL(self, d: Any) -> None: """Push data on front of circle""" if self._count == self._capacity: self._double() self._front = (self._front - 1) % self._capacity self._list[self._front] = d self._count += 1 def popR(self) -> Any: """Pop data off rear of circle array, returns None if empty""" if self._count == 0: return None else: d = self._list[self._rear] self._count, self._list[self._rear], self._rear = \ self._count-1, None, (self._rear - 1) % self._capacity return d def popL(self) -> Any: """Pop data off front of circle array, returns None if empty""" if self._count == 0: return None else: d = self._list[self._front] self._count, self._list[self._front], self._front = \ self._count-1, None, (self._front+1) % self._capacity return d def empty(self) -> None: """Empty circular array, keep current capacity""" self._list, self._front, self._rear = \ [None]*self._capacity, 0, self._capacity-1 def capacity(self) -> int: """Returns current capacity of circle array""" return self._capacity def fractionFilled(self) -> float: """Returns current capacity of circle array""" return self._count/self._capacity def resize(self, addCapacity = 0) -> None: """Compact circle array and add extra capacity""" self.compact() if addCapacity > 0: self._list = self._list + [None]*addCapacity self._capacity += addCapacity if self._count == 0: self._rear = self._capacity - 1 def map(self, f: Callable[[Any], Any]) -> CircularArray: """Apply function over the circular array's contents and return new circular array. """ return CircularArray(*map(f, self)) def mapSelf(self, f: Callable[[Any], Any]) -> None: """Apply function over the circular array's contents mutatng the circular array, don't return anything. """ ca = CircularArray(*map(f, self)) self._count, self._capacity, self._front, self._rear, self._list = \ ca._count, ca._capacity, ca._front, ca._rear, ca._list
Methods
def capacity(self) ‑> int
-
Returns current capacity of circle array
Expand source code
def capacity(self) -> int: """Returns current capacity of circle array""" return self._capacity
def compact(self) ‑> None
-
Compact the datastructure as much as possible
Expand source code
def compact(self) -> None: """Compact the datastructure as much as possible""" match self._count: case 0: self._list, self._capacity, self._front, self._rear = [None]*2, 2, 0, 1 case 1: data = [self._list[self._front], None] self._list, self._capacity, self._front, self._rear = data, 2, 0, 0 case _: if self._front > self._rear: data = self._list[self._front:] data += self._list[:self._rear+1] else: data = self._list[self._front:self._rear+1] self._list, self._capacity, self._front, self._rear = data, self._count, 0, self._capacity - 1
def copy(self) ‑> CircularArray
-
Expand source code
def copy(self) -> CircularArray: return CircularArray(*self)
def empty(self) ‑> None
-
Empty circular array, keep current capacity
Expand source code
def empty(self) -> None: """Empty circular array, keep current capacity""" self._list, self._front, self._rear = \ [None]*self._capacity, 0, self._capacity-1
def fractionFilled(self) ‑> float
-
Returns current capacity of circle array
Expand source code
def fractionFilled(self) -> float: """Returns current capacity of circle array""" return self._count/self._capacity
def map(self, f: Callable[[Any], Any]) ‑> CircularArray
-
Apply function over the circular array's contents and return new circular array.
Expand source code
def map(self, f: Callable[[Any], Any]) -> CircularArray: """Apply function over the circular array's contents and return new circular array. """ return CircularArray(*map(f, self))
def mapSelf(self, f: Callable[[Any], Any]) ‑> None
-
Apply function over the circular array's contents mutatng the circular array, don't return anything.
Expand source code
def mapSelf(self, f: Callable[[Any], Any]) -> None: """Apply function over the circular array's contents mutatng the circular array, don't return anything. """ ca = CircularArray(*map(f, self)) self._count, self._capacity, self._front, self._rear, self._list = \ ca._count, ca._capacity, ca._front, ca._rear, ca._list
def popL(self) ‑> Any
-
Pop data off front of circle array, returns None if empty
Expand source code
def popL(self) -> Any: """Pop data off front of circle array, returns None if empty""" if self._count == 0: return None else: d = self._list[self._front] self._count, self._list[self._front], self._front = \ self._count-1, None, (self._front+1) % self._capacity return d
def popR(self) ‑> Any
-
Pop data off rear of circle array, returns None if empty
Expand source code
def popR(self) -> Any: """Pop data off rear of circle array, returns None if empty""" if self._count == 0: return None else: d = self._list[self._rear] self._count, self._list[self._rear], self._rear = \ self._count-1, None, (self._rear - 1) % self._capacity return d
def pushL(self, d: Any) ‑> None
-
Push data on front of circle
Expand source code
def pushL(self, d: Any) -> None: """Push data on front of circle""" if self._count == self._capacity: self._double() self._front = (self._front - 1) % self._capacity self._list[self._front] = d self._count += 1
def pushR(self, d: Any) ‑> None
-
Push data on rear of circle
Expand source code
def pushR(self, d: Any) -> None: """Push data on rear of circle""" if self._count == self._capacity: self._double() self._rear = (self._rear + 1) % self._capacity self._list[self._rear] = d self._count += 1
def resize(self, addCapacity=0) ‑> None
-
Compact circle array and add extra capacity
Expand source code
def resize(self, addCapacity = 0) -> None: """Compact circle array and add extra capacity""" self.compact() if addCapacity > 0: self._list = self._list + [None]*addCapacity self._capacity += addCapacity if self._count == 0: self._rear = self._capacity - 1
def reverse(self) ‑> CircularArray
-
Expand source code
def reverse(self) -> CircularArray: return CircularArray(*reversed(self))
class DoubleQueue (*ds)
-
Stateful double sided queue datastructure. Will resize itself as needed. None represents the absence of a value and ignored if pushed onto a DoubleQueue.
Construct a queue data structure. Cull None values.
Expand source code
class DoubleQueue(QueueBase, FP): """Stateful double sided queue datastructure. Will resize itself as needed. None represents the absence of a value and ignored if pushed onto a DoubleQueue. """ __slots__ = () def __str__(self): return ">< " + " | ".join(map(str, self)) + " ><" def copy(self) -> DoubleQueue: """Return shallow copy of the DoubleQueue in O(n) time & space complexity.""" dqueue = DoubleQueue() dqueue._ca = self._ca.copy() return dqueue def pushR(self, *ds: Any) -> None: """Push data left to right onto rear of the DoubleQueue.""" for d in ds: if d != None: self._ca.pushR(d) def pushL(self, *ds: Any) -> None: """Push data left to right onto front of DoubleQueue.""" for d in ds: if d != None: self._ca.pushL(d) def popR(self) -> Any: """Pop data off rear of the DoubleQueue""" return self._ca.popR() def popL(self) -> Any: """Pop data off front of the DoubleQueue""" return self._ca.popL() def peakR(self) -> Any: """Return right-most element of the DoubleQueue if it exists.""" if self._ca: return self._ca[-1] else: return None def peakL(self) -> Any: """Return left-most element of the DoubleQueue if it exists.""" if self._ca: return self._ca[0] else: return None def __getitem__(self, index: int) -> Any: return self._ca[index] def __setitem__(self, index: int, value): self._ca[index] = value
Ancestors
- grscheller.datastructures.queues.QueueBase
- FP
Methods
def copy(self) ‑> DoubleQueue
-
Return shallow copy of the DoubleQueue in O(n) time & space complexity.
Expand source code
def copy(self) -> DoubleQueue: """Return shallow copy of the DoubleQueue in O(n) time & space complexity.""" dqueue = DoubleQueue() dqueue._ca = self._ca.copy() return dqueue
def peakL(self) ‑> Any
-
Return left-most element of the DoubleQueue if it exists.
Expand source code
def peakL(self) -> Any: """Return left-most element of the DoubleQueue if it exists.""" if self._ca: return self._ca[0] else: return None
def peakR(self) ‑> Any
-
Return right-most element of the DoubleQueue if it exists.
Expand source code
def peakR(self) -> Any: """Return right-most element of the DoubleQueue if it exists.""" if self._ca: return self._ca[-1] else: return None
def popL(self) ‑> Any
-
Pop data off front of the DoubleQueue
Expand source code
def popL(self) -> Any: """Pop data off front of the DoubleQueue""" return self._ca.popL()
def popR(self) ‑> Any
-
Pop data off rear of the DoubleQueue
Expand source code
def popR(self) -> Any: """Pop data off rear of the DoubleQueue""" return self._ca.popR()
def pushL(self, *ds: Any) ‑> None
-
Push data left to right onto front of DoubleQueue.
Expand source code
def pushL(self, *ds: Any) -> None: """Push data left to right onto front of DoubleQueue.""" for d in ds: if d != None: self._ca.pushL(d)
def pushR(self, *ds: Any) ‑> None
-
Push data left to right onto rear of the DoubleQueue.
Expand source code
def pushR(self, *ds: Any) -> None: """Push data left to right onto rear of the DoubleQueue.""" for d in ds: if d != None: self._ca.pushR(d)
Inherited members
class FIFOQueue (*ds)
-
Stateful single sided FIFO data structure. Will resize itself as needed. None represents the absence of a value and ignored if pushed onto an FIFOQueue.
Construct a queue data structure. Cull None values.
Expand source code
class FIFOQueue(QueueBase, FP): """Stateful single sided FIFO data structure. Will resize itself as needed. None represents the absence of a value and ignored if pushed onto an FIFOQueue. """ __slots__ = () def __str__(self): return "<< " + " < ".join(map(str, self)) + " <<" def copy(self) -> FIFOQueue: """Return shallow copy of the FIFOQueue in O(n) time & space complexity.""" fifoqueue = FIFOQueue() fifoqueue._ca = self._ca.copy() return fifoqueue def push(self, *ds: Any) -> None: """Push data on rear of the FIFOQueue & no return value.""" for d in ds: if d != None: self._ca.pushR(d) def pop(self) -> Any: """Pop data off front of the FIFOQueue.""" return self._ca.popL() def peakLastIn(self) -> Any: """Return last element pushed to the FIFOQueue without consuming it""" if self._ca: return self._ca[-1] else: return None def peakNextOut(self) -> Any: """Return next element ready to pop from the FIFOQueue.""" if self._ca: return self._ca[0] else: return None
Ancestors
- grscheller.datastructures.queues.QueueBase
- FP
Methods
def copy(self) ‑> FIFOQueue
-
Return shallow copy of the FIFOQueue in O(n) time & space complexity.
Expand source code
def copy(self) -> FIFOQueue: """Return shallow copy of the FIFOQueue in O(n) time & space complexity.""" fifoqueue = FIFOQueue() fifoqueue._ca = self._ca.copy() return fifoqueue
def peakLastIn(self) ‑> Any
-
Return last element pushed to the FIFOQueue without consuming it
Expand source code
def peakLastIn(self) -> Any: """Return last element pushed to the FIFOQueue without consuming it""" if self._ca: return self._ca[-1] else: return None
def peakNextOut(self) ‑> Any
-
Return next element ready to pop from the FIFOQueue.
Expand source code
def peakNextOut(self) -> Any: """Return next element ready to pop from the FIFOQueue.""" if self._ca: return self._ca[0] else: return None
def pop(self) ‑> Any
-
Pop data off front of the FIFOQueue.
Expand source code
def pop(self) -> Any: """Pop data off front of the FIFOQueue.""" return self._ca.popL()
def push(self, *ds: Any) ‑> None
-
Push data on rear of the FIFOQueue & no return value.
Expand source code
def push(self, *ds: Any) -> None: """Push data on rear of the FIFOQueue & no return value.""" for d in ds: if d != None: self._ca.pushR(d)
Inherited members
class LIFOQueue (*ds)
-
Stateful single sided LIFO data structure. Will resize itself as needed. None represents the absence of a value and ignored if pushed onto an FIFOQueue.
Construct a queue data structure. Cull None values.
Expand source code
class LIFOQueue(QueueBase, FP): """Stateful single sided LIFO data structure. Will resize itself as needed. None represents the absence of a value and ignored if pushed onto an FIFOQueue. """ __slots__ = () def __str__(self): return "|| " + " > ".join(map(str, self)) + " ><" def copy(self) -> LIFOQueue: """Return shallow copy of the FIFOQueue in O(n) time & space complexity.""" lifoqueue = LIFOQueue() lifoqueue._ca = self._ca.copy() return lifoqueue def push(self, *ds: Any) -> None: """Push data on rear of the LIFOQueue & no return value.""" for d in ds: if d != None: self._ca.pushR(d) def pop(self) -> Any: """Pop data off rear of the LIFOQueue.""" return self._ca.popR() def peak(self) -> Any: """Return last element pushed to the LIFOQueue without consuming it""" if self._ca: return self._ca[-1] else: return None
Ancestors
- grscheller.datastructures.queues.QueueBase
- FP
Methods
def copy(self) ‑> LIFOQueue
-
Return shallow copy of the FIFOQueue in O(n) time & space complexity.
Expand source code
def copy(self) -> LIFOQueue: """Return shallow copy of the FIFOQueue in O(n) time & space complexity.""" lifoqueue = LIFOQueue() lifoqueue._ca = self._ca.copy() return lifoqueue
def peak(self) ‑> Any
-
Return last element pushed to the LIFOQueue without consuming it
Expand source code
def peak(self) -> Any: """Return last element pushed to the LIFOQueue without consuming it""" if self._ca: return self._ca[-1] else: return None
def pop(self) ‑> Any
-
Pop data off rear of the LIFOQueue.
Expand source code
def pop(self) -> Any: """Pop data off rear of the LIFOQueue.""" return self._ca.popR()
def push(self, *ds: Any) ‑> None
-
Push data on rear of the LIFOQueue & no return value.
Expand source code
def push(self, *ds: Any) -> None: """Push data on rear of the LIFOQueue & no return value.""" for d in ds: if d != None: self._ca.pushR(d)
Inherited members