Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <time.h>
- #include <string.h>
- #include <math.h>
- #define MAX_HEIGHT 1000
- #define INFINITY (1<<20)
- struct tree {
- int key;
- struct tree* left;
- struct tree* right;
- };
- typedef struct asciiNode {
- struct asciiNode* left;
- struct asciiNode* right;
- int edge_length;
- int height;
- int lablen;
- int parent_dir; // -1=left, 0=root, 1=right
- char label[11]; // Max label length of 10 chars + terminator
- } asciiNode;
- int MAX(int x, int y) { return ((x) > (y)) ? (x) : (y); }
- int MIN(int x, int y) { return ((x) < (y)) ? (x) : (y); }
- // Get the maximum height of the tree
- int getMaxHeight(struct tree* n) {
- if (n == NULL) return 0;
- int leftHeight = getMaxHeight(n->left);
- int rightHeight = getMaxHeight(n->right);
- return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
- }
- // Convert integer to string
- int intToString(int val, char* buff) {
- sprintf(buff, "%d", val);
- return strlen(buff);
- }
- // Print the arm branches (eg, / \ ) between nodes
- void printBranches(int branchLen, int nodeSpacing, int startLen, int nodesInThisLevel, const asciiNode** nodesQueue, FILE* out) {
- int i, j;
- for (i = 0; i < nodesInThisLevel / 2; i++) {
- for (j = 0; j < startLen - 1; j++) fprintf(out, " ");
- if (nodesQueue[i * 2] != NULL) {
- fprintf(out, "/");
- }
- else {
- fprintf(out, " ");
- }
- for (j = 0; j < branchLen - 1; j++) fprintf(out, " ");
- if (nodesQueue[i * 2 + 1] != NULL) {
- fprintf(out, "\\");
- }
- else {
- fprintf(out, " ");
- }
- for (j = 0; j < nodeSpacing - 2; j++) fprintf(out, " ");
- }
- fprintf(out, "\n");
- }
- // Print the branches and node (eg, ___10___ )
- void printNodes(int branchLen, int nodeSpacing, int startLen, int nodesInThisLevel, const asciiNode** nodesQueue, FILE* out) {
- int i, j;
- for (i = 0; i < nodesInThisLevel; i++) {
- for (j = 0; j < startLen; j++) fprintf(out, " ");
- if (nodesQueue[i] == NULL) {
- for (j = 0; j < branchLen + 2; j++) fprintf(out, " ");
- continue;
- }
- if (strlen(nodesQueue[i]->label) == 1)
- fprintf(out, "%s", nodesQueue[i]->label);
- else
- fprintf(out, "%s", nodesQueue[i]->label);
- for (j = 0; j < nodeSpacing; j++) fprintf(out, " ");
- }
- fprintf(out, "\n");
- }
- struct tree* treeMakeRandom(int lo, int hi) {
- struct tree* t;
- if (hi <= lo) {
- return 0;
- }
- else {
- int mid = lo + rand() % (hi - lo);
- t = (struct tree*)malloc(sizeof(struct tree));
- t->key = mid;
- t->left = treeMakeRandom(lo, mid);
- t->right = treeMakeRandom(mid + 1, hi);
- return t;
- }
- }
- asciiNode* createAsciiNode() {
- asciiNode* node = malloc(sizeof(asciiNode));
- node->left = NULL;
- node->right = NULL;
- node->edge_length = 0;
- node->height = 0;
- node->lablen = 0;
- node->parent_dir = 0;
- return node;
- }
- // Convert the binary tree to ASCII tree
- asciiNode* buildAsciiTreeRecursive(struct tree* t) {
- if (t == NULL) return NULL;
- asciiNode* node = createAsciiNode();
- node->left = buildAsciiTreeRecursive(t->left);
- node->right = buildAsciiTreeRecursive(t->right);
- if (node->left) node->left->parent_dir = -1;
- if (node->right) node->right->parent_dir = 1;
- sprintf(node->label, "%d", t->key);
- node->lablen = strlen(node->label);
- return node;
- }
- asciiNode* buildAsciiTree(struct tree* t) {
- if (t == NULL) return NULL;
- asciiNode* node = buildAsciiTreeRecursive(t);
- node->parent_dir = 0;
- return node;
- }
- // The following function fills in the lprofile array for the given tree.
- // It assumes that the center of the label of the root of this tree
- // is located at a position (x,y). It assumes that the edge_length
- // fields have been computed for this tree.
- void computeLprofile(asciiNode* node, int x, int y, int* lprofile) {
- if (node == NULL) return;
- int isleft = (node->parent_dir == -1);
- lprofile[y] = MIN(lprofile[y], x - ((node->lablen - isleft) / 2));
- if (node->left != NULL) {
- for (int i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++) {
- lprofile[y + i] = MIN(lprofile[y + i], x - i);
- }
- }
- computeLprofile(node->left, x - node->edge_length - 1, y + node->edge_length + 1, lprofile);
- computeLprofile(node->right, x + node->edge_length + 1, y + node->edge_length + 1, lprofile);
- }
- void computeRprofile(asciiNode* node, int x, int y, int* rprofile) {
- if (node == NULL) return;
- int notleft = (node->parent_dir != -1);
- rprofile[y] = MAX(rprofile[y], x + ((node->lablen - notleft) / 2));
- if (node->right != NULL) {
- for (int i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++) {
- rprofile[y + i] = MAX(rprofile[y + i], x + i);
- }
- }
- computeRprofile(node->left, x - node->edge_length - 1, y + node->edge_length + 1, rprofile);
- computeRprofile(node->right, x + node->edge_length + 1, y + node->edge_length + 1, rprofile);
- }
- // Compute the gap between two subtrees
- int getGap(asciiNode* leftRoot, asciiNode* rightRoot) {
- int i, j;
- int* lprofile = malloc(sizeof(int) * MAX_HEIGHT);
- int* rprofile = malloc(sizeof(int) * MAX_HEIGHT);
- int gap = 0;
- for (i = 0; i < MAX_HEIGHT; i++) {
- lprofile[i] = INFINITY;
- rprofile[i] = -INFINITY;
- }
- computeLprofile(leftRoot, 0, 0, lprofile);
- computeRprofile(rightRoot, 0, 0, rprofile);
- for (i = 0; i < MAX_HEIGHT; i++) {
- gap = MAX(gap, lprofile[i] - rprofile[i]);
- }
- free(lprofile);
- free(rprofile);
- return gap + 1;
- }
- void computeEdgeLengths(asciiNode* node) {
- if (node == NULL) return;
- computeEdgeLengths(node->left);
- computeEdgeLengths(node->right);
- // Initialize min_height and delta
- int min_height = MIN(
- node->left ? node->left->height : 0,
- node->right ? node->right->height : 0);
- int delta = 4;
- // Set edge_length for this node
- node->edge_length = ((delta + min_height) / 2) - 1;
- }
- void printLevel(asciiNode* node, int x, int level) {
- if (node == NULL) return;
- int i, isleft = (node->parent_dir == -1);
- if (level == 0) {
- for (i = 0; i < (x - node->lablen) / 2; i++) printf(" ");
- printf("%s", node->label);
- for (i = 0; i < (x - node->lablen + 1) / 2; i++) printf(" ");
- }
- else if (node->edge_length >= level) {
- if (node->left != NULL) {
- for (i = 0; i < (x - 2) / 2; i++) printf(" ");
- printf("/");
- for (i = 0; i < (x - 2) / 2 + 1; i++) printf(" ");
- }
- else {
- for (i = 0; i < x; i++) printf(" ");
- }
- if (node->right != NULL) {
- for (i = 0; i < (x - 2) / 2; i++) printf(" ");
- printf("\\");
- for (i = 0; i < (x - 2) / 2 + 1; i++) printf(" ");
- }
- else {
- for (i = 0; i < x; i++) printf(" ");
- }
- }
- else {
- printLevel(node->left, x / 2, level - node->edge_length - 1);
- printLevel(node->right, x / 2, level - node->edge_length - 1);
- }
- }
- void printTree(struct tree* t) {
- if (t == NULL) return;
- asciiNode* proot = buildAsciiTree(t);
- computeEdgeLengths(proot);
- // Compute height of the tree
- int h = proot->height;
- // Width of the tree, adjusted for better spacing
- int w = pow(2, h) * 2 - 1;
- // Print each level
- for (int i = 0; i <= h; i++) {
- printLevel(proot, w, i);
- printf("\n");
- }
- }
- int treeSize(const struct tree* t) {
- if (t == 0) {
- return 0;
- }
- else {
- return 1 + treeSize(t->left) + treeSize(t->right);
- }
- }
- int treeHeight(const struct tree* t) {
- if (t == 0) {
- return -1;
- }
- else {
- int l = treeHeight(t->left);
- int r = treeHeight(t->right);
- return 1 + ((l > r) ? l : r);
- }
- }
- void freeAsciiTree(asciiNode* node) {
- if (node == NULL) return;
- freeAsciiTree(node->left);
- freeAsciiTree(node->right);
- free(node);
- }
- void freeTree(struct tree* t) {
- if (t != NULL) {
- freeTree(t->left);
- freeTree(t->right);
- free(t);
- }
- }
- int main() {
- int n;
- printf("Enter the maximum value for the tree (n): ");
- if (scanf("%d", &n) != 1 || n <= 0) {
- fprintf(stderr, "Invalid input. Please enter a positive number.\n");
- return 1;
- }
- srand(time(0));
- struct tree* t = treeMakeRandom(0, n);
- printf("\nBinary Search Tree:\n");
- printTree(t);
- printf("\nSize = %d\n", treeSize(t));
- printf("Height = %d\n", treeHeight(t));
- // Clean up
- freeTree(t);
- // Pause the console
- printf("\nPress Enter to continue...");
- getchar(); // Consume the newline from scanf
- getchar(); // Wait for Enter key
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement