From 40efd779fa93328c1dc524dde6050e7efc6ceed8 Mon Sep 17 00:00:00 2001 From: TheSuperNoob Date: Tue, 2 Jun 2020 13:36:24 +0200 Subject: [PATCH 1/4] Fix doubly linked list algorithm --- .../linked_list/doubly_linked_list.py | 133 +++++++++++------- 1 file changed, 83 insertions(+), 50 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index e449ed6ec8ac..3b5143ec7248 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -9,76 +9,109 @@ Delete operation is more efficient""" -class LinkedList: # making main class named linked list - def __init__(self): - self.head = None - self.tail = None +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 insertHead(self, x): - 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 - self.tail = newLink + def __init__(self): + self.head = None # First node in list + self.tail = None # Last node in list + + 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 = newLink # newLink <-- currenthead(head) - newLink.next = self.head # newLink <--> currenthead(head) - self.head = newLink # newLink(head) <--> oldhead - - def deleteHead(self): - temp = self.head - self.head = self.head.next # oldHead <--> 2ndElement(head) - # 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): - newLink = Link(x) - newLink.next = None # currentTail(tail) newLink --> - self.tail.next = newLink # currentTail(tail) --> newLink --> - newLink.previous = self.tail # currentTail(tail) <--> newLink --> - self.tail = newLink # oldTail <--> newLink(tail) --> - - def deleteTail(self): - 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): + 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.tail = None + + return head_data + + def insert_at_tail(self, data): + new_node = Node(data) + self.tail.next = new_node + new_node.previous = self.tail + self.tail = new_node + + def delete_tail(self) -> str: + if self.is_empty: + return "List is empty" + + tail_data = self.tail.data + if self.tail.previous: + self.tail = self.tail.previous + self.tail.next = None + else: # if there is no previous node + self.head = None + self.tail = None + + return tail_data + + def delete(self, data) -> str: current = self.head - while current.value != x: # Find the position to delete - current = current.next + while current.data != data: # Find the position to delete + if 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: - self.deleteHead() + self.delete_head() elif current == self.tail: - self.deleteTail() + self.delete_tail() else: # Before: 1 <--> 2(current) <--> 3 current.previous.next = current.next # 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): # Will return True if the list is empty return self.head is None def display(self): # Prints contents of the list + if self.is_empty: + return "List is empty" current = self.head while current is not None: - current.displayLink() + current.display_node() current = current.next print() -class Link: - next = None # This points to the link in front of the new link - previous = None # This points to the link behind the new link - - def __init__(self, x): - self.value = x +class Node: + def __init__(self, data): + self.data = data + self.previous = None + self.next = None - def displayLink(self): - print(f"{self.value}", end=" ") + def display_node(self): + print(f"{self.data}", end=" ") From cefc0343dcdfbbe9accb1182c109b014b9a32240 Mon Sep 17 00:00:00 2001 From: larsthorland Date: Tue, 23 Jun 2020 15:01:43 +0200 Subject: [PATCH 2/4] Fix bug with insert_at_tail method Create __str__() method for Node class and LinkedList class --- .../linked_list/doubly_linked_list.py | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 3b5143ec7248..a61abefdcd0d 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -28,6 +28,16 @@ def __init__(self): self.head = None # First node in list self.tail = None # Last node in list + def __str__(self): + if self.is_empty: + return "List is empty" + 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: @@ -55,9 +65,13 @@ def delete_head(self) -> str: def insert_at_tail(self, data): new_node = Node(data) - self.tail.next = new_node - new_node.previous = self.tail - self.tail = new_node + if self.is_empty: + self.tail = new_node + self.head = new_node + else: + self.tail.next = new_node + new_node.previous = self.tail + self.tail = new_node def delete_tail(self) -> str: if self.is_empty: @@ -94,18 +108,9 @@ def delete(self, data) -> str: return data @property - def is_empty(self): # Will return True if the list is empty + def is_empty(self): # return True if the list is empty return self.head is None - def display(self): # Prints contents of the list - if self.is_empty: - return "List is empty" - current = self.head - while current is not None: - current.display_node() - current = current.next - print() - class Node: def __init__(self, data): @@ -113,5 +118,5 @@ def __init__(self, data): self.previous = None self.next = None - def display_node(self): - print(f"{self.data}", end=" ") + def __str__(self): + return f"{self.data}" From c6d1b1af6d79c1fb44db7a90e72b07a341101d82 Mon Sep 17 00:00:00 2001 From: larsthorland Date: Tue, 23 Jun 2020 19:46:27 +0200 Subject: [PATCH 3/4] Simplify __str__() of LinkedList Returns empty string if there are no elements in the list --- data_structures/linked_list/doubly_linked_list.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index a61abefdcd0d..6dfb47157736 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -29,8 +29,6 @@ def __init__(self): self.tail = None # Last node in list def __str__(self): - if self.is_empty: - return "List is empty" current = self.head nodes = [] while current is not None: From dc976d8898c16900dd252ac5ec1f52563d4fbddb Mon Sep 17 00:00:00 2001 From: John Law Date: Sun, 2 Aug 2020 03:25:12 +0800 Subject: [PATCH 4/4] Fix description --- data_structures/linked_list/doubly_linked_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 6dfb47157736..1b4005f59fae 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -5,7 +5,7 @@ - Each link references the next link and the previous one. - 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. - - 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"""