/* Binary search tree without balancing * 15-122 Principles of Imperative Computation, Fall 2010 * Frank Pfenning */ /* compile with -lstring */ /*************************/ /* Client types and code */ /*************************/ /* elements */ struct elem { string word; /* key */ int count; /* information */ }; /* key comparison */ int compare(string s1, string s2) { return string_compare(s1,s2); } /* extracting keys from elements */ string elem_key(struct elem* e) //@requires e != NULL; { return e->word; } /* Interface type definitions */ /* provided above by client and used below in implementation */ typedef string key; typedef struct elem* elem; /* NULL must be an elem */ key elem_key(elem e); int compare(key k1, key k2); /* Interface */ typedef struct bst* bst; bst bst_new(); void bst_insert(bst B, elem x); /* might change to return old entry with key(x)? */ elem bst_search(bst B, key k); /* return NULL if not in tree */ /* Implementation */ typedef struct tree* tree; struct tree { elem data; tree left; tree right; }; struct bst { tree root; }; bool is_ordered(tree T, elem min, elem max) { if (T == NULL) return true; // empty tree is okay! if (T->data == NULL) return false; // no data -- bogus else { key k = elem_key(T->data); return // make sure the data is between min and max (min == NULL || compare(elem_key(min), k) < 0) && (max == NULL || compare(k, elem_key(max)) < 0) // check the subtrees && is_ordered(T->left, min, T->data) && is_ordered(T->right, T->data, max); } } bool is_ordtree(tree T) { return is_ordered(T, NULL, NULL); } bool is_bst(bst B) { return B != NULL && is_ordtree(B->root); } bst bst_new() //@ensures is_bst(\result); { bst B = alloc(struct bst); B->root = NULL; return B; } elem tree_search(tree T, key k) //@requires is_ordtree(T); //@ensures \result == NULL || compare(elem_key(\result), k) == 0; { if (T == NULL) return NULL; { key kt = elem_key(T->data); // key in tree node if (compare(k, kt) == 0) return T->data; else if (compare(k, kt) < 0) return tree_search(T->left, k); else return tree_search(T->right, k); } } elem bst_search(bst B, key k) //@requires is_bst(B); //@ensures \result == NULL || compare(elem_key(\result), k) == 0; { return tree_search(B->root, k); } tree rotate_right(tree T) //@requires T != NULL && T->left != NULL; //@requires is_ordtree(T); //@ensures is_ordtree(\result); //@ensures \result != NULL && \result->data == \old(T->left->data); { tree root = T->left; T->left = root->right; root->right = T; return root; } tree rotate_left(tree T) //@requires T != NULL && T->right != NULL; //@requires is_ordtree(T); //@ensures is_ordtree(\result); //@ensures \result != NULL && \result->data == \old(T->right->data); { tree root = T->right; T->right = root->left; root->left = T; return root; } tree root_insert(tree T, elem e) //@requires is_ordtree(T); //@requires e != NULL; //@ensures is_ordtree(T); //@ensures \result != NULL && \result->data == e; //@ensures tree_search(\result, elem_key(e)) == e; { if (T == NULL) { T = alloc(struct tree); T->data = e; T->left = NULL; T->right = NULL; } else { key kt = elem_key(T->data); key k = elem_key(e); if (compare(k, kt) == 0) { // don't rotate if updated in place T->data = e; } else if (compare(k, kt) < 0) { T->left = root_insert(T->left, e); T = rotate_right(T); } else { //@assert compare(k, kt) > 0; T->right = root_insert(T->right, e); T = rotate_left(T); } } return T; } void bst_insert(bst B, elem e) //@requires is_bst(B); //@ensures is_bst(B); { B->root = root_insert(B->root, e); return; }