Skip to content

Commit 1df74d5

Browse files
📝 Doubly Linked List Deletion
1 parent e3c661c commit 1df74d5

File tree

5 files changed

+271
-8
lines changed

5 files changed

+271
-8
lines changed
Loading
Loading
Loading

03_data_structures/02_linked_list/02_linked_list/02_doubly_linked_list/main.py

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ def __init__(self, data=None, next=None, prev=None):
55
self.prev = prev
66

77

8-
class DouplyLinkedList:
8+
class DoublyLinkedList:
99
def __init__(self):
1010
self.head = None
1111
self.tail = None
@@ -59,7 +59,33 @@ def contains(self, data):
5959
print(f"Data item is present in the list. i.e {data}")
6060
return
6161
print(f"Data item is not present in the list. i.e {data}")
62-
62+
63+
def delete(self, data):
64+
current = self.head
65+
node_deleted = False
66+
if current is None:
67+
print("List is empty. Nothing to delete.")
68+
return
69+
elif current.data == data:
70+
self.head.prev = None
71+
node_deleted = True
72+
self.head = current.next
73+
elif self.tail.data == data:
74+
self.tail = self.tail.prev
75+
self.tail.next = None
76+
node_deleted = True
77+
else:
78+
while current:
79+
if current.data == data:
80+
current.prev.next = current.next
81+
current.next.prev = current.prev
82+
node_deleted = True
83+
break
84+
current = current.next
85+
86+
if node_deleted:
87+
print(f"Node with data {data} deleted successfully.")
88+
self.count -= 1
6389

6490
# words = DouplyLinkedList()
6591
# Insert a at start
@@ -93,9 +119,33 @@ def contains(self, data):
93119

94120

95121
# Searching Element
96-
words = DouplyLinkedList()
97-
words.append('egg')
98-
words.append('ham')
99-
words.append('spam')
100-
words.contains("ham")
101-
words.contains("ham2")
122+
# words = DouplyLinkedList()
123+
# words.append('egg')
124+
# words.append('ham')
125+
# words.append('spam')
126+
# words.contains("ham")
127+
# words.contains("ham2")
128+
129+
130+
131+
# Deleting Element
132+
words = DoublyLinkedList()
133+
words.append('egg') # List: egg
134+
words.append('ham') # List: egg <-> ham
135+
words.append('spam') # List: egg <-> ham <-> spam
136+
137+
# before deletion
138+
current = words.head
139+
print("Doubly linked list before deletion:")
140+
while current:
141+
print(current.data)
142+
current = current.next
143+
144+
words.delete('ham')
145+
146+
# after deletion
147+
current = words.head
148+
print("Doubly linked list after deletion:")
149+
while current:
150+
print(current.data)
151+
current = current.next

