Fix doubly linked list algorithm (#2062)

* Fix doubly linked list algorithm

* Fix bug with insert_at_tail method

Create __str__() method for Node class and LinkedList class

* Simplify __str__() of LinkedList

Returns empty string if there are no elements in the list

* Fix description
This commit is contained in:
TheSuperNoob 2020-08-02 17:55:18 +02:00 committed by GitHub
parent b875f66f00
commit b2e8672f02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,80 +5,116 @@
- Each link references the next link and the previous one. - Each link references the next link and the previous one.
- A Doubly Linked List (DLL) contains an extra pointer, typically called previous - A Doubly Linked List (DLL) contains an extra pointer, typically called previous
pointer, together with next pointer and data which are there in singly linked list. pointer, together with next pointer and data which are there in singly linked list.
- Advantages over SLL - IT can be traversed in both forward and backward direction., - Advantages over SLL - It can be traversed in both forward and backward direction.
Delete operation is more efficient""" Delete operation is more efficient"""
class LinkedList: # making main class named linked list class LinkedList:
"""
>>> linked_list = LinkedList()
>>> linked_list.insert_at_head("a")
>>> linked_list.insert_at_tail("b")
>>> linked_list.delete_tail()
'b'
>>> linked_list.is_empty
False
>>> linked_list.delete_head()
'a'
>>> linked_list.is_empty
True
"""
def __init__(self): def __init__(self):
self.head = None # First node in list
self.tail = None # Last node in list
def __str__(self):
current = self.head
nodes = []
while current is not None:
nodes.append(current)
current = current.next
return " ".join(str(node) for node in nodes)
def insert_at_head(self, data):
new_node = Node(data)
if self.is_empty:
self.tail = new_node
self.head = new_node
else:
self.head.previous = new_node
new_node.next = self.head
self.head = new_node
def delete_head(self) -> str:
if self.is_empty:
return "List is empty"
head_data = self.head.data
if self.head.next:
self.head = self.head.next
self.head.previous = None
else: # If there is no next previous node
self.head = None self.head = None
self.tail = None self.tail = None
def insertHead(self, x): return head_data
newLink = Link(x) # Create a new link with a value attached to it
if self.isEmpty(): # Set the first element added to be the tail def insert_at_tail(self, data):
self.tail = newLink new_node = Node(data)
if self.is_empty:
self.tail = new_node
self.head = new_node
else: else:
self.head.previous = newLink # newLink <-- currenthead(head) self.tail.next = new_node
newLink.next = self.head # newLink <--> currenthead(head) new_node.previous = self.tail
self.head = newLink # newLink(head) <--> oldhead self.tail = new_node
def deleteHead(self): def delete_tail(self) -> str:
temp = self.head if self.is_empty:
self.head = self.head.next # oldHead <--> 2ndElement(head) return "List is empty"
# oldHead --> 2ndElement(head) nothing pointing at it so the old head will be
# removed
self.head.previous = None
if self.head is None:
self.tail = None # if empty linked list
return temp
def insertTail(self, x): tail_data = self.tail.data
newLink = Link(x) if self.tail.previous:
newLink.next = None # currentTail(tail) newLink --> self.tail = self.tail.previous
self.tail.next = newLink # currentTail(tail) --> newLink --> self.tail.next = None
newLink.previous = self.tail # currentTail(tail) <--> newLink --> else: # if there is no previous node
self.tail = newLink # oldTail <--> newLink(tail) --> self.head = None
self.tail = None
def deleteTail(self): return tail_data
temp = self.tail
self.tail = self.tail.previous # 2ndLast(tail) <--> oldTail --> None
self.tail.next = None # 2ndlast(tail) --> None
return temp
def delete(self, x): def delete(self, data) -> str:
current = self.head current = self.head
while current.value != x: # Find the position to delete while current.data != data: # Find the position to delete
if current.next:
current = current.next current = current.next
else: # We have reached the end an no value matches
return "No data matching given value"
if current == self.head: if current == self.head:
self.deleteHead() self.delete_head()
elif current == self.tail: elif current == self.tail:
self.deleteTail() self.delete_tail()
else: # Before: 1 <--> 2(current) <--> 3 else: # Before: 1 <--> 2(current) <--> 3
current.previous.next = current.next # 1 --> 3 current.previous.next = current.next # 1 --> 3
current.next.previous = current.previous # 1 <--> 3 current.next.previous = current.previous # 1 <--> 3
return data
def isEmpty(self): # Will return True if the list is empty @property
def is_empty(self): # return True if the list is empty
return self.head is None return self.head is None
def display(self): # Prints contents of the list
current = self.head
while current is not None:
current.displayLink()
current = current.next
print()
class Node:
def __init__(self, data):
self.data = data
self.previous = None
self.next = None
class Link: def __str__(self):
next = None # This points to the link in front of the new link return f"{self.data}"
previous = None # This points to the link behind the new link
def __init__(self, x):
self.value = x
def displayLink(self):
print(f"{self.value}", end=" ")