From 360e389bcbae76bd6a3067c9047a6abb23aea70e Mon Sep 17 00:00:00 2001 From: Arvind-raj06 Date: Sat, 23 Jan 2021 15:53:40 +0530 Subject: [PATCH 1/9] Adding deque --- .../miscellaneous_data_structures/__init__.py | 3 +- .../miscellaneous_data_structures/queue.py | 163 +++++++++++++++++- .../tests/test_queue.py | 26 ++- 3 files changed, 188 insertions(+), 4 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/__init__.py b/pydatastructs/miscellaneous_data_structures/__init__.py index be0827fe7..d50ad4775 100644 --- a/pydatastructs/miscellaneous_data_structures/__init__.py +++ b/pydatastructs/miscellaneous_data_structures/__init__.py @@ -19,7 +19,8 @@ from .queue import ( Queue, - PriorityQueue + PriorityQueue, + Deque ) __all__.extend(queue.__all__) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index 20011d9de..ce77e3cc8 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -5,7 +5,8 @@ __all__ = [ 'Queue', - 'PriorityQueue' + 'PriorityQueue', + 'Deque' ] class Queue(object): @@ -395,3 +396,163 @@ def peek(self): @property def is_empty(self): return self.items.is_empty + +class Deque(object): + """ + Represents the concept of Double-ended queue. + + Parameters + ========== + + implementation : str + Implementation to be used for queue. + By default, 'array' + items : list/tuple + Optional, by default, None + The inital items in the queue. + dtype : A valid python type + Optional, by default NoneType if item + is None. + + Examples + ======== + + >>> from pydatastructs import Deque + >>> q = Deque() + >>> q.append(1) + >>> q.appendleft(2) + >>> q.append(3) + >>> q.popleft() + 2 + >>> len(q) + 2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Double-ended_queue + """ + + def __new__(cls, implementation='array', **kwargs): + if implementation == 'array': + return ArrayDeque( + kwargs.get('items', None), + kwargs.get('dtype', int)) + raise NotImplementedError( + "%s hasn't been implemented yet."%(implementation)) + + @classmethod + def methods(cls): + return ['__new__'] + + def append(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + + def appendleft(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + + def pop(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + + def popleft(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + + @property + def is_empty(self): + raise NotImplementedError( + "This is an abstract method.") + +class ArrayDeque(Queue): + __slots__ = ['front', 'rear'] + + def __new__(cls, items=None, dtype=NoneType): + if items is None: + items = DynamicOneDimensionalArray(dtype, 0) + else: + dtype = type(items[0]) + items = DynamicOneDimensionalArray(dtype, items) + obj = object.__new__(cls) + obj.items, obj.front = items, -1 + if items.size == 0: + obj.front = -1 + obj.rear = -1 + else: + obj.front = 0 + obj.rear = items._num - 1 + return obj + + @classmethod + def methods(cls): + return ['__new__', 'append', 'appendleft', 'pop', 'popleft', 'rear', + 'is_empty', '__len__', '__str__'] + + def append(self, x): + if self.is_empty: + self.front = 0 + self.rear = -1 + self.items._dtype = type(x) + self.items.append(x) + self.rear += 1 + + def appendleft(self, x): + temp = [] + if self.is_empty: + self.front = 0 + self.rear = -1 + self.items._dtype = type(x) + temp.append(x) + for i in range(self.front, self.rear + 1): + temp.append(self.items._data[i]) + self.items = DynamicOneDimensionalArray(type(temp[0]), temp) + self.rear += 1 + + def popleft(self): + if self.is_empty: + raise IndexError("Queue is empty.") + return_value = dc(self.items[self.front]) + front_temp = self.front + if self.front == self.rear: + self.front = -1 + self.rear = -1 + else: + if (self.items._num - 1)/self.items._size < \ + self.items._load_factor: + self.front = 0 + else: + self.front += 1 + self.items.delete(front_temp) + return return_value + + def pop(self): + if self.is_empty: + raise IndexError("Queue is empty.") + return_value = dc(self.items[self.rear]) + rear_temp = self.rear + if self.front == self.rear: + self.front = -1 + self.rear = -1 + else: + if (self.items._num - 1)/self.items._size < \ + self.items._load_factor: + self.front = 0 + else: + self.rear -= 1 + self.items.delete(rear_temp) + return return_value + + @property + def is_empty(self): + return self.__len__() == 0 + + def __len__(self): + return self.items._num + + def __str__(self): + _data = [] + for i in range(self.front, self.rear + 1): + _data.append(self.items._data[i]) + return str(_data) diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index b8ef5ee2a..fba69ae2a 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -1,7 +1,7 @@ -from pydatastructs.miscellaneous_data_structures import Queue +from pydatastructs.miscellaneous_data_structures import Queue, Deque from pydatastructs.miscellaneous_data_structures.queue import ( ArrayQueue, LinkedListQueue, PriorityQueue, - LinkedListPriorityQueue) + LinkedListPriorityQueue, ArrayDeque) from pydatastructs.utils.raises_util import raises from pydatastructs.utils.misc_util import _check_type @@ -80,3 +80,25 @@ def test_ImplementationPriorityQueue(): assert pq1.pop() == 1 assert pq1.is_empty is True assert raises(IndexError, lambda: pq1.peek) + +def test_Queue(): + q = Deque(implementation='array') + q1 = Deque() + assert _check_type(q, ArrayDeque) is True + assert _check_type(q1, ArrayDeque) is True + +def test_ArrayDeque(): + q1 = Deque() + raises(IndexError, lambda: q1.popleft()) + q1 = Deque(implementation='array', items=[0]) + q1.append(1) + q1.append(2) + q1.appendleft(3) + assert str(q1) == '[3, 0, 1, 2]' + assert len(q1) == 4 + assert q1.popleft() == 3 + assert q1.pop() == 2 + assert len(q1) == 2 + assert q1.popleft() == 0 + assert q1.pop() == 1 + assert len(q1) == 0 From a2eca0eee2af81eff502337e1dbef778b50e3124 Mon Sep 17 00:00:00 2001 From: Arvind-raj06 Date: Sun, 24 Jan 2021 23:20:00 +0530 Subject: [PATCH 2/9] Done trying --- .../miscellaneous_data_structures/queue.py | 53 +++++++++++++++---- .../tests/test_queue.py | 13 +++++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index ce77e3cc8..b5758d11c 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -48,7 +48,7 @@ def __new__(cls, implementation='array', **kwargs): if implementation == 'array': return ArrayQueue( kwargs.get('items', None), - kwargs.get('dtype', int)) + kwargs.get('dtype', int), kwargs.get('double_ended', bool)) elif implementation == 'linked_list': return LinkedListQueue( kwargs.get('items', None) @@ -77,9 +77,9 @@ def is_empty(self): class ArrayQueue(Queue): - __slots__ = ['front'] + __slots__ = ['front', 'rear', 'deque'] - def __new__(cls, items=None, dtype=NoneType): + def __new__(cls, items=None, dtype=NoneType, double_ended=False): if items is None: items = DynamicOneDimensionalArray(dtype, 0) else: @@ -89,20 +89,40 @@ def __new__(cls, items=None, dtype=NoneType): obj.items, obj.front = items, -1 if items.size == 0: obj.front = -1 + obj.rear = -1 else: obj.front = 0 + obj.rear = items._num - 1 + obj.deque = double_ended return obj @classmethod def methods(cls): - return ['__new__', 'append', 'popleft', 'rear', - 'is_empty', '__len__', '__str__'] + if cls.deque is True: + return ['__new__', 'append', 'appendleft', 'popleft', 'pop', 'is_empty', '__len__', '__str__'] + else: + return ['__new__', 'append', 'popleft', 'is_empty', '__len__', '__str__'] def append(self, x): if self.is_empty: self.front = 0 self.items._dtype = type(x) self.items.append(x) + self.rear += 1 + + def appendleft(self, x): + if self.deque is False: + raise ImplementationError("Deque operations can't be done here") + temp = [] + if self.is_empty: + self.front = 0 + self.rear = -1 + self.items._dtype = type(x) + temp.append(x) + for i in range(self.front, self.rear + 1): + temp.append(self.items._data[i]) + self.items = DynamicOneDimensionalArray(type(temp[0]), temp) + self.rear += 1 def popleft(self): if self.is_empty: @@ -111,6 +131,7 @@ def popleft(self): front_temp = self.front if self.front == self.rear: self.front = -1 + self.rear = -1 else: if (self.items._num - 1)/self.items._size < \ self.items._load_factor: @@ -120,9 +141,24 @@ def popleft(self): self.items.delete(front_temp) return return_value - @property - def rear(self): - return self.items._last_pos_filled + def pop(self): + if self.deque is False: + raise ImplementationError("Deque operations can't be done here") + if self.is_empty: + raise IndexError("Queue is empty.") + return_value = dc(self.items[self.rear]) + rear_temp = self.rear + if self.front == self.rear: + self.front = -1 + self.rear = -1 + else: + if (self.items._num - 1)/self.items._size < \ + self.items._load_factor: + self.front = 0 + else: + self.rear -= 1 + self.items.delete(rear_temp) + return return_value @property def is_empty(self): @@ -137,7 +173,6 @@ def __str__(self): _data.append(self.items._data[i]) return str(_data) - class LinkedListQueue(Queue): __slots__ = ['queue'] diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index fba69ae2a..c57872aba 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -30,6 +30,19 @@ def test_ArrayQueue(): assert q1.popleft() == 3 assert len(q1) == 0 + q2=Queue(implementation='array', items=[0], deque=True) + q2.append(1) + q2.append(2) + q2.appendleft(3) + assert str(q2) == '[3, 0, 1, 2]' + assert len(q2) == 4 + assert q2.popleft() == 3 + assert q2.pop() == 2 + assert len(q2) == 2 + assert q2.popleft() == 0 + assert q2.pop() == 1 + assert len(q2) == 0 + def test_LinkedListQueue(): q1 = Queue(implementation='linked_list') q1.append(1) From a26d12423bb78a5a7579f65969bb0483632982e1 Mon Sep 17 00:00:00 2001 From: Arvind-raj06 Date: Tue, 26 Jan 2021 19:00:32 +0530 Subject: [PATCH 3/9] Correction --- .../miscellaneous_data_structures/queue.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index b5758d11c..a34691d85 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -77,7 +77,7 @@ def is_empty(self): class ArrayQueue(Queue): - __slots__ = ['front', 'rear', 'deque'] + __slots__ = ['front', 'rear', 'double_ended'] def __new__(cls, items=None, dtype=NoneType, double_ended=False): if items is None: @@ -93,15 +93,12 @@ def __new__(cls, items=None, dtype=NoneType, double_ended=False): else: obj.front = 0 obj.rear = items._num - 1 - obj.deque = double_ended + obj.double_ended = double_ended return obj @classmethod def methods(cls): - if cls.deque is True: - return ['__new__', 'append', 'appendleft', 'popleft', 'pop', 'is_empty', '__len__', '__str__'] - else: - return ['__new__', 'append', 'popleft', 'is_empty', '__len__', '__str__'] + return ['__new__', 'append', 'appendleft', 'popleft', 'pop', 'is_empty', '__len__', '__str__'] def append(self, x): if self.is_empty: @@ -111,7 +108,7 @@ def append(self, x): self.rear += 1 def appendleft(self, x): - if self.deque is False: + if self.double_ended is False: raise ImplementationError("Deque operations can't be done here") temp = [] if self.is_empty: @@ -142,7 +139,7 @@ def popleft(self): return return_value def pop(self): - if self.deque is False: + if self.double_ended is False: raise ImplementationError("Deque operations can't be done here") if self.is_empty: raise IndexError("Queue is empty.") From 0a770af536f0664cf8bdcbc06eb41d1f0a2fa008 Mon Sep 17 00:00:00 2001 From: Arvind-raj06 Date: Thu, 28 Jan 2021 11:59:30 +0530 Subject: [PATCH 4/9] Cleared --- .../miscellaneous_data_structures/__init__.py | 3 +- .../miscellaneous_data_structures/queue.py | 163 +----------------- .../tests/test_queue.py | 28 +-- 3 files changed, 5 insertions(+), 189 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/__init__.py b/pydatastructs/miscellaneous_data_structures/__init__.py index d50ad4775..be0827fe7 100644 --- a/pydatastructs/miscellaneous_data_structures/__init__.py +++ b/pydatastructs/miscellaneous_data_structures/__init__.py @@ -19,8 +19,7 @@ from .queue import ( Queue, - PriorityQueue, - Deque + PriorityQueue ) __all__.extend(queue.__all__) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index a34691d85..8cc57a232 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -5,8 +5,7 @@ __all__ = [ 'Queue', - 'PriorityQueue', - 'Deque' + 'PriorityQueue' ] class Queue(object): @@ -428,163 +427,3 @@ def peek(self): @property def is_empty(self): return self.items.is_empty - -class Deque(object): - """ - Represents the concept of Double-ended queue. - - Parameters - ========== - - implementation : str - Implementation to be used for queue. - By default, 'array' - items : list/tuple - Optional, by default, None - The inital items in the queue. - dtype : A valid python type - Optional, by default NoneType if item - is None. - - Examples - ======== - - >>> from pydatastructs import Deque - >>> q = Deque() - >>> q.append(1) - >>> q.appendleft(2) - >>> q.append(3) - >>> q.popleft() - 2 - >>> len(q) - 2 - - References - ========== - - .. [1] https://en.wikipedia.org/wiki/Double-ended_queue - """ - - def __new__(cls, implementation='array', **kwargs): - if implementation == 'array': - return ArrayDeque( - kwargs.get('items', None), - kwargs.get('dtype', int)) - raise NotImplementedError( - "%s hasn't been implemented yet."%(implementation)) - - @classmethod - def methods(cls): - return ['__new__'] - - def append(self, *args, **kwargs): - raise NotImplementedError( - "This is an abstract method.") - - def appendleft(self, *args, **kwargs): - raise NotImplementedError( - "This is an abstract method.") - - def pop(self, *args, **kwargs): - raise NotImplementedError( - "This is an abstract method.") - - def popleft(self, *args, **kwargs): - raise NotImplementedError( - "This is an abstract method.") - - @property - def is_empty(self): - raise NotImplementedError( - "This is an abstract method.") - -class ArrayDeque(Queue): - __slots__ = ['front', 'rear'] - - def __new__(cls, items=None, dtype=NoneType): - if items is None: - items = DynamicOneDimensionalArray(dtype, 0) - else: - dtype = type(items[0]) - items = DynamicOneDimensionalArray(dtype, items) - obj = object.__new__(cls) - obj.items, obj.front = items, -1 - if items.size == 0: - obj.front = -1 - obj.rear = -1 - else: - obj.front = 0 - obj.rear = items._num - 1 - return obj - - @classmethod - def methods(cls): - return ['__new__', 'append', 'appendleft', 'pop', 'popleft', 'rear', - 'is_empty', '__len__', '__str__'] - - def append(self, x): - if self.is_empty: - self.front = 0 - self.rear = -1 - self.items._dtype = type(x) - self.items.append(x) - self.rear += 1 - - def appendleft(self, x): - temp = [] - if self.is_empty: - self.front = 0 - self.rear = -1 - self.items._dtype = type(x) - temp.append(x) - for i in range(self.front, self.rear + 1): - temp.append(self.items._data[i]) - self.items = DynamicOneDimensionalArray(type(temp[0]), temp) - self.rear += 1 - - def popleft(self): - if self.is_empty: - raise IndexError("Queue is empty.") - return_value = dc(self.items[self.front]) - front_temp = self.front - if self.front == self.rear: - self.front = -1 - self.rear = -1 - else: - if (self.items._num - 1)/self.items._size < \ - self.items._load_factor: - self.front = 0 - else: - self.front += 1 - self.items.delete(front_temp) - return return_value - - def pop(self): - if self.is_empty: - raise IndexError("Queue is empty.") - return_value = dc(self.items[self.rear]) - rear_temp = self.rear - if self.front == self.rear: - self.front = -1 - self.rear = -1 - else: - if (self.items._num - 1)/self.items._size < \ - self.items._load_factor: - self.front = 0 - else: - self.rear -= 1 - self.items.delete(rear_temp) - return return_value - - @property - def is_empty(self): - return self.__len__() == 0 - - def __len__(self): - return self.items._num - - def __str__(self): - _data = [] - for i in range(self.front, self.rear + 1): - _data.append(self.items._data[i]) - return str(_data) diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index c57872aba..465fc50aa 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -1,7 +1,7 @@ -from pydatastructs.miscellaneous_data_structures import Queue, Deque +from pydatastructs.miscellaneous_data_structures import Queue from pydatastructs.miscellaneous_data_structures.queue import ( ArrayQueue, LinkedListQueue, PriorityQueue, - LinkedListPriorityQueue, ArrayDeque) + LinkedListPriorityQueue) from pydatastructs.utils.raises_util import raises from pydatastructs.utils.misc_util import _check_type @@ -30,7 +30,7 @@ def test_ArrayQueue(): assert q1.popleft() == 3 assert len(q1) == 0 - q2=Queue(implementation='array', items=[0], deque=True) + q2=Queue(implementation='array', items=[0], double_ended=True) q2.append(1) q2.append(2) q2.appendleft(3) @@ -93,25 +93,3 @@ def test_ImplementationPriorityQueue(): assert pq1.pop() == 1 assert pq1.is_empty is True assert raises(IndexError, lambda: pq1.peek) - -def test_Queue(): - q = Deque(implementation='array') - q1 = Deque() - assert _check_type(q, ArrayDeque) is True - assert _check_type(q1, ArrayDeque) is True - -def test_ArrayDeque(): - q1 = Deque() - raises(IndexError, lambda: q1.popleft()) - q1 = Deque(implementation='array', items=[0]) - q1.append(1) - q1.append(2) - q1.appendleft(3) - assert str(q1) == '[3, 0, 1, 2]' - assert len(q1) == 4 - assert q1.popleft() == 3 - assert q1.pop() == 2 - assert len(q1) == 2 - assert q1.popleft() == 0 - assert q1.pop() == 1 - assert len(q1) == 0 From a87a5791a26f4b0d2feaa4046689d068ce848e50 Mon Sep 17 00:00:00 2001 From: Arvind-raj06 Date: Fri, 29 Jan 2021 23:49:26 +0530 Subject: [PATCH 5/9] Done --- .../miscellaneous_data_structures/queue.py | 84 ++++++++++++------- .../tests/test_queue.py | 23 ++++- 2 files changed, 74 insertions(+), 33 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index 8cc57a232..cbceb5f3f 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -47,10 +47,12 @@ def __new__(cls, implementation='array', **kwargs): if implementation == 'array': return ArrayQueue( kwargs.get('items', None), - kwargs.get('dtype', int), kwargs.get('double_ended', bool)) + kwargs.get('dtype', int), + kwargs.get('double_ended', False)) elif implementation == 'linked_list': return LinkedListQueue( - kwargs.get('items', None) + kwargs.get('items', None), + kwargs.get('double_ended', False) ) else: raise NotImplementedError( @@ -107,18 +109,19 @@ def append(self, x): self.rear += 1 def appendleft(self, x): - if self.double_ended is False: - raise ImplementationError("Deque operations can't be done here") - temp = [] - if self.is_empty: - self.front = 0 - self.rear = -1 + if self.double_ended: + temp = [] + if self.is_empty: + self.front = 0 + self.rear = -1 self.items._dtype = type(x) - temp.append(x) - for i in range(self.front, self.rear + 1): - temp.append(self.items._data[i]) - self.items = DynamicOneDimensionalArray(type(temp[0]), temp) - self.rear += 1 + temp.append(x) + for i in range(self.front, self.rear + 1): + temp.append(self.items._data[i]) + self.items = DynamicOneDimensionalArray(type(temp[0]), temp) + self.rear += 1 + else: + raise ModuleNotFoundError("Deque operations can't be done here.") def popleft(self): if self.is_empty: @@ -138,23 +141,24 @@ def popleft(self): return return_value def pop(self): - if self.double_ended is False: - raise ImplementationError("Deque operations can't be done here") - if self.is_empty: - raise IndexError("Queue is empty.") - return_value = dc(self.items[self.rear]) - rear_temp = self.rear - if self.front == self.rear: - self.front = -1 - self.rear = -1 - else: - if (self.items._num - 1)/self.items._size < \ - self.items._load_factor: - self.front = 0 + if self.double_ended: + if self.is_empty: + raise IndexError("Queue is empty.") + return_value = dc(self.items[self.rear]) + rear_temp = self.rear + if self.front == self.rear: + self.front = -1 + self.rear = -1 else: - self.rear -= 1 - self.items.delete(rear_temp) - return return_value + if (self.items._num - 1)/self.items._size < \ + self.items._load_factor: + self.front = 0 + else: + self.rear -= 1 + self.items.delete(rear_temp) + return return_value + else: + raise ModuleNotFoundError("Deque operations can't be done here") @property def is_empty(self): @@ -171,9 +175,9 @@ def __str__(self): class LinkedListQueue(Queue): - __slots__ = ['queue'] + __slots__ = ['queue', 'double_ended'] - def __new__(cls, items=None): + def __new__(cls, items=None, double_ended=False): obj = object.__new__(cls) obj.queue = SinglyLinkedList() if items is None: @@ -183,16 +187,32 @@ def __new__(cls, items=None): obj.append(x) else: raise TypeError("Expected type: list/tuple") + obj.double_ended = double_ended return obj @classmethod def methods(cls): - return ['__new__', 'append', 'popleft', 'rear', + return ['__new__', 'append', 'appendleft', 'pop', 'popleft', 'rear', 'is_empty', '__len__', '__str__', 'front', 'size'] def append(self, x): self.queue.append(x) + def appendleft(self, x): + if self.double_ended: + self.queue.appendleft(x) + else: + raise ModuleNotFoundError("Deque operations can't be done here") + + def pop(self): + if self.is_empty: + raise IndexError("Queue is empty.") + if self.double_ended: + return_value = self.queue.popright() + return return_value + else: + raise ModuleNotFoundError("Deque operations can't be done here") + def popleft(self): if self.is_empty: raise IndexError("Queue is empty.") diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index 465fc50aa..a3cfa1680 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -30,7 +30,7 @@ def test_ArrayQueue(): assert q1.popleft() == 3 assert len(q1) == 0 - q2=Queue(implementation='array', items=[0], double_ended=True) + q2 = Queue(implementation='array', items=[0], double_ended=True) q2.append(1) q2.append(2) q2.appendleft(3) @@ -43,6 +43,10 @@ def test_ArrayQueue(): assert q2.pop() == 1 assert len(q2) == 0 + q1 = Queue(implementation='array', items=[0]) + assert raises(ModuleNotFoundError, lambda: q1.appendleft(2)) + + def test_LinkedListQueue(): q1 = Queue(implementation='linked_list') q1.append(1) @@ -73,6 +77,23 @@ def test_LinkedListQueue(): assert rear.key == q1.popleft().key + q1 = Queue(implementation='linked_list', double_ended=True) + q1.appendleft(1) + q2 = Queue(implementation='linked_list', items=[0, 1]) + assert raises(ModuleNotFoundError, lambda: q2.appendleft(1)) + q1 = Queue(implementation='linked_list', items = [0, 1], double_ended=True) + q1.appendleft(2) + q1.append(3) + assert str(q1) == "['2', '0', '1', '3']" + assert len(q1) == 4 + assert q1.popleft().key == 2 + assert q1.pop().key == 3 + assert len(q1) == 2 + assert q1.pop().key == 1 + assert q1.popleft().key == 0 + assert len(q1) == 0 + raises(IndexError, lambda: q1.popleft()) + def test_PriorityQueue(): pq1 = PriorityQueue(implementation='linked_list') assert _check_type(pq1, LinkedListPriorityQueue) is True From e6e8e9dae2e3daf7f545712ce8159e33790659e4 Mon Sep 17 00:00:00 2001 From: czgdp1807 Date: Sun, 31 Jan 2021 12:09:57 +0530 Subject: [PATCH 6/9] Some changes --- .../miscellaneous_data_structures/queue.py | 87 ++++++++++--------- .../tests/test_queue.py | 4 +- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index cbceb5f3f..bad7126eb 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -62,10 +62,24 @@ def __new__(cls, implementation='array', **kwargs): def methods(cls): return ['__new__'] + def _double_ended_check(self): + if not self.double_ended: + raise NotImplementedError( + "This method is only supported for " + "double ended queues.") + def append(self, *args, **kwargs): raise NotImplementedError( "This is an abstract method.") + def appendleft(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + + def pop(self, *args, **kwargs): + raise NotImplementedError( + "This is an abstract method.") + def popleft(self, *args, **kwargs): raise NotImplementedError( "This is an abstract method.") @@ -99,7 +113,8 @@ def __new__(cls, items=None, dtype=NoneType, double_ended=False): @classmethod def methods(cls): - return ['__new__', 'append', 'appendleft', 'popleft', 'pop', 'is_empty', '__len__', '__str__'] + return ['__new__', 'append', 'appendleft', 'popleft', + 'pop', 'is_empty', '__len__', '__str__'] def append(self, x): if self.is_empty: @@ -109,19 +124,17 @@ def append(self, x): self.rear += 1 def appendleft(self, x): - if self.double_ended: - temp = [] - if self.is_empty: - self.front = 0 - self.rear = -1 - self.items._dtype = type(x) - temp.append(x) - for i in range(self.front, self.rear + 1): - temp.append(self.items._data[i]) - self.items = DynamicOneDimensionalArray(type(temp[0]), temp) - self.rear += 1 - else: - raise ModuleNotFoundError("Deque operations can't be done here.") + self._double_ended_check() + temp = [] + if self.is_empty: + self.front = 0 + self.rear = -1 + self.items._dtype = type(x) + temp.append(x) + for i in range(self.front, self.rear + 1): + temp.append(self.items._data[i]) + self.items = DynamicOneDimensionalArray(type(temp[0]), temp) + self.rear += 1 def popleft(self): if self.is_empty: @@ -141,24 +154,23 @@ def popleft(self): return return_value def pop(self): - if self.double_ended: - if self.is_empty: - raise IndexError("Queue is empty.") - return_value = dc(self.items[self.rear]) - rear_temp = self.rear - if self.front == self.rear: - self.front = -1 - self.rear = -1 - else: - if (self.items._num - 1)/self.items._size < \ - self.items._load_factor: - self.front = 0 - else: - self.rear -= 1 - self.items.delete(rear_temp) - return return_value + self._double_ended_check() + if self.is_empty: + raise IndexError("Queue is empty.") + + return_value = dc(self.items[self.rear]) + rear_temp = self.rear + if self.front == self.rear: + self.front = -1 + self.rear = -1 else: - raise ModuleNotFoundError("Deque operations can't be done here") + if (self.items._num - 1)/self.items._size < \ + self.items._load_factor: + self.front = 0 + else: + self.rear -= 1 + self.items.delete(rear_temp) + return return_value @property def is_empty(self): @@ -193,25 +205,22 @@ def __new__(cls, items=None, double_ended=False): @classmethod def methods(cls): return ['__new__', 'append', 'appendleft', 'pop', 'popleft', 'rear', - 'is_empty', '__len__', '__str__', 'front', 'size'] + 'is_empty', '__len__', '__str__', 'front', 'size'] def append(self, x): self.queue.append(x) def appendleft(self, x): + self._double_ended_check() if self.double_ended: self.queue.appendleft(x) - else: - raise ModuleNotFoundError("Deque operations can't be done here") def pop(self): + self._double_ended_check() if self.is_empty: raise IndexError("Queue is empty.") - if self.double_ended: - return_value = self.queue.popright() - return return_value - else: - raise ModuleNotFoundError("Deque operations can't be done here") + return_value = self.queue.popright() + return return_value def popleft(self): if self.is_empty: diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index a3cfa1680..c5c0d6269 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -44,7 +44,7 @@ def test_ArrayQueue(): assert len(q2) == 0 q1 = Queue(implementation='array', items=[0]) - assert raises(ModuleNotFoundError, lambda: q1.appendleft(2)) + assert raises(NotImplementedError, lambda: q1.appendleft(2)) def test_LinkedListQueue(): @@ -80,7 +80,7 @@ def test_LinkedListQueue(): q1 = Queue(implementation='linked_list', double_ended=True) q1.appendleft(1) q2 = Queue(implementation='linked_list', items=[0, 1]) - assert raises(ModuleNotFoundError, lambda: q2.appendleft(1)) + assert raises(NotImplementedError, lambda: q2.appendleft(1)) q1 = Queue(implementation='linked_list', items = [0, 1], double_ended=True) q1.appendleft(2) q1.append(3) From 36a96a07346e60ed240ddb43345ba4d22f219041 Mon Sep 17 00:00:00 2001 From: czgdp1807 Date: Sun, 31 Jan 2021 12:21:47 +0530 Subject: [PATCH 7/9] Some API consistencies --- .../miscellaneous_data_structures/queue.py | 87 ++++++++++--------- .../tests/test_queue.py | 1 - 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index bad7126eb..bb0f56878 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -63,7 +63,7 @@ def methods(cls): return ['__new__'] def _double_ended_check(self): - if not self.double_ended: + if not self._double_ended: raise NotImplementedError( "This method is only supported for " "double ended queues.") @@ -92,7 +92,7 @@ def is_empty(self): class ArrayQueue(Queue): - __slots__ = ['front', 'rear', 'double_ended'] + __slots__ = ['_front', '_rear', '_double_ended'] def __new__(cls, items=None, dtype=NoneType, double_ended=False): if items is None: @@ -101,55 +101,56 @@ def __new__(cls, items=None, dtype=NoneType, double_ended=False): dtype = type(items[0]) items = DynamicOneDimensionalArray(dtype, items) obj = object.__new__(cls) - obj.items, obj.front = items, -1 + obj.items, obj._front = items, -1 if items.size == 0: - obj.front = -1 - obj.rear = -1 + obj._front = -1 + obj._rear = -1 else: - obj.front = 0 - obj.rear = items._num - 1 - obj.double_ended = double_ended + obj._front = 0 + obj._rear = items._num - 1 + obj._double_ended = double_ended return obj @classmethod def methods(cls): return ['__new__', 'append', 'appendleft', 'popleft', - 'pop', 'is_empty', '__len__', '__str__'] + 'pop', 'is_empty', '__len__', '__str__', 'front', + 'rear'] def append(self, x): if self.is_empty: - self.front = 0 + self._front = 0 self.items._dtype = type(x) self.items.append(x) - self.rear += 1 + self._rear += 1 def appendleft(self, x): self._double_ended_check() temp = [] if self.is_empty: - self.front = 0 - self.rear = -1 + self._front = 0 + self._rear = -1 self.items._dtype = type(x) temp.append(x) - for i in range(self.front, self.rear + 1): + for i in range(self._front, self._rear + 1): temp.append(self.items._data[i]) self.items = DynamicOneDimensionalArray(type(temp[0]), temp) - self.rear += 1 + self._rear += 1 def popleft(self): if self.is_empty: raise IndexError("Queue is empty.") - return_value = dc(self.items[self.front]) - front_temp = self.front - if self.front == self.rear: - self.front = -1 - self.rear = -1 + return_value = dc(self.items[self._front]) + front_temp = self._front + if self._front == self._rear: + self._front = -1 + self._rear = -1 else: if (self.items._num - 1)/self.items._size < \ self.items._load_factor: - self.front = 0 + self._front = 0 else: - self.front += 1 + self._front += 1 self.items.delete(front_temp) return return_value @@ -158,20 +159,28 @@ def pop(self): if self.is_empty: raise IndexError("Queue is empty.") - return_value = dc(self.items[self.rear]) - rear_temp = self.rear - if self.front == self.rear: - self.front = -1 - self.rear = -1 + return_value = dc(self.items[self._rear]) + rear_temp = self._rear + if self._front == self._rear: + self._front = -1 + self._rear = -1 else: if (self.items._num - 1)/self.items._size < \ self.items._load_factor: - self.front = 0 + self._front = 0 else: - self.rear -= 1 + self._rear -= 1 self.items.delete(rear_temp) return return_value + @property + def front(self): + return self._front + + @property + def rear(self): + return self._rear + @property def is_empty(self): return self.__len__() == 0 @@ -181,13 +190,13 @@ def __len__(self): def __str__(self): _data = [] - for i in range(self.front, self.rear + 1): + for i in range(self._front, self._rear + 1): _data.append(self.items._data[i]) return str(_data) class LinkedListQueue(Queue): - __slots__ = ['queue', 'double_ended'] + __slots__ = ['queue', '_double_ended'] def __new__(cls, items=None, double_ended=False): obj = object.__new__(cls) @@ -199,20 +208,20 @@ def __new__(cls, items=None, double_ended=False): obj.append(x) else: raise TypeError("Expected type: list/tuple") - obj.double_ended = double_ended + obj._double_ended = double_ended return obj @classmethod def methods(cls): - return ['__new__', 'append', 'appendleft', 'pop', 'popleft', 'rear', - 'is_empty', '__len__', '__str__', 'front', 'size'] + return ['__new__', 'append', 'appendleft', 'pop', 'popleft', + 'is_empty', '__len__', '__str__', 'front', 'rear'] def append(self, x): self.queue.append(x) def appendleft(self, x): self._double_ended_check() - if self.double_ended: + if self._double_ended: self.queue.appendleft(x) def pop(self): @@ -230,7 +239,7 @@ def popleft(self): @property def is_empty(self): - return self.size == 0 + return self.__len__() == 0 @property def front(self): @@ -240,12 +249,8 @@ def front(self): def rear(self): return self.queue.tail - @property - def size(self): - return self.queue.size - def __len__(self): - return self.size + return self.queue.size def __str__(self): return str(self.queue) diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index c5c0d6269..50c30b491 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -66,7 +66,6 @@ def test_LinkedListQueue(): q1 = Queue(implementation='linked_list',items=['a',None,type,{}]) assert len(q1) == 4 - assert q1.size == 4 front = q1.front assert front.key == q1.popleft().key From 705f450db882c6860c67c9d284417cc2128c6a60 Mon Sep 17 00:00:00 2001 From: czgdp1807 Date: Sun, 31 Jan 2021 12:24:49 +0530 Subject: [PATCH 8/9] Docs update --- pydatastructs/miscellaneous_data_structures/queue.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pydatastructs/miscellaneous_data_structures/queue.py b/pydatastructs/miscellaneous_data_structures/queue.py index bb0f56878..cc9a50e67 100644 --- a/pydatastructs/miscellaneous_data_structures/queue.py +++ b/pydatastructs/miscellaneous_data_structures/queue.py @@ -23,6 +23,12 @@ class Queue(object): dtype : A valid python type Optional, by default NoneType if item is None. + Required only for 'array' implementation. + double_ended : bool + Optional, by default, False. + Set to True if the queue should support + additional, appendleft and pop operations + from left and right sides respectively. Examples ======== From b2e588cbd409dbc55c70bf2df4cc11a8305f96f8 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 31 Jan 2021 12:29:05 +0530 Subject: [PATCH 9/9] Apply suggestions from code review --- pydatastructs/miscellaneous_data_structures/tests/test_queue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py index 50c30b491..3ae937019 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_queue.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_queue.py @@ -91,7 +91,7 @@ def test_LinkedListQueue(): assert q1.pop().key == 1 assert q1.popleft().key == 0 assert len(q1) == 0 - raises(IndexError, lambda: q1.popleft()) + assert raises(IndexError, lambda: q1.popleft()) def test_PriorityQueue(): pq1 = PriorityQueue(implementation='linked_list')