Double Ended Queues or Deques using Python

August 5, 2018 3 min read Deques Python

Double ended queues supports insertion or deletion at both the ends.

# Deque :  Deque or Double-Ended Queue supports insertion or deletion at both front and rear 
# Deque ADT :-
# D.add_first(e)   : Add an element e to the front of Deque
# D.add_last(e)    : Add an element e to the rear of Deque
# D.delete_first() : Remove and return the first element, error if empty
# D.delete_last()  : Remove and return the last element, error if empty
# D.first()        : Return the reference of the first element, error if empty
# D.last()         : Return the reference of the last element, error if empty
# D.isEmpty()      : Returns True if Deque is empty
# D.size()         : Returns the size of Deque
 
# Implementation :
# Queue will be implemented using Lists (circular dynamic arrays) with default size of 10

class EmptyDequeException(Exception):
    pass

class Deque(object):
    def __init__(self,N=10):
        self._N = N
        self._A = [None]*self._N
        self._front = -1
        self._rear= -1

    def isEmpty(self):
        if (self._front == -1) and (self._rear == -1):
            return True
        return False

    def add_first(self,e):
        if self.size() == self._N:
            self._resize(self._N*2)
        if self.isEmpty():
            self._front = 0
            self._rear = 0
        else:
            self._front = (self._N + self._front - 1) % self._N
        self._A[self._front] = e

    def add_last(self,e):
        if self.size() == self._N:
            self._resize(self._N*2)
        if self.isEmpty():
            self._front = 0
            self._rear = 0
        else:
            self._rear = (self._N + self._rear + 1) % self._N
        self._A[self._rear] = e

    def delete_first(self):
        if self.isEmpty():
            raise EmptyDequeException("Empty Deque")
        elif self._rear == self._front:
            retElem = self._A[self._front]
            self._A[self._front] = None # Don't care about the data
            self._rear = -1
            self._front = -1
        else:
            retElem = self._A[self._front]
            self._A[self._front] = None # Don't care about the data 
            self._front = (self._front + 1) % self._N
        return retElem

    def delete_last(self):
        if self.isEmpty():
            raise EmptyDequeException("Empty Deque")
        elif self._rear == self._front:
            retElem = self._A[self._rear]
            self._A[self._rear] = None # Don't care about the data 
            self._rear = -1
            self._front = -1
        else:
            retElem = self._A[self._rear]
            self._A[self._rear] = None # Don't care about the data
            self._rear = (self._rear - 1) % self._N
        return retElem

    def first(self):
        if self.isEmpty():
            raise EmptyDequeException("Empty Deque")
        return self._A[self._front]

    def last(self):
        if self.isEmpty():
            raise EmptyDequeException("Empty Deque")
        return self._A[self._rear]

    def size(self):
        if self.isEmpty():
            return 0
        return ((self._N - self._front + self._rear) % self._N) + 1

    def _resize(self,newSize):
        A1 = self._A
        self._A = [None]*newSize
        k = self._front
        for i in range(self.size()):
            self._A[i] = A1[k]
            k = (k + 1)%self._N
        self._front = 0
        self._rear = k
        self._N = newSize
import unittest
from deque import Deque, EmptyDequeException

class TestDeque(unittest.TestCase):
    def setUp(self):
        self.D = Deque(N=5)
  
    def test_empty_deque(self):
        self.assertEqual(self.D.size(),0)
        self.assertTrue(self.D.isEmpty())
        with self.assertRaises(EmptyDequeException) as cm:
            self.D.delete_first()
        expected_msg ="Empty Deque"
        self.assertEquals(cm.exception.message, expected_msg)
        with self.assertRaises(EmptyDequeException) as cm:
            self.D.delete_last()
        expected_msg ="Empty Deque"
        self.assertEquals(cm.exception.message, expected_msg)
        with self.assertRaises(EmptyDequeException) as cm:
            self.D.first()
        expected_msg ="Empty Deque"
        self.assertEquals(cm.exception.message, expected_msg)
        with self.assertRaises(EmptyDequeException) as cm:
            self.D.last()
        expected_msg ="Empty Deque"
        self.assertEquals(cm.exception.message, expected_msg)

    def test_add_delete_element(self):
        self.D.add_first('A')
        self.assertListEqual(['A',None,None,None,None,],self.D._A)
        self.assertEqual(self.D.size(),1)
        self.assertEqual(self.D.first(),'A')
        self.assertEqual(self.D.last(),'A')
        self.assertFalse(self.D.isEmpty())
        self.D.add_last('B')
        self.assertListEqual(['A','B',None,None,None,],self.D._A)
        self.assertEqual(self.D.size(),2)
        self.assertEqual(self.D.first(),'A')
        self.assertEqual(self.D.last(),'B')
        self.D.add_last('C')
        self.D.add_first('AA')
        self.assertListEqual(['A','B','C',None,'AA'],self.D._A)
        self.assertEqual(self.D.size(),4)
        self.assertEqual(self.D.first(),'AA')
        self.D.add_first('AAA')
        self.assertEqual(self.D.size(),5)
        self.assertEqual(self.D.first(),'AAA')
        self.assertEqual(self.D.last(),'C')
        self.assertListEqual(['A','B','C','AAA','AA'],self.D._A)
        self.D.delete_first()
        self.assertEqual(self.D.first(),'AA')
        self.assertEqual(self.D.last(),'C')
        self.D.delete_last()
        self.assertEqual(self.D.first(),'AA')
        self.assertEqual(self.D.last(),'B')
        self.assertListEqual(['A','B',None,None,'AA'],self.D._A)
        self.D.add_last('C')
        self.D.add_last('D')
        self.D.add_last('E')
        self.assertListEqual(['AA','A','B','C','D','E',None,None,None,None],self.D._A)
        self.D.add_last('F')
        self.assertEqual(self.D.first(),'AA')
        self.assertEqual(self.D.last(),'F')
        self.assertEqual(self.D.size(),7)
        self.assertEqual(self.D.delete_first(),'AA')
        self.assertEqual(self.D.delete_last(),'F')
        self.assertListEqual([None,'A','B','C','D','E',None,None,None,None],self.D._A)

if __name__ == '__main__':
    unittest.main(verbosity=2)

Comments