Skip to content

Commit 6886bdb

Browse files
📝 Inserting a Node at a begining or ending
1 parent 15066f5 commit 6886bdb

File tree

5 files changed

+328
-2
lines changed

5 files changed

+328
-2
lines changed
Loading
Loading
Loading
Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,59 @@
11
class Node:
2-
def __init__(self,data=None, next=None, prev=None):
2+
def __init__(self, data=None, next=None, prev=None):
33
self.data = data
44
self.next = next
5-
self.prev = prev
5+
self.prev = prev
6+
7+
8+
class DouplyLinkedList:
9+
def __init__(self):
10+
self.head = None
11+
self.tail = None
12+
self.count = 1
13+
14+
def append(self, data):
15+
# Append an item at the end of the list.
16+
new_node = Node(data, None, None)
17+
if self.head is None:
18+
self.head = new_node
19+
self.tail = new_node
20+
else:
21+
new_node.prev = self.tail
22+
self.tail.next = new_node
23+
self.tail = new_node
24+
self.count += 1
25+
26+
def append_at_start(self, data):
27+
new_node = Node(data, next=None, prev=None)
28+
if self.head is None:
29+
self.head = new_node
30+
self.tail = new_node
31+
else:
32+
new_node.next = self.head
33+
self.head.prev = new_node
34+
self.head = new_node
35+
self.count += 1
36+
37+
38+
# 1️⃣ Create list and append some items (using previously defined append)
39+
words = DouplyLinkedList()
40+
words.append('egg')
41+
words.append('ham')
42+
words.append('spam')
43+
44+
# 2️⃣ Display before insertion at start
45+
print("Before append_at_start:")
46+
current = words.head
47+
while current:
48+
print(current.data)
49+
current = current.next
50+
51+
# 3️⃣ Insert at beginning
52+
words.append_at_start('book')
53+
54+
# 4️⃣ Display after insertion
55+
print("\nAfter append_at_start:")
56+
current = words.head
57+
while current:
58+
print(current.data)
59+
current = current.next

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

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,275 @@ class DoublyLinkedList:
112112

