Skip to content

Create deque_doubly.py #1652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 5, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions data_structures/linked_list/deque_doubly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"""
Implementing Deque using DoublyLinkedList ...
Operations:
1. insertion in the front -> O(1)
2. insertion in the end -> O(1)
3. remove fron the front -> O(1)
4. remove from the end -> O(1)
"""

class _DoublyLinkedBase:
""" A Private class (to be inherited) """
class _Node:
__slots__ = '_prev', '_data', '_next'
def __init__(self, link_p, element, link_n):
self._prev = link_p
self._data = element
self._next = link_n

def has_next_and_prev(self):
return " Prev -> {0}, Next -> {1}".format(self._prev != None, self._next != None)

def __init__(self):
self._header = self._Node(None, None, None)
self._trailer = self._Node(None, None, None)
self._header._next = self._trailer
self._trailer._prev = self._header
self._size = 0

def __len__(self):
return self._size

def is_empty(self):
return self.__len__() == 0

def _insert(self, predecessor, e, successor):
# Create new_node by setting it's prev.link -> header
# setting it's next.link -> trailer
new_node = self._Node(predecessor, e, successor)
predecessor._next = new_node
successor._prev = new_node
self._size += 1
return self

def _delete(self, node):
predecessor = node._prev
successor = node._next

predecessor._next = successor
successor._prev = predecessor
self._size -= 1
temp = node._data
node._prev = node._next = node._data = None
del node
return temp

class LinkedDeque(_DoublyLinkedBase):

def first(self):
""" return first element
>>> d = LinkedDeque()
>>> d.add_first('A').first()
'A'
>>> d.add_first('B').first()
'B'
"""
if self.is_empty():
raise Exception('List is empty')
return self._header._next._data

def last(self):
""" return last element
>>> d = LinkedDeque()
>>> d.add_last('A').last()
'A'
>>> d.add_last('B').last()
'B'
"""
if self.is_empty():
raise Exception('List is empty')
return self._trailer._prev._data

### DEque Insert Operations (At the front, At the end) ###

def add_first(self, element):
""" insertion in the front
>>> LinkedDeque().add_first('AV').first()
'AV'
"""
return self._insert(self._header, element, self._header._next)

def add_last(self, element):
""" insertion in the end
>>> LinkedDeque().add_last('B').last()
'B'
"""
return self._insert(self._trailer._prev, element, self._trailer)

### DEqueu Remove Operations (At the front, At the end) ###

def remove_first(self):
""" removal from the front
>>> d = LinkedDeque()
>>> d.is_empty()
True
>>> d.remove_first()
Traceback (most recent call last):
...
IndexError: remove_first from empty list
>>> d.add_first('A') # doctest: +ELLIPSIS
<linked_list.deque_doubly.LinkedDeque object at ...
>>> d.remove_first()
'A'
>>> d.is_empty()
True
"""
if self.is_empty():
raise IndexError('remove_first from empty list')
return self._delete(self._header._next)

def remove_last(self):
""" removal in the end
>>> d = LinkedDeque()
>>> d.is_empty()
True
>>> d.remove_last()
Traceback (most recent call last):
...
IndexError: remove_first from empty list
>>> d.add_first('A') # doctest: +ELLIPSIS
<linked_list.deque_doubly.LinkedDeque object at ...
>>> d.remove_last()
'A'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test to make sure that d is empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, i've done something like ...

>>> d = LinkedDeque()
>>> d.is_empty()
True
>>> d.add_first('A') # doctest: +ELLIPSIS
<deque_doubly.LinkedDeque object at ...
>>> d.remove_last()
 'A'
>>> d.is_empty()
True

is it okay sir?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<deque_doubly.LinkedDeque object at ...
—>
<linked_list.deque_doubly.LinkedDeque object at ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why you added those two lines after <deque_doubly ...
are you running this from the linked_list directory?

>>> d.is_empty()
True
"""
if self.is_empty():
raise IndexError('remove_first from empty list')
return self._delete(self._trailer._prev)