|
| 1 | +// Implementing a crit-bit tree in C++. |
| 2 | +// This is a simple implementation of a crit-bit tree, which is a |
| 3 | +// data structure for storing strings. It is a binary tree, where |
| 4 | +// each node is a bit in the string. The tree is balanced, and |
| 5 | +// the strings are stored in lexicographic order. |
| 6 | + |
| 7 | +#include <bits/stdc++.h> |
| 8 | +using namespace std; |
| 9 | + |
| 10 | +// A crit-bit tree is a binary tree, where each node is a bit in the |
| 11 | +// string. The tree is balanced, and the strings are stored in |
| 12 | +// lexicographic order. The tree is represented by a pointer to the |
| 13 | +// root node. The root node is a dummy node, and the actual strings |
| 14 | +// are stored in the children of the root node. The root node is |
| 15 | +// always a 0 node, and the children of the root node are always 1 |
| 16 | +// nodes. The children of a 1 node are either 0 nodes or 1 nodes. |
| 17 | + |
| 18 | +// Create a new node with the given bit and value. |
| 19 | +struct node { |
| 20 | + int bit; |
| 21 | + string value; |
| 22 | + node *left, *right; |
| 23 | + node(int bit, string value) : bit(bit), value(value), left(NULL), right(NULL) {} |
| 24 | +}; |
| 25 | + |
| 26 | +// Insert a string into the tree. The tree is modified in place. |
| 27 | +void insert(node *&root, string s) { |
| 28 | + // If the tree is empty, create a new root node. |
| 29 | + if (root == NULL) { |
| 30 | + root = new node(0, ""); |
| 31 | + root->left = new node(1, s); |
| 32 | + return; |
| 33 | + } |
| 34 | + |
| 35 | + // Find the node with the highest bit that is different from the |
| 36 | + // string. If there is no such node, then the string is already |
| 37 | + // in the tree. |
| 38 | + node *n = root; |
| 39 | + while (n->bit < s.size() && n->bit < n->value.size() && s[n->bit] == n->value[n->bit]) |
| 40 | + n = (s[n->bit] == '0') ? n->left : n->right; |
| 41 | + if (n->bit >= s.size() || n->bit >= n->value.size()) return; |
| 42 | + |
| 43 | + // Create a new node with the bit that is different from the |
| 44 | + // string. The new node will be the parent of the old node and |
| 45 | + // the new string. |
| 46 | + node *p = new node(n->bit, s); |
| 47 | + if (s[p->bit] == '0') { |
| 48 | + p->left = new node(p->bit + 1, s); |
| 49 | + p->right = n; |
| 50 | + } else { |
| 51 | + p->left = n; |
| 52 | + p->right = new node(p->bit + 1, s); |
| 53 | + } |
| 54 | + |
| 55 | + // Replace the old node with the new node. |
| 56 | + if (n == root) { |
| 57 | + root = p; |
| 58 | + } else { |
| 59 | + node *parent = root; |
| 60 | + while (parent->left != n && parent->right != n) |
| 61 | + parent = (s[parent->bit] == '0') ? parent->left : parent->right; |
| 62 | + if (parent->left == n) |
| 63 | + parent->left = p; |
| 64 | + else |
| 65 | + parent->right = p; |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +// Find the string in the tree that is equal to the given string. |
| 70 | +// If there is no such string, return NULL. |
| 71 | +string *find(node *root, string s) { |
| 72 | + if (root == NULL) return NULL; |
| 73 | + node *n = root; |
| 74 | + while (n->bit < s.size() && n->bit < n->value.size() && s[n->bit] == n->value[n->bit]) |
| 75 | + n = (s[n->bit] == '0') ? n->left : n->right; |
| 76 | + if (n->bit >= s.size() || n->bit >= n->value.size()) return NULL; |
| 77 | + return &n->value; |
| 78 | +} |
| 79 | + |
| 80 | +// construct a crit-bit tree from a list of strings |
| 81 | +node *construct(vector<string> &strings) { |
| 82 | + node *root = NULL; |
| 83 | + for (string s : strings) |
| 84 | + insert(root, s); |
| 85 | + return root; |
| 86 | +} |
| 87 | + |
| 88 | +// print the crit-bit tree in lexicographic order |
| 89 | +void print(node *root) { |
| 90 | + if (root == NULL) return; |
| 91 | + print(root->left); |
| 92 | + cout << root->value << endl; |
| 93 | + print(root->right); |
| 94 | +} |
0 commit comments