Files
codetutor/frontend/src/content/algorithms/linkedlist-reversal.ts
T

516 lines
17 KiB
TypeScript

import type { AlgorithmDefinition } from '@/lib/visualizations/types';
export const linkedListReversalAlgorithm: AlgorithmDefinition = {
id: 'linkedlist-reversal',
title: 'Reverse a Linked List',
slug: 'linkedlist-reversal',
pattern: {
name: 'LinkedList Reversal',
description: 'Reverse links between nodes using three pointers',
},
problemStatement:
'Given a singly linked list, reverse it in-place and return the new head.',
intuition:
'Use three pointers (prev, curr, next) to reverse each link. Save next before breaking the link, then move forward.',
code: {
language: 'python',
code: `def reverse_list(head):
prev = None
curr = head
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
return prev`,
},
steps: [
// Problem phase
{
id: 'step-1',
phase: 'problem',
explanation: 'We have a linked list: 1 → 2 → 3 → 4 → null. Reverse it to get 4 → 3 → 2 → 1 → null.',
dataState: {
arrays: [],
pointers: [],
variables: [],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'normal' },
{ id: 'n2', value: 2, index: 1, state: 'normal' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [],
},
},
// Intuition phase
{
id: 'step-2',
phase: 'intuition',
explanation:
'Key insight: We need to reverse each arrow. To do this safely, save the next node before changing the link.',
dataState: {
arrays: [],
pointers: [],
variables: [],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'highlighted' },
{ id: 'n2', value: 2, index: 1, state: 'comparing' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [],
},
},
// Code phase - initialization
{
id: 'step-3',
phase: 'code',
explanation: 'Initialize prev = None (nothing before head yet) and curr = head.',
codeLine: 2,
codeHighlightLines: [2, 3],
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'None' },
{ id: 'curr', name: 'curr', value: 'node 1' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'highlighted' },
{ id: 'n2', value: 2, index: 1, state: 'normal' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'curr', name: 'curr', nodeIndex: 0, color: 'curr' },
],
},
},
// Execution - iteration 1
{
id: 'step-4',
phase: 'execution',
explanation: 'Check: curr (node 1) exists. Enter the while loop.',
codeLine: 5,
decision: {
question: 'Is curr not None?',
answer: 'Yes, curr is node 1',
action: 'Enter the while loop',
},
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'None' },
{ id: 'curr', name: 'curr', value: 'node 1' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'highlighted' },
{ id: 'n2', value: 2, index: 1, state: 'normal' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'curr', name: 'curr', nodeIndex: 0, color: 'curr' },
],
},
},
{
id: 'step-5',
phase: 'execution',
explanation: 'Save next_node = curr.next (node 2). This preserves our forward reference.',
codeLine: 6,
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'None' },
{ id: 'curr', name: 'curr', value: 'node 1' },
{ id: 'next', name: 'next', value: 'node 2' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'highlighted' },
{ id: 'n2', value: 2, index: 1, state: 'comparing' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'curr', name: 'curr', nodeIndex: 0, color: 'curr' },
{ id: 'next', name: 'next', nodeIndex: 1, color: 'next' },
],
},
},
{
id: 'step-6',
phase: 'execution',
explanation: 'Reverse the link: curr.next = prev. Node 1 now points to None (backwards!).',
codeLine: 7,
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'None' },
{ id: 'curr', name: 'curr', value: 'node 1' },
{ id: 'next', name: 'next', value: 'node 2' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'comparing' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'curr', name: 'curr', nodeIndex: 0, color: 'curr' },
{ id: 'next', name: 'next', nodeIndex: 1, color: 'next' },
],
},
},
{
id: 'step-7',
phase: 'execution',
explanation: 'Move prev forward: prev = curr. Now prev points to node 1.',
codeLine: 8,
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 1', previousValue: 'None' },
{ id: 'curr', name: 'curr', value: 'node 1' },
{ id: 'next', name: 'next', value: 'node 2' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'comparing' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 0, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 0, color: 'curr' },
{ id: 'next', name: 'next', nodeIndex: 1, color: 'next' },
],
},
},
{
id: 'step-8',
phase: 'execution',
explanation: 'Move curr forward: curr = next_node. Now curr points to node 2.',
codeLine: 9,
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 1' },
{ id: 'curr', name: 'curr', value: 'node 2', previousValue: 'node 1' },
{ id: 'next', name: 'next', value: 'node 2' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'highlighted' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 0, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 1, color: 'curr' },
],
},
},
// Iteration 2
{
id: 'step-9',
phase: 'execution',
explanation: 'Check: curr (node 2) exists. Continue loop.',
codeLine: 5,
decision: {
question: 'Is curr not None?',
answer: 'Yes, curr is node 2',
action: 'Continue the while loop',
},
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 1' },
{ id: 'curr', name: 'curr', value: 'node 2' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'highlighted' },
{ id: 'n3', value: 3, index: 2, state: 'normal' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 0, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 1, color: 'curr' },
],
},
},
{
id: 'step-10',
phase: 'execution',
explanation: 'Save next_node = curr.next (node 3).',
codeLine: 6,
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 1' },
{ id: 'curr', name: 'curr', value: 'node 2' },
{ id: 'next', name: 'next', value: 'node 3' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'highlighted' },
{ id: 'n3', value: 3, index: 2, state: 'comparing' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 0, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 1, color: 'curr' },
{ id: 'next', name: 'next', nodeIndex: 2, color: 'next' },
],
},
},
{
id: 'step-11',
phase: 'execution',
explanation: 'Reverse the link: curr.next = prev. Node 2 now points to node 1.',
codeLine: 7,
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 1' },
{ id: 'curr', name: 'curr', value: 'node 2' },
{ id: 'next', name: 'next', value: 'node 3' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'success' },
{ id: 'n3', value: 3, index: 2, state: 'comparing' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 0, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 1, color: 'curr' },
{ id: 'next', name: 'next', nodeIndex: 2, color: 'next' },
],
},
},
{
id: 'step-12',
phase: 'execution',
explanation: 'Move prev = curr, curr = next_node. Advance to process node 3.',
codeLine: 8,
codeHighlightLines: [8, 9],
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 2', previousValue: 'node 1' },
{ id: 'curr', name: 'curr', value: 'node 3', previousValue: 'node 2' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'success' },
{ id: 'n3', value: 3, index: 2, state: 'highlighted' },
{ id: 'n4', value: 4, index: 3, state: 'normal' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 1, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 2, color: 'curr' },
],
},
},
// Iteration 3 (condensed)
{
id: 'step-13',
phase: 'execution',
explanation: 'Process node 3: save next (node 4), reverse link (3→2), advance pointers.',
codeLine: 6,
codeHighlightLines: [6, 7, 8, 9],
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 3', previousValue: 'node 2' },
{ id: 'curr', name: 'curr', value: 'node 4', previousValue: 'node 3' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'success' },
{ id: 'n3', value: 3, index: 2, state: 'success' },
{ id: 'n4', value: 4, index: 3, state: 'highlighted' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 2, color: 'prev' },
{ id: 'curr', name: 'curr', nodeIndex: 3, color: 'curr' },
],
},
},
// Iteration 4 (last node)
{
id: 'step-14',
phase: 'execution',
explanation: 'Process node 4: save next (null), reverse link (4→3), advance pointers.',
codeLine: 6,
codeHighlightLines: [6, 7, 8, 9],
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 4', previousValue: 'node 3' },
{ id: 'curr', name: 'curr', value: 'None', previousValue: 'node 4' },
],
calculations: [],
linkedLists: [
{
id: 'list',
nodes: [
{ id: 'n1', value: 1, index: 0, state: 'success' },
{ id: 'n2', value: 2, index: 1, state: 'success' },
{ id: 'n3', value: 3, index: 2, state: 'success' },
{ id: 'n4', value: 4, index: 3, state: 'success' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [
{ id: 'prev', name: 'prev', nodeIndex: 3, color: 'prev' },
],
},
},
// Exit and return
{
id: 'step-15',
phase: 'execution',
explanation: 'Check: curr is None. Exit loop. Return prev (node 4), the new head!',
codeLine: 11,
decision: {
question: 'Is curr not None?',
answer: 'No, curr is None',
action: 'Exit loop, return prev',
},
dataState: {
arrays: [],
pointers: [],
variables: [
{ id: 'prev', name: 'prev', value: 'node 4' },
{ id: 'curr', name: 'curr', value: 'None' },
{ id: 'result', name: 'result', value: 'node 4 (new head)' },
],
calculations: [],
linkedLists: [
{
id: 'list',
label: 'Reversed: 4 → 3 → 2 → 1 → null',
nodes: [
{ id: 'n4', value: 4, index: 0, state: 'success' },
{ id: 'n3', value: 3, index: 1, state: 'success' },
{ id: 'n2', value: 2, index: 2, state: 'success' },
{ id: 'n1', value: 1, index: 3, state: 'success' },
{ id: 'null', value: 0, index: 4, state: 'normal', isNull: true },
],
},
],
linkedListPointers: [],
},
},
],
};