Table Of Contents
Previous Section Next Section

Program 61: Looking Through a Dictionary Slowly

I wrote the following program when I was a junior at Caltech. (It was written in Pascal originally.) I was a poor speller, so I needed something to help me find words in the dictionary.

I decided to write a program to read the dictionary into a binary tree (a data structure I just learned about) and to look for words in it.

Binary trees are supposed to be efficient data structures, but this program takes an awfully long time to execute.

Why?

  1 /************************************************
  2  * find_word -- find a word in the dictionary.  *
  3  *                                              *
  4  * Usage:                                       *
  5  *     find_word <word-start> [<word-start>...] *
  6  ************************************************/
  7 #include <iostream>
  8 #include <fstream>
  9 #include <iomanip>
 10 #include <cctype>
 11 #include <cstring>
 12 #include <cstdlib>
 13
 14 /************************************************
 15  * tree -- A simple binary tree class           *
 16  *                                              *
 17  * Member functions:                            *
 18  *      enter -- Add an entry to the tree       *
 19  *      find -- See if an entry is in the tree. *
 20  ************************************************/
 21 class tree
 22 {
 23     private:
 24         // The basic node of a tree
 25         class node {
 26             private:
 27                 // tree to the right
 28                 node    *right;
 29
 30                 // tree to the left
 31                 node    *left;
 32             public:
 33                 // data for this tree
 34                 char    *data;
 35
 36             public:
 37                 node() :
 38                     right(NULL), left(NULL),
 39                     data(NULL) {}
 40                 // Destructor defaults
 41             private:
 42                 // No copy constructor
 43                 node(const node &);
 44
 45                 // No assignment operator
 46                 node & operator = (const node &);
 47
 48             // Let tree manipulate our data
 49             friend class tree;
 50
 51         };
 52
 53         // the top of the tree
 54         node *root;
 55
 56         // Enter a new node into a tree or
 57         // sub-tree
 58         void enter_one(
 59            // Node of sub-tree to look at
 60            node *&node,
 61
 62            // Word to add
 63            const char *const data
 64         );
 65
 66         // Find an item in the tree
 67         void find_one(
 68             // Prefix to search for
 69             const char start[],
 70
 71             // Node to start search
 72             const node *const node,
 73
 74             // Keep looking flag
 75             const bool look
 76         );
 77     public:
 78         tree(void) { root = NULL;}
 79         // Destructor defaults
 80     private:
 81         // No copy constructor
 82         tree(const tree &);
 83
 84         // No assignment operator
 85         tree & operator = (const tree &);
 86
 87     public:
 88         // Add a new data to our tree
 89         void enter(
 90             // Data to add
 91             const char *const data
 92         ) {
 93             enter_one(root, data);
 94         }
 95
 96         // Find all words that start
 97         // with the given prefix
 98         void find(
 99             const char start[]  // Starting string
100         )
101         {
102             find_one(start, root, true);
103         }
104 };
105
106 /************************************************
107  * tree::enter_one -- enter a data into         *
108  *      the tree                                *
109  ************************************************/
110 void tree::enter_one(
111    node *&new_node,       // Sub-tree to look at
112    const char *const data // Word to add
113 )
114 {
115     int  result;        // result of strcmp
116
117     // see if we have reached the end
118     if (new_node == NULL) {
119         new_node = new node;
120
121         new_node->left = NULL;
122         new_node->right = NULL;
123         new_node->data = strdup(data);
124     }
125
126     result = strcmp(new_node->data, data);
127     if (result == 0) {
128         return;
129     }
130
131     if (result < 0)
132         enter_one(new_node->right, data);
133     else
134         enter_one(new_node->left, data);
135 }
136
137 /************************************************
138  * tree::find_one -- find words that match this *
139  *                      one in the tree.        *
140  ************************************************/
141 void tree::find_one(
142         const char start[],   // Start of the work
143         const node *const top,// Top node
144         const bool look       // Keep looking
145 )
146 {
147     if (top == NULL)
148         return;                 // short tree
149
150     // Result of checking our prefix
151     // against the word
152     int cmp = strncmp(start,
153             top->data, strlen(start));
154
155     if ((cmp < 0) && (look))
156         find_one(start, top->left, true);
157     else if ((cmp > 0) && (look))
158         find_one(start, top->right, true);
159
160     if (cmp != 0)
161         return;
162
163     /*
164      * We found a string that starts this one.
165      * Keep searching and print things.
166      */
167     find_one(start, top->left, false);
168     std::cout << top->data << '\n';
169     find_one(start, top->right, false);
170 }
171
172 int main(int argc, char *argv[])
173 {
174     // A tree to hold a set of words
175     tree dict_tree;
176
177     // The dictionary to search
178     std::ifstream dict_file("/usr/dict/words");
179
180     if (dict_file.bad()) {
181         std::cerr <<
182             "Error: Unable to open "
183             "dictionary file\n";
184         exit (8);
185     }
186
187     /*
188      * Read the dictionary and construct the tree
189      */
190     while (1) {
191         char line[100]; // Line from the file
192
193         dict_file.getline(line, sizeof(line));
194
195         if (dict_file.eof())
196             break;
197
198         dict_tree.enter(strdup(line));
199     }
200     /*
201      * Search for each word
202      */
203     while (argc > 1) {
204         std::cout << "------ " << argv[1] << '\n';
205         dict_tree.find(argv[1]);
206         ++argv;
207         --argc;
208     }
209     return (0);
210 }

(Next Hint 42. Answer 74.)

Table Of Contents
Previous Section Next Section