113113
```
114114
---
115+
116+
# **Inserting a Node at the Beginning of a Doubly Linked List**
117+
118+
In a **doubly linked list**, each node holds:
119+
120+
* **`data`**
121+
* **`next`** pointer → next node
122+
* **`prev`** pointer → previous node
123+
124+
We maintain two pointers in the list object:
125+
126+
* **`head`** → first node
127+
* **`tail`** → last node
128+
* **`count`** → number of nodes
129+
130+
Below, we’ll walk through **three key figures** illustrating insertion into an **empty list** and **non-empty list**, then present and explain the Python code, and finally show a usage example with output.
131+
132+
## 🖼️ Figures & Their Explanations
133+
134+
*(Carousel: Figures 4.20, 4.21, and 4.22)*
135+
136+
1. **Figure 4.20: Inserting into an *Empty* List**
137+
138+
<div align="center">
139+
<img src="./images/03.jpg" alt="" width="400px"/>
140+
</div>
141+
142+
* Both **`head`** and **`tail`** are `None` → list is empty.
143+
* When we create a single `new_node`, we set:
144+
145+
```plaintext
146+
head → new_node ← tail
147+
new_node.next = None
148+
new_node.prev = None
149+
```
150+
* Now both pointers reference the same sole node.
151+
152+
1. **Figure 4.21: Inserting into a *Non-Empty* List**
153+
154+
<div align="center">
155+
<img src="./images/04.jpg" alt="" width="500px"/>
156+
</div>
157+
158+
* Initial list: A ⇄ B ⇄ C
159+
160+
```plaintext
161+
head → A ⇄ B ⇄ C ← tail
162+
```
163+
* We’ll insert `new_node` before A (at the start).
164+
165+
1. **Figure 4.22: Step-by-Step Link Updates**
166+
The three dotted arrows show the order of pointer updates when inserting at the front:
167+
168+
<div align="center">
169+
<img src="./images/05.jpg" alt="" width="500px"/>
170+
</div>
171+
172+
1. **`new_node.next = head`**
173+
174+
* Link the new node **forward** to the old head.
175+
2. **`head.prev = new_node`**
176+
177+
* Link the old head **backward** to the new node.
178+
3. **`head = new_node`**
179+
180+
* Update the list’s head pointer to the new node.
181+
182+
## 📝 Python Code: `append at end or append_at_start`
183+
184+
```python
185+
class DoublyLinkedList:
186+
def __init__(self):
187+
self.head = None # First node
188+
self.tail = None # Last node
189+
self.count = 0 # Number of nodes
190+
191+
def append(self, data):
192+
# Append an item at the end of the list.
193+
new_node = Node(data, None, None)
194+
if self.head is None:
195+
self.head = new_node
196+
self.tail = new_node
197+
else:
198+
new_node.prev = self.tail
199+
self.tail.next = new_node
200+
self.tail = new_node
201+
self.count += 1
202+
203+
204+
def append_at_start(self, data):
205+
"""
206+
Insert a new node containing `data` at the beginning of the list.
207+
Runs in O(1) time.
208+
"""
209+
# 1️⃣ Create the new standalone node
210+
new_node = Node(data, next=None, prev=None)
211+
212+
# 2️⃣ Empty list? Initialize both head and tail.
213+
if self.head is None:
214+
self.head = new_node
215+
self.tail = new_node
216+
217+
# 3️⃣ Non-empty list? Insert before current head.
218+
else:
219+
new_node.next = self.head # ➡️ Link forward to old head
220+
self.head.prev = new_node # ⬅️ Link old head backward to new_node
221+
self.head = new_node # 🔄 Update head to new_node
222+
223+
# 4️⃣ Maintain node count
224+
self.count += 1
225+
```
226+
227+
# Doubly Linked List Operations
228+
229+
This document provides an in-depth guide to building and manipulating a **Doubly Linked List** in Python. We cover:
230+
231+
1. **Node Definition**
232+
2. **Figures** illustrating insertion scenarios
233+
3. **Append at Start** (Insert at Head) — detailed breakdown
234+
4. **Append at End** (Insert at Tail) — detailed breakdown
235+
5. **Usage Example**
236+
237+
## 1. Node Definition
238+
239+
Each node in a doubly linked list must store:
240+
241+
* **`data`**: The payload or value.
242+
* **`next`**: A reference to the **next** node in the list (or `None`).
243+
* **`prev`**: A reference to the **previous** node in the list (or `None`).
244+
245+
```python
246+
class Node:
247+
def __init__(self, data=None, next=None, prev=None):
248+
self.data = data # 🎁 Node’s stored value
249+
self.next = next # ➡️ Pointer to the next node
250+
self.prev = prev # ⬅️ Pointer to the previous node
251+
```
252+
253+
When a node is created in isolation:
254+
255+
* `next` and `prev` both default to `None`, indicating no connections yet.
256+
257+
258+
## 3. Append at Start (Insert at Head)
259+
260+
### Code
261+
262+
```python
263+
class DoublyLinkedList:
264+
def __init__(self):
265+
self.head = None # First node in the list
266+
self.tail = None # Last node in the list
267+
self.count = 0 # Number of nodes
268+
269+
def append_at_start(self, data):
270+
"""
271+
Inserts a new node containing `data` at the beginning (head) of the list.
272+
Operates in O(1) time.
273+
"""
274+
# 1️⃣ Create the new node with no connections
275+
new_node = Node(data)
276+
277+
# 2️⃣ If the list is empty, both head and tail become new_node
278+
if self.head is None:
279+
self.head = new_node
280+
self.tail = new_node
281+
else:
282+
# 3️⃣ Link new_node → old head
283+
new_node.next = self.head # Forward link
284+
# 4️⃣ Link old head ← new_node
285+
self.head.prev = new_node # Backward link
286+
# 5️⃣ Update head to the new node
287+
self.head = new_node
288+
289+
# 6️⃣ Update node count
290+
self.count += 1
291+
```
292+
293+
### Detailed Explanation
294+
295+
1. **Node Creation**: `new_node = Node(data)` sets up a new node whose `.next` and `.prev` are `None`.
296+
2. **Empty-List Case**:
297+
298+
* If `self.head` is `None`, the list has no elements. Both `head` and `tail` are assigned to `new_node`.
299+
3. **Non-Empty Case**:
300+
301+
* **Forward Link**: `new_node.next = self.head` points the new node to the former head.
302+
* **Backward Link**: `self.head.prev = new_node` sets the old head’s previous pointer to the new node.
303+
* **Reassign Head**: `self.head = new_node` makes the new node the entry point of the list.
304+
4. **Count Update**: Increments `self.count` to reflect the addition.
305+
306+
This method runs in **constant time** (O(1)) and ensures the list remains fully bidirectional.
307+
308+
## 4. Append at End (Insert at Tail)
309+
310+
### Code
311+
312+
```python
313+
def append(self, data):
314+
"""
315+
Appends a new node containing `data` at the end (tail) of the list.
316+
Operates in O(1) time using the tail pointer.
317+
"""
318+
# 1️⃣ Create the new node
319+
new_node = Node(data)
320+
321+
# 2️⃣ If the list is empty, initialize head and tail
322+
if self.head is None:
323+
self.head = new_node
324+
self.tail = new_node
325+
else:
326+
# 3️⃣ Backward link: new_node.prev → old tail
327+
new_node.prev = self.tail
328+
# 4️⃣ Forward link: old tail.next → new_node
329+
self.tail.next = new_node
330+
# 5️⃣ Move tail pointer to new_node
331+
self.tail = new_node
332+
333+
# 6️⃣ Update node count
334+
self.count += 1
335+
```
336+
337+
### Detailed Explanation
338+
339+
1. **Node Creation**: `new_node = Node(data)`.
340+
2. **Empty-List Case**:
341+
342+
* Both `head` and `tail` are assigned to `new_node` when the list was empty.
343+
3. **Non-Empty Case**:
344+
345+
* **Backward Link**: `new_node.prev = self.tail` attaches the new node back to the old tail.
346+
* **Forward Link**: `self.tail.next = new_node` links the old tail to the new node.
347+
* **Reassign Tail**: `self.tail = new_node` updates the tail to the newly added node.
348+
4. **Count Update**: `self.count += 1`.
349+
350+
Again, this method is **O(1)**, thanks to direct access via `self.tail`.
351+
352+
## 5. Usage Example
353+
354+
```python
355+
# Initialize list and append elements
356+
dll = DoublyLinkedList()
357+
dll.append('egg')
358+
dll.append('ham')
359+
dll.append('spam')
360+
361+
# Before insertion at head
362+
enumeration = []
363+
node = dll.head
364+
while node:
365+
enumeration.append(node.data)
366+
node = node.next
367+
print("Before append_at_start:", enumeration)
368+
369+
# Insert at head
370+
dll.append_at_start('book')
371+
372+
# After insertion at head
373+
enumeration = []
374+
node = dll.head
375+
while node:
376+
enumeration.append(node.data)
377+
node = node.next
378+
print("After append_at_start:", enumeration)
379+
```
380+
381+
**Expected Output:**
382+
383+
```
384+
Before append_at_start: ['egg', 'ham', 'spam']
385+
After append_at_start: ['book', 'egg', 'ham', 'spam']
386+
```

0 commit comments

Comments
 (0)