├── .gitignore
├── LICENSE
├── README.md
├── book
├── Makefile
├── book.tex
├── figs
│ ├── 200px-Binary_search_tree-svg.png
│ ├── Binary_search_tree_1229.png
│ ├── DOMinspector.png
│ ├── DOMtree01.png
│ ├── bst.odg
│ ├── bst.pdf
│ ├── dom_tree1.odg
│ ├── dom_tree1.pdf
│ ├── figure01small.png
│ ├── figure02.png
│ ├── figure02small.png
│ ├── figure03.png
│ ├── figure03small.png
│ ├── figure04.png
│ ├── figure04small.png
│ ├── figure1.png
│ ├── figure2.png
│ ├── figure3.png
│ ├── hashtable.png
│ ├── index.odg
│ ├── index.pdf
│ ├── linked_list1.odg
│ ├── linked_list1.pdf
│ ├── linked_list_diagram1.png
│ ├── merge_sort1.odg
│ ├── merge_sort1.pdf
│ ├── merge_sort2.odg
│ ├── merge_sort2.pdf
│ ├── profile1.png
│ ├── profile2.png
│ ├── profile3.png
│ ├── profile4.png
│ ├── radix_sort1.odg
│ ├── radix_sort1.pdf
│ ├── tower.odg
│ ├── tower.pdf
│ ├── towers.pdf
│ ├── yuml1.pdf
│ ├── yuml1.png
│ └── yuml2.pdf
├── footer.html
└── header.html
├── code
├── build.xml
├── lib
│ ├── ant-junit.jar
│ ├── commons-math3-3.6.jar
│ ├── hamcrest-core-1.3.jar
│ ├── hamcrest-library-1.3.jar
│ ├── jcommon-1.0.23.jar
│ ├── jedis-2.8.0.jar
│ ├── jfreechart-1.0.19.jar
│ ├── jsoup-1.8.3.jar
│ ├── junit-4.12.jar
│ └── servlet.jar
└── src
│ └── com
│ └── allendowney
│ └── thinkdast
│ ├── Card.java
│ ├── HelloJsoup.java
│ ├── Index.java
│ ├── IndexTest.java
│ ├── JedisIndex.java
│ ├── JedisIndexTest.java
│ ├── JedisMaker.java
│ ├── JedisTermCounter.java
│ ├── JedisTermCounterTest.java
│ ├── LinkedListExample.java
│ ├── ListClientExample.java
│ ├── ListClientExampleTest.java
│ ├── ListLinks.java
│ ├── ListNode.java
│ ├── ListSorter.java
│ ├── ListSorterTest.java
│ ├── MyArrayList.java
│ ├── MyArrayListTest.java
│ ├── MyBetterMap.java
│ ├── MyBetterMapTest.java
│ ├── MyFixedHashMap.java
│ ├── MyFixedHashMapTest.java
│ ├── MyHashMap.java
│ ├── MyHashMapTest.java
│ ├── MyLinearMap.java
│ ├── MyLinearMapTest.java
│ ├── MyLinkedList.java
│ ├── MyLinkedListTest.java
│ ├── MyTreeMap.java
│ ├── MyTreeMapExample.java
│ ├── MyTreeMapTest.java
│ ├── Page.java
│ ├── ProfileListAdd.java
│ ├── ProfileMapPut.java
│ ├── Profiler.java
│ ├── SelectionSort.java
│ ├── SillyArray.java
│ ├── SillyString.java
│ ├── TermCounter.java
│ ├── TermCounterTest.java
│ ├── WikiCrawler.java
│ ├── WikiCrawlerTest.java
│ ├── WikiFetcher.java
│ ├── WikiNodeExample.java
│ ├── WikiNodeIterable.java
│ ├── WikiParser.java
│ ├── WikiParserTest.java
│ ├── WikiPhilosophy.java
│ ├── WikiPhilosophyTest.java
│ ├── WikiSearch.java
│ └── WikiSearchTest.java
└── solutions
├── build.xml
├── lib
├── ant-junit.jar
├── commons-math3-3.6.jar
├── hamcrest-core-1.3.jar
├── hamcrest-library-1.3.jar
├── jcommon-1.0.23.jar
├── jedis-2.8.0.jar
├── jfreechart-1.0.19.jar
├── jsoup-1.8.3.jar
├── junit-4.12.jar
└── servlet.jar
└── src
├── com
└── allendowney
│ └── thinkdast
│ ├── Card.java
│ ├── HelloJsoup.java
│ ├── Index.java
│ ├── IndexTest.java
│ ├── JedisIndex.java
│ ├── JedisIndexTest.java
│ ├── JedisMaker.java
│ ├── JedisTermCounter.java
│ ├── JedisTermCounterTest.java
│ ├── LinkedListExample.java
│ ├── ListClientExample.java
│ ├── ListClientExampleTest.java
│ ├── ListLinks.java
│ ├── ListNode.java
│ ├── ListSorter.java
│ ├── ListSorterTest.java
│ ├── MyArrayList.java
│ ├── MyArrayListTest.java
│ ├── MyBetterMap.java
│ ├── MyBetterMapTest.java
│ ├── MyFixedHashMap.java
│ ├── MyFixedHashMapTest.java
│ ├── MyHashMap.java
│ ├── MyHashMapTest.java
│ ├── MyLinearMap.java
│ ├── MyLinearMapTest.java
│ ├── MyLinkedList.java
│ ├── MyLinkedListTest.java
│ ├── MyTreeMap.java
│ ├── MyTreeMapExample.java
│ ├── MyTreeMapTest.java
│ ├── Page.java
│ ├── ProfileListAdd.java
│ ├── ProfileMapPut.java
│ ├── Profiler.java
│ ├── SelectionSort.java
│ ├── SillyArray.java
│ ├── SillyString.java
│ ├── TermCounter.java
│ ├── TermCounterTest.java
│ ├── WikiCrawler.java
│ ├── WikiCrawlerTest.java
│ ├── WikiFetcher.java
│ ├── WikiNodeExample.java
│ ├── WikiNodeIterable.java
│ ├── WikiParser.java
│ ├── WikiParserTest.java
│ ├── WikiPhilosophy.java
│ ├── WikiPhilosophyTest.java
│ ├── WikiSearch.java
│ └── WikiSearchTest.java
└── resources
└── en.wikipedia.org
└── wiki
├── Awareness
├── Computer_science
├── Concurrent_computing
├── Consciousness
├── Java_(Programming_Language)
├── Java_(programming_language)
├── Knowledge
├── Mathematics
├── Modern_philosophy
├── Philosophy
├── Programming_language
├── Property_(philosophy)
├── Quality_(philosophy)
└── Science
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Allen Downey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ThinkDataStructures
2 |
3 | LaTeX source and supporting code for *Think Data Structures: Algorithms and Information Retrieval in Java*
4 |
5 |
6 | Data structures and algorithms are among the most important inventions
7 | of the last 50 years, and they are fundamental tools
8 | software engineers need to know. But in my opinion, most of the books
9 | on these topics are too theoretical, too big, and too bottom-up:
10 |
11 | * Too theoretical: Mathematical analysis of algorithms is based
12 | on simplifying assumptions that limit its usefulness in practice.
13 | Many presentations of this topic gloss over the simplifications and
14 | focus on the math. In this book I present the most practical subset
15 | of this material and eliminate the rest.
16 |
17 | * Too big: Most books on these topics are at least 500 pages,
18 | and some are more than 1000. By focusing on the topics I think are
19 | most useful for software engineers, I kept this book under
20 | 250 pages.
21 |
22 | * Too bottom-up: Many data structures books focus on how data
23 | structures work (the implementations), with less about how to use
24 | them (the interfaces). In this book, I go ``top down'', starting
25 | with the interfaces. Readers learn to use the structures in the
26 | Java Collections Framework before getting into the details of how
27 | they work.
28 |
29 | Finally, many present this material out of context and without
30 | motivation: it's just one damn data structure after another!
31 |
32 | I try to alleviate the boredom by organizing the topics around an
33 | application -- web search -- that uses data structures extensively,
34 | and is an interesting and important topic in its own right.
35 |
36 | This application also motivates some topics that are not usually
37 | covered in an introductory data structures class, including persistent
38 | data structures, with Redis, and streaming algorithms.
39 |
40 | I have made difficult decisions about what to leave out, but
41 | I have made some compromises. I include a few topics
42 | that most readers will never use, but that they might be expected to
43 | know, possibly in a technical interview. For these topics, I
44 | present both the conventional wisdom as well as my reasons to be
45 | skeptical.
46 |
47 | This book also presents basic aspects of software engineering practice,
48 | including version control and unit testing. Each chapter ends with
49 | an exercise that allows readers to apply what they have learned.
50 | Each exercise includes automated tests that check the solution.
51 | And for most exercises, I present my solution at the beginning of
52 | the next chapter.
53 |
54 | This book is intended for college students in computer science and related
55 | fields, as well as professional software engineers, people training in
56 | software engineering, and people preparing for technical interviews.
57 |
58 | I assume that the reader knows Java at an intermediate level,
59 | but I explain some Java features along the way, and provide pointers
60 | to supplementary material.
61 |
62 | People who have read *Think Java* or *Head First
63 | Java* are prepared for this book.
64 |
--------------------------------------------------------------------------------
/book/Makefile:
--------------------------------------------------------------------------------
1 | F = thinkdast
2 |
3 | all:
4 | pdflatex book
5 | makeindex book.idx # shouldn't need .idx here, but we do
6 | pdflatex book
7 | evince book.pdf
8 |
9 | hevea: book.tex header.html footer.html
10 | cp book.tex $(F).tex
11 | rm -rf html
12 | mkdir html
13 | hevea -O -exec xxdate.exe -e latexonly htmlonly $(F).tex
14 | imagen -png -pdf $(F)
15 | hacha $(F).html
16 | cp up.png next.png back.png html
17 | # TODO: might have to bring back $(F).png
18 | mv -i index.html $(F).css $(F)*.html html
19 | rm *motif.gif
20 |
21 | plastex:
22 | # Before running plastex, we need the current directory in PYTHONPATH
23 | # export PYTHONPATH=$PYTHONPATH:.
24 | python preprocess.py book.tex > $(F).plastex
25 | plastex --renderer=DocBook --theme=book --image-resolution=300 --filename=$(F).xml $(F).plastex
26 | cd $(F); python ../postprocess.py $(F).xml > temp; mv temp $(F).xml
27 |
28 | xxe:
29 | xmlcopyeditor ~/ThinkDataStructures/$(F)/$(F).xml &
30 |
31 | lint:
32 | xmllint -noout $(F)/$(F).xml
33 |
34 | oreilly:
35 | rsync -a $(F)/$(F).xml atlas
36 | rsync -a figs/*.pdf atlas/figs/
37 | rsync -a figs/*.png atlas/figs/
38 | cd atlas; git add $(F).xml figs/*
39 | cd atlas; git commit -m "Automated check in."
40 | cd atlas; git push
41 |
42 | DEST = /home/downey/public_html/greent/$(F)
43 |
44 | distrib:
45 | rm -rf dist
46 | mkdir dist
47 | cp book.pdf $(F).pdf
48 | rsync -a $(F).pdf html dist
49 | rsync -a dist/* $(DEST)
50 | chmod -R o+r $(DEST)/*
51 | cd $(DEST)/..; sh back
52 |
--------------------------------------------------------------------------------
/book/figs/200px-Binary_search_tree-svg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/200px-Binary_search_tree-svg.png
--------------------------------------------------------------------------------
/book/figs/Binary_search_tree_1229.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/Binary_search_tree_1229.png
--------------------------------------------------------------------------------
/book/figs/DOMinspector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/DOMinspector.png
--------------------------------------------------------------------------------
/book/figs/DOMtree01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/DOMtree01.png
--------------------------------------------------------------------------------
/book/figs/bst.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/bst.odg
--------------------------------------------------------------------------------
/book/figs/bst.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/bst.pdf
--------------------------------------------------------------------------------
/book/figs/dom_tree1.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/dom_tree1.odg
--------------------------------------------------------------------------------
/book/figs/dom_tree1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/dom_tree1.pdf
--------------------------------------------------------------------------------
/book/figs/figure01small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure01small.png
--------------------------------------------------------------------------------
/book/figs/figure02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure02.png
--------------------------------------------------------------------------------
/book/figs/figure02small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure02small.png
--------------------------------------------------------------------------------
/book/figs/figure03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure03.png
--------------------------------------------------------------------------------
/book/figs/figure03small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure03small.png
--------------------------------------------------------------------------------
/book/figs/figure04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure04.png
--------------------------------------------------------------------------------
/book/figs/figure04small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure04small.png
--------------------------------------------------------------------------------
/book/figs/figure1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure1.png
--------------------------------------------------------------------------------
/book/figs/figure2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure2.png
--------------------------------------------------------------------------------
/book/figs/figure3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/figure3.png
--------------------------------------------------------------------------------
/book/figs/hashtable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/hashtable.png
--------------------------------------------------------------------------------
/book/figs/index.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/index.odg
--------------------------------------------------------------------------------
/book/figs/index.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/index.pdf
--------------------------------------------------------------------------------
/book/figs/linked_list1.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/linked_list1.odg
--------------------------------------------------------------------------------
/book/figs/linked_list1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/linked_list1.pdf
--------------------------------------------------------------------------------
/book/figs/linked_list_diagram1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/linked_list_diagram1.png
--------------------------------------------------------------------------------
/book/figs/merge_sort1.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/merge_sort1.odg
--------------------------------------------------------------------------------
/book/figs/merge_sort1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/merge_sort1.pdf
--------------------------------------------------------------------------------
/book/figs/merge_sort2.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/merge_sort2.odg
--------------------------------------------------------------------------------
/book/figs/merge_sort2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/merge_sort2.pdf
--------------------------------------------------------------------------------
/book/figs/profile1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/profile1.png
--------------------------------------------------------------------------------
/book/figs/profile2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/profile2.png
--------------------------------------------------------------------------------
/book/figs/profile3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/profile3.png
--------------------------------------------------------------------------------
/book/figs/profile4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/profile4.png
--------------------------------------------------------------------------------
/book/figs/radix_sort1.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/radix_sort1.odg
--------------------------------------------------------------------------------
/book/figs/radix_sort1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/radix_sort1.pdf
--------------------------------------------------------------------------------
/book/figs/tower.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/tower.odg
--------------------------------------------------------------------------------
/book/figs/tower.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/tower.pdf
--------------------------------------------------------------------------------
/book/figs/towers.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/towers.pdf
--------------------------------------------------------------------------------
/book/figs/yuml1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/yuml1.pdf
--------------------------------------------------------------------------------
/book/figs/yuml1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/yuml1.png
--------------------------------------------------------------------------------
/book/figs/yuml2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/book/figs/yuml2.pdf
--------------------------------------------------------------------------------
/book/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
This HTML version of Think Data Structures is provided for convenience, but it is not the best format of the book.
11 | In particular, some of the symbols are not rendered correctly.
12 |
13 |
You might prefer to read the PDF version.
14 |
15 |
Or you can buy this book on Amazon.com.
16 |
--------------------------------------------------------------------------------
/code/lib/ant-junit.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/ant-junit.jar
--------------------------------------------------------------------------------
/code/lib/commons-math3-3.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/commons-math3-3.6.jar
--------------------------------------------------------------------------------
/code/lib/hamcrest-core-1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/hamcrest-core-1.3.jar
--------------------------------------------------------------------------------
/code/lib/hamcrest-library-1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/hamcrest-library-1.3.jar
--------------------------------------------------------------------------------
/code/lib/jcommon-1.0.23.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/jcommon-1.0.23.jar
--------------------------------------------------------------------------------
/code/lib/jedis-2.8.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/jedis-2.8.0.jar
--------------------------------------------------------------------------------
/code/lib/jfreechart-1.0.19.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/jfreechart-1.0.19.jar
--------------------------------------------------------------------------------
/code/lib/jsoup-1.8.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/jsoup-1.8.3.jar
--------------------------------------------------------------------------------
/code/lib/junit-4.12.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/junit-4.12.jar
--------------------------------------------------------------------------------
/code/lib/servlet.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AllenDowney/ThinkDataStructures/cc10971a1904eda5f5b818a3d70ee1a836fd8799/code/lib/servlet.jar
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/Card.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.Comparator;
6 | import java.util.List;
7 |
8 |
9 | /**
10 | * Represents a playing card.
11 | *
12 | */
13 | public class Card implements Comparable {
14 |
15 | // string representations of ranks
16 | public static final String[] RANKS = {
17 | null, "Ace", "2", "3", "4", "5", "6", "7",
18 | "8", "9", "10", "Jack", "Queen", "King"};
19 |
20 | // string representations of suits
21 | public static final String[] SUITS = {
22 | "Clubs", "Diamonds", "Hearts", "Spades"};
23 |
24 | // rank and suit are instance variables
25 | private final int rank;
26 | private final int suit;
27 |
28 | /**
29 | * Constructs a card of the given rank and suit.
30 | */
31 | public Card(int rank, int suit) {
32 | this.rank = rank;
33 | this.suit = suit;
34 | }
35 |
36 | /**
37 | * Gets the card's rank.
38 | */
39 | public int getRank() {
40 | return this.rank;
41 | }
42 |
43 | /**
44 | * Gets the card's suit.
45 | */
46 | public int getSuit() {
47 | return this.suit;
48 | }
49 |
50 | /**
51 | * Returns a string representation of the card.
52 | */
53 | public String toString() {
54 | return RANKS[this.rank] + " of " + SUITS[this.suit];
55 | }
56 |
57 | /**
58 | * Returns a negative integer if this card comes before
59 | * the given card, zero if the two cards are equal, or
60 | * a positive integer if this card comes after the card.
61 | */
62 | public int compareTo(Card that) {
63 | if (this.suit < that.suit) {
64 | return -1;
65 | }
66 | if (this.suit > that.suit) {
67 | return 1;
68 | }
69 | if (this.rank < that.rank) {
70 | return -1;
71 | }
72 | if (this.rank > that.rank) {
73 | return 1;
74 | }
75 | return 0;
76 | }
77 |
78 | /**
79 | * Returns true if the given card has the same
80 | * rank AND same suit; otherwise returns false.
81 | */
82 | public boolean equals(Card that) {
83 | return this.rank == that.rank
84 | && this.suit == that.suit;
85 | }
86 |
87 | /**
88 | * Make a List of 52 cards.
89 | */
90 | public static List makeDeck() {
91 | List cards = new ArrayList();
92 | for (int suit = 0; suit <= 3; suit++) {
93 | for (int rank = 1; rank <= 13; rank++) {
94 | Card card = new Card(rank, suit);
95 | cards.add(card);
96 | }
97 | }
98 | return cards;
99 | }
100 |
101 | /**
102 | * Demonstrates how to call the search methods.
103 | */
104 | public static void main(String[] args) {
105 |
106 | // sort the cards using the natural ordering
107 | List cards = makeDeck();
108 | Collections.sort(cards);
109 | System.out.println(cards.get(0));
110 | System.out.println(cards.get(51));
111 |
112 | Comparator comparator = new Comparator() {
113 | @Override
114 | public int compare(Card card1, Card card2) {
115 | if (card1.getSuit() < card2.getSuit()) {
116 | return -1;
117 | }
118 | if (card1.getSuit() > card2.getSuit()) {
119 | return 1;
120 | }
121 | int rank1 = getRankAceHigh(card1);
122 | int rank2 = getRankAceHigh(card2);
123 |
124 | if (rank1 < rank2) {
125 | return -1;
126 | }
127 | if (rank1 > rank2) {
128 | return 1;
129 | }
130 | return 0;
131 | }
132 |
133 | private int getRankAceHigh(Card card) {
134 | int rank = card.getRank();
135 | if (rank == 1) {
136 | return 14;
137 | } else {
138 | return rank;
139 | }
140 | }
141 | };
142 |
143 | // sort the cards using an external comparator
144 | Collections.sort(cards, comparator);
145 | System.out.println(cards.get(0));
146 | System.out.println(cards.get(51));
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/HelloJsoup.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import org.jsoup.Jsoup;
4 | import org.jsoup.nodes.Document;
5 | import org.jsoup.nodes.Element;
6 | import org.jsoup.select.Elements;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 |
11 | /**
12 | * Example program to list links from a URL.
13 | *
14 | * From: http://jsoup.org/cookbook/extracting-data/example-list-links
15 | */
16 | public class HelloJsoup {
17 |
18 | public static void main(String[] args) throws IOException {
19 |
20 | String dirname = System.getProperty("user.dir");
21 | String filename = "src/resources/en.wikipedia.org/wiki/Computer_science";
22 | String baseURI = dirname + "/" + filename;
23 |
24 | File input = new File(baseURI);
25 | Document doc = Jsoup.parse(input, "UTF-8", baseURI);
26 |
27 | //print("Fetching %s...", url);
28 | //Document doc = Jsoup.connect(url).get();
29 |
30 | Element content = doc.getElementById("mw-content-text");
31 | Elements paragraphs = content.getElementsByTag("p");
32 |
33 |
34 | for (Element p : paragraphs) {
35 | Elements links = p.select("a[href]");
36 | for (Element link : links) {
37 | print(" * a: <%s> (%s)", link.attr("href"), trim(link.text(), 35));
38 | }
39 | break;
40 | }
41 |
42 |
43 | // Elements media = doc.select("[src]");
44 | // Elements imports = doc.select("link[href]");
45 | //
46 | // print("\nMedia: (%d)", media.size());
47 | // for (Element src : media) {
48 | // if (src.tagName().equals("img")) {
49 | // print(" * %s: <%s> %sx%s (%s)",
50 | // src.tagName(), src.attr("abs:src"), src.attr("width"), src.attr("height"),
51 | // trim(src.attr("alt"), 20));
52 | // } else {
53 | // print(" * %s: <%s>", src.tagName(), src.attr("abs:src"));
54 | // }
55 | // }
56 | //
57 | // print("\nImports: (%d)", imports.size());
58 | // for (Element link : imports) {
59 | // print(" * %s <%s> (%s)", link.tagName(),link.attr("abs:href"), link.attr("rel"));
60 | // }
61 | //
62 | // print("\nLinks: (%d)", links.size());
63 | // for (Element link : links) {
64 | // print(" * a: <%s> (%s)", link.attr("abs:href"), trim(link.text(), 35));
65 | // break;
66 | // }
67 | }
68 |
69 | private static void print(String msg, Object... args) {
70 | System.out.println(String.format(msg, args));
71 | }
72 |
73 | private static String trim(String s, int width) {
74 | if (s.length() > width)
75 | return s.substring(0, width-1) + ".";
76 | else
77 | return s;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/Index.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import java.io.IOException;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 | import java.util.Set;
7 | import java.util.HashSet;
8 |
9 | import org.jsoup.select.Elements;
10 |
11 | /**
12 | * Encapsulates a map from search term to set of TermCounter.
13 | *
14 | * @author downey
15 | *
16 | */
17 | public class Index {
18 |
19 | private Map> index = new HashMap>();
20 |
21 | /**
22 | * Adds a TermCounter to the set associated with `term`.
23 | *
24 | * @param term
25 | * @param tc
26 | */
27 | public void add(String term, TermCounter tc) {
28 | Set set = get(term);
29 |
30 | // if we're seeing a term for the first time, make a new Set
31 | if (set == null) {
32 | set = new HashSet();
33 | index.put(term, set);
34 | }
35 | // otherwise we can modify an existing Set
36 | set.add(tc);
37 | }
38 |
39 | /**
40 | * Looks up a search term and returns a set of TermCounters.
41 | *
42 | * @param term
43 | * @return
44 | */
45 | public Set get(String term) {
46 | return index.get(term);
47 | }
48 |
49 | /**
50 | * Prints the contents of the index.
51 | */
52 | public void printIndex() {
53 | // loop through the search terms
54 | for (String term: keySet()) {
55 | System.out.println(term);
56 |
57 | // for each term, print the pages where it appears
58 | Set tcs = get(term);
59 | for (TermCounter tc: tcs) {
60 | Integer count = tc.get(term);
61 | System.out.println(" " + tc.getLabel() + " " + count);
62 | }
63 | }
64 | }
65 |
66 | /**
67 | * Returns the set of terms that have been indexed.
68 | *
69 | * @return
70 | */
71 | public Set keySet() {
72 | return index.keySet();
73 | }
74 |
75 | /**
76 | * Add a page to the index.
77 | *
78 | * @param url URL of the page.
79 | * @param paragraphs Collection of elements that should be indexed.
80 | */
81 | public void indexPage(String url, Elements paragraphs) {
82 | // TODO: Your code here
83 |
84 | // make a TermCounter and count the terms in the paragraphs
85 |
86 | // for each term in the TermCounter, add the TermCounter to the index
87 | }
88 |
89 | /**
90 | * @param args
91 | * @throws IOException
92 | */
93 | public static void main(String[] args) throws IOException {
94 |
95 | WikiFetcher wf = new WikiFetcher();
96 | Index indexer = new Index();
97 |
98 | String url = "https://en.wikipedia.org/wiki/Java_(programming_language)";
99 | Elements paragraphs = wf.fetchWikipedia(url);
100 | indexer.indexPage(url, paragraphs);
101 |
102 | url = "https://en.wikipedia.org/wiki/Programming_language";
103 | paragraphs = wf.fetchWikipedia(url);
104 | indexer.indexPage(url, paragraphs);
105 |
106 | indexer.printIndex();
107 | }
108 | }
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/IndexTest.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.hamcrest.CoreMatchers.*;
5 |
6 | import java.io.IOException;
7 | import java.util.Set;
8 |
9 | import org.jsoup.select.Elements;
10 | import org.junit.Before;
11 | import org.junit.Test;
12 |
13 | public class IndexTest {
14 |
15 | private Index index;
16 | private WikiFetcher wf;
17 |
18 | @Before
19 | public void setUp() {
20 | wf = new WikiFetcher();
21 | index = new Index();
22 | }
23 |
24 | @Test
25 | public void testIndexPage() throws IOException {
26 | // add two pages to the index
27 | String url = "https://en.wikipedia.org/wiki/Java_(programming_language)";
28 | Elements paragraphs = wf.readWikipedia(url);
29 | index.indexPage(url, paragraphs);
30 |
31 | url = "https://en.wikipedia.org/wiki/Programming_language";
32 | paragraphs = wf.readWikipedia(url);
33 | index.indexPage(url, paragraphs);
34 |
35 | // check the results: the word "occur" only appears on one page, twice
36 | Set set = index.get("occur");
37 | assertThat(set.size(), is(1));
38 |
39 | for (TermCounter tc: set) {
40 | // this loop only happens once
41 | assertThat(tc.size(), is(4798));
42 | assertThat(tc.get("occur"), is(2));
43 | assertThat(tc.get("not there"), is(0));
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/JedisIndexTest.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.hamcrest.CoreMatchers.*;
5 |
6 | import java.io.IOException;
7 | import java.util.Map;
8 |
9 | import org.jsoup.select.Elements;
10 | import org.junit.After;
11 | import org.junit.Before;
12 | import org.junit.Test;
13 |
14 | import redis.clients.jedis.Jedis;
15 |
16 | /**
17 | * @author downey
18 | *
19 | */
20 | public class JedisIndexTest {
21 |
22 | private static String url1, url2;
23 | private Jedis jedis;
24 | private JedisIndex index;
25 |
26 | /**
27 | * @throws java.lang.Exception
28 | */
29 | @Before
30 | public void setUp() throws Exception {
31 | jedis = JedisMaker.make();
32 | index = new JedisIndex(jedis);
33 |
34 | loadIndex(index);
35 | }
36 |
37 | /**
38 | * Loads the index with two pages read from files.
39 | *
40 | * @return
41 | * @throws IOException
42 | */
43 | private static void loadIndex(JedisIndex index) throws IOException {
44 | WikiFetcher wf = new WikiFetcher();
45 |
46 | url1 = "https://en.wikipedia.org/wiki/Java_(programming_language)";
47 | Elements paragraphs = wf.readWikipedia(url1);
48 | index.indexPage(url1, paragraphs);
49 |
50 | url2 = "https://en.wikipedia.org/wiki/Programming_language";
51 | paragraphs = wf.readWikipedia(url2);
52 | index.indexPage(url2, paragraphs);
53 | }
54 |
55 | /**
56 | * @throws java.lang.Exception
57 | */
58 | @After
59 | public void tearDown() throws Exception {
60 | jedis.close();
61 | }
62 |
63 | /**
64 | * Test method for {@link JedisIndex#getCounts(java.lang.String)}.
65 | */
66 | @Test
67 | public void testGetCounts() {
68 | Map map = index.getCounts("the");
69 | assertThat(map.get(url1), is(339));
70 | assertThat(map.get(url2), is(264));
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/JedisMaker.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.net.URI;
9 | import java.net.URISyntaxException;
10 | import java.net.URL;
11 | import java.net.URLDecoder;
12 |
13 | import redis.clients.jedis.Jedis;
14 |
15 |
16 | public class JedisMaker {
17 |
18 | /**
19 | * Make a Jedis object and authenticate it.
20 | *
21 | * @return
22 | * @throws IOException
23 | */
24 | public static Jedis make() throws IOException {
25 |
26 | // assemble the directory name
27 | String slash = File.separator;
28 | String filename = "resources" + slash + "redis_url.txt";
29 | URL fileURL = JedisMaker.class.getClassLoader().getResource(filename);
30 | String filepath = URLDecoder.decode(fileURL.getFile(), "UTF-8");
31 |
32 | // open the file
33 | StringBuilder sb = new StringBuilder();
34 | BufferedReader br;
35 | try {
36 | br = new BufferedReader(new FileReader(filepath));
37 | } catch (FileNotFoundException e1) {
38 | System.out.println("File not found: " + filename);
39 | printInstructions();
40 | return null;
41 | }
42 |
43 | // read the file
44 | while (true) {
45 | String line = br.readLine();
46 | if (line == null) break;
47 | sb.append(line);
48 | }
49 | br.close();
50 |
51 | // parse the URL
52 | URI uri;
53 | try {
54 | uri = new URI(sb.toString());
55 | } catch (URISyntaxException e) {
56 | System.out.println("Reading file: " + filename);
57 | System.out.println("It looks like this file does not contain a valid URI.");
58 | printInstructions();
59 | return null;
60 | }
61 | String host = uri.getHost();
62 | int port = uri.getPort();
63 |
64 | String[] array = uri.getAuthority().split("[:@]");
65 | String auth = array[1];
66 |
67 | // connect to the server
68 | Jedis jedis = new Jedis(host, port);
69 |
70 | try {
71 | jedis.auth(auth);
72 | } catch (Exception e) {
73 | System.out.println("Trying to connect to " + host);
74 | System.out.println("on port " + port);
75 | System.out.println("with authcode " + auth);
76 | System.out.println("Got exception " + e);
77 | printInstructions();
78 | return null;
79 | }
80 | return jedis;
81 | }
82 |
83 |
84 | /**
85 | *
86 | */
87 | private static void printInstructions() {
88 | System.out.println("");
89 | System.out.println("To connect to RedisToGo, you have to provide a file called");
90 | System.out.println("redis_url.txt that contains the URL of your Redis server.");
91 | System.out.println("If you select an instance on the RedisToGo web page,");
92 | System.out.println("you should see a URL that contains the information you need:");
93 | System.out.println("redis://redistogo:AUTH@HOST:PORT");
94 | System.out.println("Create a file called redis_url.txt in the src/resources");
95 | System.out.println("directory, and paste in the URL.");
96 | }
97 |
98 |
99 | /**
100 | * @param args
101 | * @throws IOException
102 | */
103 | public static void main(String[] args) throws IOException {
104 |
105 | Jedis jedis = make();
106 |
107 | // String
108 | jedis.set("mykey", "myvalue");
109 | String value = jedis.get("mykey");
110 | System.out.println("Got value: " + value);
111 |
112 | // Set
113 | jedis.sadd("myset", "element1", "element2", "element3");
114 | System.out.println("element2 is member: " + jedis.sismember("myset", "element2"));
115 |
116 | // List
117 | jedis.rpush("mylist", "element1", "element2", "element3");
118 | System.out.println("element at index 1: " + jedis.lindex("mylist", 1));
119 |
120 | // Hash
121 | jedis.hset("myhash", "word1", Integer.toString(2));
122 | jedis.hincrBy("myhash", "word2", 1);
123 | System.out.println("frequency of word1: " + jedis.hget("myhash", "word1"));
124 | System.out.println("frequency of word2: " + jedis.hget("myhash", "word2"));
125 |
126 | jedis.close();
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/code/src/com/allendowney/thinkdast/JedisTermCounter.java:
--------------------------------------------------------------------------------
1 | package com.allendowney.thinkdast;
2 |
3 | import java.io.IOException;
4 | import java.util.List;
5 | import java.util.Map;
6 | import org.jsoup.select.Elements;
7 |
8 | import redis.clients.jedis.Jedis;
9 | import redis.clients.jedis.Transaction;
10 |
11 |
12 | /**
13 | * Encapsulates a map from search term to frequency (count).
14 | *
15 | * @author downey
16 | *
17 | */
18 | public class JedisTermCounter extends TermCounter {
19 |
20 | public JedisTermCounter(String label) {
21 | super(label);
22 | }
23 |
24 | /**
25 | *
26 | * @return
27 | */
28 | public List