01 / Reading Guide
Reading Guide
Citation
Wengrow, J. (2020). A Common-Sense Guide to Data Structures and Algorithms: Level Up Your Core Programming Skills (2nd ed.). The Pragmatic Bookshelf.
Chapter Summary
The second edition has 506 pages in twenty chapters, each ending with "Wrapping Up" and a set of exercises, followed by an appendix of exercise solutions for every chapter. The preface covers who the book is for, what is new in this edition, how to read it, the code examples and the online resources; the publisher offers the source code as a download. Code examples appear in JavaScript, Python and Ruby. The publisher says the second edition adds exercises to every chapter and new chapters on recursion, dynamic programming, using Big O in everyday code, and heaps and tries.
Chapters 1–3: Why Data Structures Matter; Why Algorithms Matter; O Yes! Big O Notation
The book's method is set out in Chapter 1, available as a free extract: the speed of an operation is measured not in time but in the number of steps it takes. The chapter counts the steps of reading, searching, inserting and deleting in an array, then compares the array with a set, where one rule (no duplicates) changes the cost of insertion. Chapter 2 introduces ordered arrays and compares binary with linear search; Chapter 3 turns step counting into Big O notation, including logarithms and O(log N).
Chapters 4–6: Speeding Up Your Code with Big O; Optimizing Code with and Without Big O; Optimizing for Optimistic Scenarios
Three chapters use the simple sorts to deepen the analysis. Bubble sort (a free extract) shows a quadratic algorithm and how to replace a quadratic solution with a linear one; selection sort shows why Big O ignores constants yet two algorithms in the same category can still differ; insertion sort introduces best, worst and average cases.
Chapter 7: Big O in Everyday Code
A new chapter, also available as an extract, that applies the analysis to short practical functions: averaging even numbers, building words, sampling an array, labelling clothing, checking palindromes, listing products and cracking passwords. The opening explains that determining the current Big O is the first step in optimizing code.
Chapters 8–9: Blazing Fast Lookup with Hash Tables; Crafting Elegant Code with Stacks and Queues
Hash tables are covered through hash functions, collisions and what makes a hash table efficient, with uses for both organizing data and speeding up code. Stacks and queues are presented as constrained data structures and abstract data types.
Chapters 10–13: Recursively Recurse with Recursion; Learning to Write in Recursive; Dynamic Programming; Recursive Algorithms for Speed
The recursion block moves from reading recursive code and the base case, through categories of recursive problems and top-down thinking (the staircase problem, anagram generation), to dynamic programming by memoization and by working bottom-up. Chapter 13 applies recursion to partitioning, quicksort and its worst case, and quickselect, and notes how sorting can be a key to other algorithms.
Chapters 14–17: Node-Based Data Structures; Speeding Up All the Things with Binary Search Trees; Keeping Your Priorities Straight with Heaps; It Doesn't Hurt to Trie
Linked and doubly linked lists (including queues built from them), binary search trees with insertion, deletion and traversal, heaps as priority queues (including storing a heap in an array and the "last node" problem), and tries used to build autocomplete.
Chapter 18: Connecting Everything with Graphs
Directed graphs, an object-oriented implementation, depth-first and breadth-first search and their efficiency, weighted graphs and Dijkstra's algorithm.
Chapters 19–20: Dealing with Space Constraints; Techniques for Code Optimization
Chapter 19 extends Big O to memory, discusses time–space trade-offs and the hidden space cost of recursion. Chapter 20 gathers practical optimization strategies: start from the current Big O, imagine the best possible Big O, look for "magical lookups", recognize patterns, use greedy algorithms and change the data structure.
Key Concepts
Chapters 1–7: Measuring efficiency
- Steps, not seconds: an operation's speed is the number of steps it takes, which does not depend on hardware.
- Big O notation: how the number of steps grows relative to N data elements, ignoring constants.
- Best, worst and average case: why the same algorithm can behave differently on different inputs.
- Binary search: halving an ordered array at each step, the source of O(log N).
Chapters 8–13: Lookup, constraints and recursion
- Hash tables: key-based lookup through a hash function, with collisions handled to keep lookups fast.
- Abstract data types: stacks and queues defined by the operations they allow.
- Recursion and the base case: solving a problem in terms of smaller instances of itself.
- Memoization and bottom-up dynamic programming: eliminating repeated recursive calls on overlapping subproblems.
Chapters 14–18: Node-based structures
- Linked lists: nodes connected by links, with different costs for reading and insertion than arrays.
- Binary search trees and heaps: trees ordered for fast search, or for fast access to the highest-priority element.
- Graph search and Dijkstra's algorithm: depth-first and breadth-first traversal and shortest paths in weighted graphs.
Chapters 19–20: Space and optimization
- Space complexity: Big O applied to memory, including the call stack used by recursion.
- Optimization techniques: deliberate strategies for finding a faster algorithm.
Critical Analysis
Strengths
- A single, concrete idea of efficiency. The free first chapter shows the approach: every claim about speed is reduced to counting steps on small examples before any notation appears, so the reader builds Big O from experience rather than from a definition.
- Analysis of ordinary code. Chapter 7 analyses short functions of the kind found in real codebases, and Chapter 20 turns analysis into a set of optimization habits, so the theory is tied to code a working programmer writes.
- Exercises with full solutions. Every chapter ends with exercises, and the appendix gives solutions for all twenty chapters, which makes the book workable for self-study.
- Multi-language examples. Examples in JavaScript, Python and Ruby keep the code accessible to working web developers; the publisher lists no prerequisites beyond programming.
Limitations
- Informal analysis. Big O is introduced through step counting; the table of contents shows no formal definitions, proofs of correctness or recurrence solving, so students heading into a theory course will need a more rigorous text.
- Selective coverage. Merge sort, balanced search trees, minimum spanning trees and other standard algorithms do not appear in the section headings; the book covers the core structures but not a full course syllabus.
- Dynamically typed examples only. The code is in JavaScript, Python and Ruby; students whose course uses Java or C++ must translate the implementations themselves.
Where It Fits in the Course
Within the course this is a gentle first book, alongside Bhargava's Grokking Algorithms. Both suit readers who program but have no computer science background; Wengrow spends more time on step counting and on analysing everyday code and includes exercises with solutions, while Bhargava relies more on illustrations and also covers topics such as greedy and approximation algorithms. Either can come first; reading both is reasonable for a reader who wants a second explanation of the same core ideas.
After this book the course moves to full textbooks. Goodrich, Tamassia and Goldwasser's Data Structures and Algorithms in Java and Pat Morin's free Open Data Structures treat the same structures with implementations, formal analysis and proofs, and are the natural next step for a university course. Peter Brass's Advanced Data Structures and Chris Okasaki's Purely Functional Data Structures are specialist monographs for much later.
How to Use This Book
The book is aimed at programmers who want to understand data structures and algorithms for daily work, including self-taught and bootcamp-trained developers and students taking a first data structures course. It assumes basic programming in any language and only school arithmetic; logarithms are explained in Chapter 3.
A practical plan:
- Core, in order: Chapters 1–9. The book builds its analysis cumulatively, and Chapter 7's analysis of real code is worth doing carefully.
- Recursion block: Chapters 10–13 as a unit; Chapter 12 on dynamic programming depends on the two before it.
- Data structures: Chapters 14–18. Heaps and tries (Chapters 16–17) can be skipped on a first pass if time is short; graphs (Chapter 18) should not be.
- Synthesis: Chapters 19–20 close the book and suit a review before technical interviews or a course exam.
Do each chapter's exercises before reading the solutions, and type out and run the downloadable code in the language you use most, timing a slow and a fast version of the same task to see the step counts in practice. If you are taking a university course, read the matching chapter of a formal textbook after each block here, and use this book's explanations when the formal treatment becomes hard to follow.
