Addison Wesley, 1973,1968
This is Volume I of Knuth's series on The Art of Computer Programming.
The book walks through the basics of data structures and computational number theory. Topics covered include stacks, queues, linked lists, doubly linked lists, trees, etc.
These are basics that every programmer needs to know.
The other books in this series include: Sorting and Searching and Seminumerical Algorithms. Each is fascinating in it's own regard and ought to be part of the repertoire of knowledge that every programmer is familiar with.
Academic Press, 1972
This is the book in which Dijkstra told us that
goto might not be such a good idea. This is also the book in which Ole-Johan Dahl described the early principles of Object-Oriented Programming. There is much wealth within these pages that all who aspire to Software Craftsmanship should be familiar with.
Structured Analysis and System Specification
Yourdon Press, 1979, 1978
This is a classic of early software system design. DeMarco describes the top-down approach of functional decomposition and introduces the use of Data Flow Diagrams and Data Dictionaries to specify that decomposition.
The book is very approachable, and full of deep insights. Every programmer ought to be familiar with it.
Structure and Interpretation of Computer Programs (SICP)
This book was life changing. Or at least it was career modifying. It was my first introduction to functional programming; though neither the title, nor the first two chapters mentioned the term.
The book is completely unapologetic in it's approach, giving no quarter to those who want an easy ride. It moves at light speed from one topic to the next, demonstrating concept after concept with clear, concise, and plentiful code.
The language of the book is
Scheme; but the reader barely notices because the language is so lightweight, and because the topics are so intense.
I read this book with a kind of ecstatic energy – virtually throwing the pages from one to the next in my enthusiasm. And then at page 217 the authors slammed on the brakes, apologized profusely for what they were about to do to me, and then introduced the first assignment statement.
I was thunderstruck. While reading all the previous code I had not realized that they had not used assignment. I had to go back and check.
It was then – quite late in my career – that I realized that Functional Programming was important for me to learn.