Ref: 2 Rename folder to follow previous articles

This commit is contained in:
2026-06-17 18:23:06 -04:00
parent 5f7e37b79b
commit 463614284f
20 changed files with 0 additions and 0 deletions

View File

@@ -1,74 +0,0 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
CMakeLists.txt.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe

View File

@@ -1,30 +0,0 @@
# Reverse Linked List Example
This directory contains a small standalone C++ example for the classic three-pointer linked list reversal algorithm.
## Build
```bash
g++ -std=c++17 -Wall -Wextra -pedantic main.cpp -o reverse_linked_list
```
## Run
```bash
./reverse_linked_list
```
## Expected Output
```text
Original list:
1 -> 2 -> 3 -> 4 -> 5 -> null
Reversed list:
5 -> 4 -> 3 -> 2 -> 1 -> null
```
## Memory walkthrough
see memory_walkthrough.md

View File

@@ -1,216 +0,0 @@
/**
* @file main.cpp
* @brief Demonstrates the classic three-pointer algorithm for reversing a singly linked list.
*
* This example is intentionally small and self-contained.
* It is not meant to show that reversing linked lists is a common production task.
* Instead, it documents the interview pattern clearly enough that a reader unfamiliar
* with it can compile the program, run it, and inspect the output.
*/
#include <iostream>
#include <initializer_list>
/**
* @brief A minimal singly linked list node.
*
* Each node stores an integer value and a pointer to the next node.
* The last node in the list has @c next equal to @c nullptr.
*/
struct Node {
int value; ///< Payload stored in the node.
Node *next; ///< Pointer to the next node, or nullptr for the last node.
};
/**
* @brief Appends a new value to the end of the list.
*
* @param head Reference to the head pointer of the list.
* @param value Value to store in the new node.
*
* This helper is used only to build the demonstration list.
* It keeps the example simple and avoids using STL containers for the list itself,
* because the goal is to demonstrate raw pointer manipulation.
*/
void appendNode (Node *&head, int value) {
Node *node = new Node{value, nullptr};
if (head == nullptr) {
head = node;
return;
}
Node *current = head;
while (current->next != nullptr)
current = current->next;
current->next = node;
}
/**
* @brief Creates a linked list from an initializer list.
*
* @param values Values to insert into the list in the given order.
* @return Pointer to the first node of the created list.
*
* The caller owns the returned list and must release it with freeList().
*/
Node *createList (std::initializer_list<int> values) {
Node *head = nullptr;
for (int value : values)
appendNode (head, value);
return head;
}
/**
* @brief Prints the list without modifying it.
*
* @param head Pointer to the first node of the list.
*
* Output example:
* @code
* 1 -> 2 -> 3 -> 4 -> null
* @endcode
*/
void printList (const Node *head) {
const Node *current = head;
while (current != nullptr) {
std::cout << current->value << " -> ";
current = current->next;
}
std::cout << "null" << std::endl;
}
/**
* @brief Reverses a singly linked list in place.
*
* @param head Pointer to the first node of the original list.
* @return Pointer to the first node of the reversed list.
*
* This is the classic three-pointer interview algorithm.
*
* The three pointers are:
*
* - @c previous — the already reversed part of the list
* - @c current — the node we are processing right now
* - @c next — the original next node saved before we overwrite @c current->next
*
* Why @c next is necessary:
*
* In a singly linked list, each node only knows where the next node is.
* When we execute:
*
* @code
* current->next = previous;
* @endcode
*
* we destroy the original forward link.
* Without saving it first, the rest of the list would be lost.
*
* The algorithm works by moving one node at a time from the original forward chain
* into the reversed chain.
*
* Initial state:
*
* @code
* previous = null
* current = 1 -> 2 -> 3 -> 4 -> null
* @endcode
*
* After processing node 1:
*
* @code
* previous = 1 -> null
* current = 2 -> 3 -> 4 -> null
* @endcode
*
* After processing node 2:
*
* @code
* previous = 2 -> 1 -> null
* current = 3 -> 4 -> null
* @endcode
*
* When @c current becomes @c nullptr, @c previous points to the new head.
*
* Complexity:
*
* - Time: O(n), because each node is visited once.
* - Extra memory: O(1), because only a fixed number of pointers is used.
*/
Node *reverseList (Node *head) {
Node *previous = nullptr;
Node *current = head;
while (current != nullptr) {
/*
* Save the original next node before changing current->next.
* Without this line, the rest of the list would become unreachable.
*/
Node *next = current->next;
/*
* Reverse the direction of the link.
* The current node now points to the already reversed part.
*/
current->next = previous;
/*
* Move previous forward.
* The current node becomes the new head of the reversed part.
*/
previous = current;
/*
* Continue with the node that originally followed current.
*/
current = next;
}
return previous;
}
/**
* @brief Releases all nodes in the list.
*
* @param head Pointer to the first node of the list.
*
* This function is separated from the reversal and printing logic.
* It exists only because this example uses raw @c new to keep the node structure explicit.
*/
void freeList (Node *head) {
Node *current = head;
while (current != nullptr) {
Node *next = current->next;
delete current;
current = next;
}
}
/**
* @brief Program entry point.
*
* Builds a small list, prints it, reverses it, prints it again,
* and finally releases all allocated nodes.
*/
int main() {
Node *list = createList ({1, 2, 3, 4, 5});
std::cout << "Original list:" << std::endl;
printList (list);
list = reverseList (list);
std::cout << "\nReversed list:" << std::endl;
printList (list);
freeList (list);
return 0;
}