03_data_structures/02_linked_list/02_linked_list/02_doubly_linked_list/readme.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,3 +726,216 @@ class DoublyLinkedList:
726726
727727
---
728728
729+
# **Doubly Linked List Deletion** 🗑️
730+
731+
## 📖 Overview
732+
733+
A **doubly linked list** allows efficient traversal in both directions because each node holds pointers to its **next** and **previous** neighbors. Deletion in a doubly linked list is simpler than in a singly linked list since we don’t need extra pointers to remember the predecessor—each node already knows its previous node.
734+
735+
- Deletion scenarios (start, end, intermediate, not found) 🔍
736+
737+
## 🚀 Deletion Scenarios
738+
739+
A node to be deleted is identified by matching its `data` field with the target value. There are **four** possible scenarios:
740+
741+
1. **At the start** (head) of the list
742+
2. **At the end** (tail) of the list
743+
3. **Somewhere in the middle** of the list
744+
4. **Not found** in the list
745+
746+
## 🖼️ Figures Explained
747+
748+
### 1. Deletion at the Start (Figure 4.26)
749+
750+
<div align="center">
751+
<img src="./images/09.jpg" alt="" width="600px"/>
752+
</div>
753+
754+
* The **crossed-out** node is the original head. ⚠️
755+
* We update `head` to point to **its next** node. ➡️
756+
* We then set the new head’s `.prev` to `None` (no predecessor). 🔗❌
757+
* The list remains intact forward from the new head.
758+
759+
### 2. Deletion at the End (Figure 4.27)
760+
761+
<div align="center">
762+
<img src="./images/10.jpg" alt="" width="600px"/>
763+
</div>
764+
765+
* The **crossed-out** node is the original tail. ⚠️
766+
* We update `tail` to its `.prev` node (second-last). ⬅️
767+
* We then set the new tail’s `.next` to `None` (no successor). 🔗❌
768+
* The list remains intact backward from the new tail.
769+
770+
### 3. Deletion in the Middle (Figure 4.28)
771+
772+
<div align="center">
773+
<img src="./images/11.jpg" alt="" width="600px"/>
774+
</div>
775+
776+
* Nodes **A**, **B**, **C** are consecutive.
777+
* We want to delete **B** (crossed out). 🗑️
778+
* Set `A.next` to point to `C`. 🔀
779+
* Set `C.prev` to point to `A`. 🔄
780+
* Node **B** is now isolated and removed.
781+
782+
783+
## 💻 Python Implementation
784+
785+
```python
786+
class DoublyLinkedList:
787+
# ... (other methods) ...
788+
789+
def delete(self, data):
790+
"""
791+
Delete a node whose .data matches the given value.
792+
"""
793+
current = self.head # Start at head ➡️
794+
node_deleted = False # Flag to track deletion ✅
795+
796+
# 1. Empty list? 🚫
797+
if current is None:
798+
print("List is empty")
799+
800+
# 2. Delete at head 🔝
801+
elif current.data == data:
802+
self.head.prev = None
803+
node_deleted = True
804+
self.head = current.next
805+
806+
# 3. Delete at tail 🔚
807+
elif self.tail.data == data:
808+
self.tail = self.tail.prev
809+
self.tail.next = None
810+
node_deleted = True
811+
812+
# 4. Delete in middle or report not found 🔍
813+
else:
814+
while current:
815+
if current.data == data:
816+
current.prev.next = current.next
817+
current.next.prev = current.prev
818+
node_deleted = True
819+
break # Stop after deletion
820+
current = current.next
821+
822+
if not node_deleted:
823+
print("Item not found")
824+
825+
# 5. Update count if deleted ➖
826+
if node_deleted:
827+
self.count -= 1
828+
```
829+
830+
831+
## 🔍 Line-by-Line Explanation
832+
833+
1. `current = self.head`
834+
835+
* Start searching from the front of the list. 🌅
836+
837+
2. `node_deleted = False`
838+
839+
* Initialize a flag to record if deletion occurs. 🎯
840+
841+
3. **Empty List Check**
842+
843+
```python
844+
if current is None:
845+
print("List is empty")
846+
```
847+
848+
* If `head` is `None`, the list has no nodes. 🚫
849+
* We notify the user and exit.
850+
851+
4. **Delete at Head**
852+
853+
```python
854+
elif current.data == data:
855+
self.head.prev = None
856+
node_deleted = True
857+
self.head = current.next
858+
```
859+
860+
* Match found at the first node.
861+
* Clear the new head’s `.prev` pointer.
862+
* Move `head` to the next node. 🎉
863+
864+
5. **Delete at Tail**
865+
866+
```python
867+
elif self.tail.data == data:
868+
self.tail = self.tail.prev
869+
self.tail.next = None
870+
node_deleted = True
871+
```
872+
873+
* Match found at the last node.
874+
* Move `tail` backward one node.
875+
* Clear its `.next` pointer. 🏁
876+
877+
6. **Delete in the Middle**
878+
879+
```python
880+
else:
881+
while current:
882+
if current.data == data:
883+
current.prev.next = current.next
884+
current.next.prev = current.prev
885+
node_deleted = True
886+
break
887+
current = current.next
888+
889+
if not node_deleted:
890+
print("Item not found")
891+
```
892+
893+
* Traverse until you find the node.
894+
* Re-link surrounding nodes around the target.
895+
* If no match, inform the user. 📢
896+
897+
7. **Update Count**
898+
899+
```python
900+
if node_deleted:
901+
self.count -= 1
902+
```
903+
904+
* Decrement total node count only if deletion happened. 🔢➖
905+
906+
## 🏃 Dry Run Example
907+
908+
Consider the following scenario:
909+
910+
```python
911+
words = DoublyLinkedList()
912+
words.append('egg') # List: egg
913+
words.append('ham') # List: egg <-> ham
914+
words.append('spam') # List: egg <-> ham <-> spam
915+
words.delete('ham') # Remove middle node
916+
```
917+
918+
**Step-by-step:**
919+
920+
1. **Initial**: `head` → 'egg' ↔︎ 'ham' ↔︎ 'spam' ← `tail`
921+
2. **Search** finds `'ham'` in the middle.
922+
3. Execute:
923+
924+
* `'egg'.next` = `'spam'` ➡️
925+
* `'spam'.prev` = `'egg'` ⬅️
926+
4. `'ham'` is removed. List becomes:
927+
928+
```
929+
head → egg <-> spam ← tail
930+
```
931+
5. `count` decremented by 1.
932+
933+
**Final Output when traversing:**
934+
935+
```
936+
egg
937+
spam
938+
```
939+
940+
---
941+

0 commit comments

Comments
 (0)