/* Here's the binary search using start and size rather than low and high. I can't really articulate why, but I find this easier to understand than using low and high, especially when the search loop ends. Note how I decrement size by size/2 when I'm discarding the first half of the vector. This is to handle odd and even sizes correctly. */ #include #include #include #include using namespace std; class Bsearch { public: void Create(const string &filename); // Create the vector from the file. bool Find(const string &word) const; // Return whether a word is in the vector. protected: vector words; }; /* Create() is straightforward -- it reads each words into a vector, and while doing so, determines whether the vector is sorted. If it is not, then it is sorted at the end of Create(). */ void Bsearch::Create(const string &filename) { ifstream fin; bool sorted; string w; sorted = true; fin.open(filename.c_str()); if (fin.fail()) throw (string) "Could not open " + filename; while (fin >> w) { if (words.size() > 0 && w < words[words.size()-1]) sorted = false; words.push_back(w); } if (!sorted) sort(words.begin(), words.end()); } /* This is the code where I use start and size rather than low and high. */ bool Bsearch::Find(const string &word) const { int start, size, mid; start = 0; size = words.size(); if (size == 0) return false; while (size > 1) { mid = start + size/2; /* I guess I like how this code translates logically: */ if (words[mid] > word) { /* If word is not in the second half... */ size /= 2; /* Discard the second half. */ } else { start += size/2; /* Otherwise discard the first half. */ size -= size/2; } } printf("start: %d\n", start); return (words[start] == word); } /* The main() is straightfoward -- create the dictionary from the file, then find each word on standard input. */ int main(int argc, char **argv) { Bsearch b; bool verbose, fnd; int tfound, total; string w; try { if (argc != 3) throw (string) "usage: a.out dictionary-file verbose(y/n) -- words on stdin."; verbose = (argv[2][0] == 'y'); tfound = 0; total = 0; b.Create(argv[1]); while (cin >> w) { total++; fnd = b.Find(w); if (fnd) tfound++; if (verbose) printf("%s: %s\n", w.c_str(), (fnd) ? "found" : "not-found"); } printf("Found: %d of %d\n", tfound, total); } catch (const string &s) { cerr << s << endl; return 1; } }