View File

@@ -1,827 +0,0 @@
# Reverse Linked List — Memory Walkthrough
This walkthrough explains the classic three-pointer linked list reversal using a memory-oriented view.
The goal is not only to show that the algorithm works, but also to show what happens to:
- stack variables
- heap nodes
- `next` fields inside each node
The example list contains three nodes:
```text
1 -> 2 -> 3 -> null
```
For clarity, fake addresses are used:
```text
Node 1: 0x1000
Node 2: 0x2000
Node 3: 0x3000
```
These addresses are illustrative only.
A real program will use different addresses.
---
## Algorithm
```cpp
Node* reverseList(Node* head) {
Node* previous = nullptr;
Node* current = head;
while(current != nullptr) {
Node* next = current->next;
current->next = previous;
previous = current;
current = next;
}
return previous;
}
```
The three important pointers are:
| Pointer | Meaning |
|---|---|
| `previous` | Head of the already reversed part |
| `current` | Node currently being processed |
| `next` | Saved pointer to the remaining original list |
The most important rule is:
> Save `next` before changing `current->next`.
Otherwise the rest of the original list may become unreachable.
---
## Step 0 — Initial State
Before the loop starts:
```cpp
Node* previous = nullptr;
Node* current = head;
```
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | nullptr |
| current | 0x1000 |
| next | not set |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=2000 |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=3000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
### Logical view
```text
head/current
|
v
1 -> 2 -> 3 -> null
previous -> null
```
At this point, nothing has been reversed yet.
---
## Step 1 — Save `next`
Inside the first loop iteration:
```cpp
Node* next = current->next;
```
`current` points to Node 1.
`current->next` points to Node 2.
So:
```text
next = 0x2000
```
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | nullptr |
| current | 0x1000 |
| next | 0x2000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=2000 |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=3000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
Nothing in the heap changed yet.
The `next` stack variable only saves access to the rest of the list.
Without this temporary pointer, Node 2 and Node 3 could be lost after the next operation.
---
## Step 2 — Reverse `current->next`
Now the algorithm changes the link:
```cpp
current->next = previous;
```
`current` is Node 1.
`previous` is `nullptr`.
So Node 1 no longer points to Node 2.
It now points to `nullptr`.
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | nullptr |
| current | 0x1000 |
| next | 0x2000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=3000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
### Logical view
```text
current
|
v
1 -> null
next
|
v
2 -> 3 -> null
```
This is the key mutation.
The original list is now split into two logical parts:
```text
Reversed part:
1 -> null
Remaining original part:
2 -> 3 -> null
```
---
## Step 3 — Move `previous`
The algorithm advances the reversed part:
```cpp
previous = current;
```
`previous` now points to Node 1.
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x1000 |
| current | 0x1000 |
| next | 0x2000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=3000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
### Logical view
```text
previous/current
|
v
1 -> null
next
|
v
2 -> 3 -> null
```
The reversed part now officially starts at `previous`.
---
## Step 4 — Move `current`
The algorithm continues with the saved next node:
```cpp
current = next;
```
`current` now points to Node 2.
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x1000 |
| current | 0x2000 |
| next | 0x2000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=3000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
### Logical view
```text
previous
|
v
1 -> null
current
|
v
2 -> 3 -> null
```
The first iteration is complete.
---
## Step 5 — Second Iteration: Save `next`
The loop repeats.
```cpp
Node* next = current->next;
```
`current` points to Node 2.
Node 2 points to Node 3.
So:
```text
next = 0x3000
```
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x1000 |
| current | 0x2000 |
| next | 0x3000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=3000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
Again, the heap has not changed yet.
---
## Step 6 — Second Iteration: Reverse Link
```cpp
current->next = previous;
```
`current` is Node 2.
`previous` is Node 1.
So Node 2 now points back to Node 1.
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x1000 |
| current | 0x2000 |
| next | 0x3000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=1000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
### Logical view
```text
current
|
v
2 -> 1 -> null
next
|
v
3 -> null
```
The reversed part will become:
```text
2 -> 1 -> null
```
after `previous` moves to Node 2.
---
## Step 7 — Second Iteration: Move Pointers
```cpp
previous = current;
current = next;
```
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x2000 |
| current | 0x3000 |
| next | 0x3000 |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=1000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
### Logical view
```text
previous
|
v
2 -> 1 -> null
current
|
v
3 -> null
```
Now two nodes are reversed.
---
## Step 8 — Third Iteration: Save `next`
```cpp
Node* next = current->next;
```
`current` is Node 3.
Node 3 points to `nullptr`.
So:
```text
next = nullptr
```
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x2000 |
| current | 0x3000 |
| next | nullptr |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=1000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=null |
+-----------+-----------+
```
---
## Step 9 — Third Iteration: Reverse Link
```cpp
current->next = previous;
```
`current` is Node 3.
`previous` is Node 2.
So Node 3 now points to Node 2.
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x2000 |
| current | 0x3000 |
| next | nullptr |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=1000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=2000 |
+-----------+-----------+
```
### Logical view
```text
current
|
v
3 -> 2 -> 1 -> null
```
The whole list is now reversed, but the loop still needs to update the stack pointers.
---
## Step 10 — Third Iteration: Move Pointers
```cpp
previous = current;
current = next;
```
Since `next` is `nullptr`, `current` becomes `nullptr`.
### Stack
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| head | 0x1000 |
| previous | 0x3000 |
| current | nullptr |
| next | nullptr |
+----------+----------+
```
### Heap
```text
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=1000 |
+-----------+-----------+
0x3000
+-----------+-----------+
| value = 3 | next=2000 |
+-----------+-----------+
```
### Logical view
```text
previous
|
v
3 -> 2 -> 1 -> null
current -> null
```
The loop condition fails:
```cpp
while(current != nullptr)
```
because `current` is now `nullptr`.
---
## Step 11 — Return New Head
At the end:
```cpp
return previous;
```
`previous` points to Node 3.
Node 3 is the new head of the reversed list.
### Final stack view
```text
+----------+----------+
| Variable | Value |
+----------+----------+
| old head | 0x1000 |
| new head | 0x3000 |
+----------+----------+
```
### Final heap view
```text
0x3000
+-----------+-----------+
| value = 3 | next=2000 |
+-----------+-----------+
0x2000
+-----------+-----------+
| value = 2 | next=1000 |
+-----------+-----------+
0x1000
+-----------+-----------+
| value = 1 | next=null |
+-----------+-----------+
```
### Final logical view
```text
new head
|
v
3 -> 2 -> 1 -> null
```
---
## Why the Temporary `next` Pointer Matters
This line is not optional:
```cpp
Node* next = current->next;
```
Without it, this operation:
```cpp
current->next = previous;
```
would overwrite the only pointer to the remaining original list.
For example, at the beginning:
```text
1 -> 2 -> 3 -> null
```
If Node 1 is changed to:
```text
1 -> null
```
before saving Node 2, then Node 2 and Node 3 are no longer reachable from any local variable.
That is why the algorithm always follows this order:
```cpp
Node* next = current->next; // preserve the remaining list
current->next = previous; // reverse the link
previous = current; // grow the reversed part
current = next; // continue with the remaining part
```
The order is the algorithm.
---
## Summary
During the algorithm:
- `previous` points to the already reversed part.
- `current` points to the node being processed.
- `next` preserves access to the not-yet-processed part.
- Only one `next` field is modified per iteration.
- No nodes are copied.
- No new list is allocated.
- The original nodes are relinked in-place.
The algorithm is small, but it is easy to get wrong because it mutates the structure while traversing it.
That is why a memory-level walkthrough is often more useful than just showing the final code.

View File

@@ -1,5 +0,0 @@
Original list:
1 -> 2 -> 3 -> 4 -> 5 -> null
Reversed list:
5 -> 4 -> 3 -> 2 -> 1 -> null

View File

@@ -1,7 +0,0 @@
TEMPLATE = app
CONFIG += console c++17
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += \
main.cpp