add debugPrintDot

This commit is contained in:
2024-01-17 14:10:50 -08:00
parent a6381a981e
commit aa85c77d8f
3 changed files with 79 additions and 2 deletions

View File

@@ -86,6 +86,77 @@ void destroyNode(Node *node) {
assert(node->child[1] == nullptr);
free(node);
}
// Return a pointer to the node whose key immediately follows `n`'s key (if
// `dir` is false, precedes). Return nullptr if none exists.
[[maybe_unused]] Node *next(Node *n, bool dir) {
// Traverse left spine of right child (when moving right, i.e. dir = true)
if (n->child[dir]) {
n = n->child[dir];
while (n->child[!dir]) {
n = n->child[!dir];
}
} else {
// Search upward for a node such that we're the left child (when moving
// right, i.e. dir = true)
while (n->parent && n == n->parent->child[dir]) {
n = n->parent;
}
n = n->parent;
}
return n;
}
// Return a pointer to the node whose key is greatest among keys in the tree
// rooted at `n` (if dir = false, least). Return nullptr if none exists (i.e.
// `n` is null).
[[maybe_unused]] Node *extrema(Node *n, bool dir) {
if (n == nullptr) {
return nullptr;
}
while (n->child[dir] != nullptr) {
n = n->child[dir];
}
return n;
}
[[maybe_unused]] void debugPrintDot(FILE *file, Node *node) {
struct DebugDotPrinter {
explicit DebugDotPrinter(FILE *file) : file(file) {}
void print(Node *node) {
for (int i = 0; i < 2; ++i) {
if (node->child[0] != nullptr) {
fprintf(file, " _%.*s -> _%.*s;\n", node->len,
(const char *)(node + 1), node->child[0]->len,
(const char *)(node->child[0] + 1));
print(node->child[0]);
} else {
fprintf(file, " _%.*s -> null%d;\n", node->len,
(const char *)(node + 1), id);
fprintf(file, " null%d [shape=point];\n", id);
++id;
}
}
}
int id = 0;
FILE *file;
};
fprintf(file, "digraph TreeSet {\n");
fprintf(file, " node [fontname=\"Scientifica\"];\n");
for (auto iter = extrema(node, false); iter != nullptr;
iter = next(iter, true)) {
fprintf(file, " _%.*s;\n", node->len, (const char *)(node + 1));
}
if (node != nullptr) {
DebugDotPrinter{file}.print(node);
}
fprintf(file, "}\n");
}
} // namespace
struct ConflictSet::Impl {
@@ -151,5 +222,8 @@ ConflictSet &ConflictSet::operator=(ConflictSet &&other) noexcept {
}
#ifdef ENABLE_TESTS
int main(void) { ConflictSet cs{0}; }
int main(void) {
ConflictSet::Impl cs{0};
debugPrintDot(stdout, cs.root);
}
#endif