Linked Structures
Reverse a Linked List
Reverse a singly linked list by flipping every next_idx pointer.
A recursive walk visits each node once and records its predecessor;
the head becomes the original tail.
Algorithm
Canonical input 1 -> 2 -> 3 -> 4 -> 5 reverses to
5 -> 4 -> 3 -> 2 -> 1 -> null.
pointer flip
For each node, set its new `next` to the node that arrived just before it in the original walk. The original head's new `next` is `null`.
head swap
After every node is flipped, the original tail is the new head.
Visual walkthrough
Basic Implementation
basic.sql
.mode list
.headers off
CREATE TABLE node(idx INTEGER PRIMARY KEY, val INTEGER, next_idx INTEGER);
INSERT INTO node(idx, val, next_idx) VALUES
(0, 1, 1),
(1, 2, 2),
(2, 3, 3),
(3, 4, 4),
(4, 5, NULL);
CREATE TABLE reversed(idx INTEGER PRIMARY KEY, val INTEGER, next_idx INTEGER);
WITH RECURSIVE flip(cur, prev) AS (
SELECT 0, NULL
UNION ALL
SELECT (SELECT next_idx FROM node WHERE idx = flip.cur), flip.cur
FROM flip
WHERE flip.cur IS NOT NULL
)
INSERT INTO reversed(idx, val, next_idx)
SELECT n.idx, n.val, flip.prev
FROM node n JOIN flip ON flip.cur = n.idx;
WITH RECURSIVE head(idx) AS (
SELECT idx FROM reversed WHERE idx NOT IN (
SELECT next_idx FROM reversed WHERE next_idx IS NOT NULL
)
),
walk(idx, line) AS (
SELECT reversed.idx, CAST(reversed.val AS TEXT) || ' -> '
FROM reversed JOIN head ON head.idx = reversed.idx
UNION ALL
SELECT reversed.idx, walk.line || CAST(reversed.val AS TEXT) || ' -> '
FROM walk JOIN reversed
ON reversed.idx = (SELECT next_idx FROM reversed WHERE idx = walk.idx)
WHERE (SELECT next_idx FROM reversed WHERE idx = walk.idx) IS NOT NULL
)
SELECT line || 'null' FROM walk
ORDER BY LENGTH(line) DESC LIMIT 1;
Complexity
- Time: O(n)
- Space: O(n) for the
reversedtable holding the rewritten pointers
Implementation notes
- SQL: the input list is staged in
node(idx, val, next_idx)with the original ordering. AWITH RECURSIVE flip(cur, prev)CTE walks forward throughnext_idx, producing one row per node that pairs the node's own index with the index that came before it. - The
INSERT INTO reversedprojection joins eachnodeto itsfliprow so the newnext_idxis the original predecessor — exactly what aprev/curr/nextimperative loop would write back. The original head'sprevisNULL, so its reversednext_idxis the null sentinel. - The printing walk finds the new head as the index that is no
row's
next_idxinreversed, then chains forward through the reversed pointers to produce5 -> 4 -> 3 -> 2 -> 1 -> null.