Problem
I want to print the nodes of a binary tree inorder and would like to have the nodes printed with as many dashes as the height they are in and then it's data.
Research done
I have found other posts like this one or this one but I'm still clueless on how I can represent my binary tree the way I want, as it differs to the ones stated on those questions.
Example
So lets say I insert nodes with data in this manner:
5,4,2,3,9,8
The output I would expect when representing the binary tree would be:
-9
--8
5
-4
---3
--2
Toy example code
So far I was able to print the nodes in the correct order. But after days I'm still clueless on how to implement a recursive function to get the correct representation. I also tried loops but found it's even messier and wasn't getting the correct result either.
The problem is that the amount of dashes is not the correct one and I'm unsure on where I need to append the dashes within the recursion. I'm thinking I may need to rewrite the whole printBinaryTreeRecurrsively code.
Below you can see the toy example code which can be compiled as a whole:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct repBinaryTree *BinaryTree;
struct repBinaryTree {
int data;
BinaryTree left;
BinaryTree right;
};
BinaryTree newNode() {
BinaryTree b = new repBinaryTree;
b->data = NULL;
b->left = b->right = NULL;
return b;
}
BinaryTree insertNode(int i, BinaryTree b) {
if (b==NULL) {
b = newNode();
b->data = i;
} else if ( i < b->data ) {
if (b->left == NULL) {
b->left = newNode();
b->left->data = i;
} else {
insertNode(i, b->left);
}
} else if ( i > b->data ) {
if (b->right == NULL) {
b->right = newNode();
b->right->data = i;
} else {
insertNode(i, b->right);
}
}
return b;
}
char* printBinaryTreeRecurrsively(BinaryTree b, char level[]) {
if (b == NULL) {
printf("\n");
return level;
} else {
level = printBinaryTreeRecurrsively(b->right, level);
printf("%s%d",level,b->data);
level = printBinaryTreeRecurrsively(b->left, level);
}
strcat(level,"-");
return level;
}
int main () {
BinaryTree b = insertNode(5,NULL);
b = insertNode(4, b);
b = insertNode(2, b);
b = insertNode(3, b);
b = insertNode(9, b);
b = insertNode(8, b);
printf("Recursive BinaryTree print:");
char level0[] = "";
printBinaryTreeRecurrsively(b, level0);
printf("Expected BinaryTree print:");
printf("\n-9\n--8\n5\n-4\n---3\n--2\n");
}
The output I get after compiling and running the program from command line is as follows:
cedric#multivac:~$ g++ printBinaryTree.cpp -o printBinaryTree
cedric#multivac:~$ ./printBinaryTree
Recursive BinaryTree print:
9
8
--5
--4
--3
---2
Expected BinaryTree print:
-9
--8
5
-4
---3
--2
Question
How should I rewrite my printBinaryTreeRecurrsively function code so as I get the correct output?
Modify the function to this instead
void printBinaryTreeRecurrsively(BinaryTree b, int level) {
if (b == NULL) {
printf("\n");
} else {
printBinaryTreeRecurrsively(b->right, level+1);
for (int i = 0; i < level; i++) {
printf("-");
}
printf("%d",b->data);
printBinaryTreeRecurrsively(b->left, level+1);
}
}
and call in main() as
printBinaryTreeRecurrsively(b, 0);
This method is much simpler than worrying about string concatenation etc. Just keep track of which level you're on with an int, print the correct number of -, and tell the levels below to print with one more -.
Related
First, I need to create and show a list that ends with number 1000. That works well.
Then, I want to create another list with only the numbers that are divisible by 3 in the first list, but it doesn't work.
The worst thing is that it doesn't even tell me what's going on. It just gives error in the execution but the console doesn't say anything.
I will really appreciate any help.
I tried all.
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define CANTIDAD_NUMEROS 13
#define CANTIDAD_NUMEROS2 6
#define DESDE 1
#define HASTA 10
typedef struct lista{
int num;
struct lista *sig;
}nodo;
void crear (nodo *pt, int, int);
void crear2 (nodo *pt, int, nodo *pt2);
void mostrar(nodo *pt);
int main()
{
int i=0;
int t=0;
nodo *prin;
nodo *prin2;
prin=(nodo*)malloc(sizeof(nodo));
prin2=(nodo*)malloc(sizeof(nodo));
crear(prin,i, t); //creates first list
mostrar (prin); //shows first list
crear2(prin,i, prin2); //gets 'divisible by 3' numbers
mostrar(prin2); // shows second list
return 0;
}
//creates list
void crear (nodo *registro, int cont, int t)
{
scanf("%d", &t);
registro->num = t;
if (registro->num == 1000)
registro->sig=NULL;
else
{
registro->sig=(nodo*)malloc(sizeof(nodo));
cont++;
crear (registro->sig,cont, t);
}
return;
}
//shows list
void mostrar (nodo *registro)
{
if (registro->sig !=NULL)
{
printf ("%d\n",registro->num);
mostrar (registro->sig);
}else{
printf("%d\n",registro->num);
}
return;
}
//creates second list with only numbers that are divisible by 3
void crear2 (nodo *registro, int cont, nodo *registroNuevo)
{
if ((registro->num % 3) == 0){
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
}
if(registro->sig != NULL){
crear2(registro->sig,cont, registroNuevo->sig);
}else{
return;
}
}
I expect to have the 1st list shown (which it's happening) and also the 2nd list shown with the numbers that are divisible by 3, which doesn't happen.
First of all, I admire your dedication to recursion!
The problem is that in crear2, registroNuevo->sig is uninitialized which causes a segfault. I almost always start a function that operates on a recursive linked data structure by checking if the parameter node is null. If so, I can safely continue on with the body of the function. Following this logic of protecting against nulls, we need to pass the registroNuevo node along without touching it in the case when registro->num % 3 != 0 and ensure all of its fields are initialized.
Here's the corrected function:
void crear2(nodo *registro, int cont, nodo *registroNuevo)
{
if (registro) {
if (registro->num % 3 == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = NULL;
if (registro->sig) {
registroNuevo->sig = malloc(sizeof(nodo));
}
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
crear2(registro->sig, cont, registroNuevo);
}
}
}
Having said that, this function is still a bit less than ideal for a couple reasons. First of all, the name is vague and could describe the behavior better. Also, if there are no items divisible by three, you've got a malloced node back in the calling scope that never gets initialized, so it's a bit brittle in that regard. Thirdly, even with a parameter, it feels like a highly specific function without much reusability factor that could be written iteratively inside the calling scope like:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo
{
int num;
struct nodo *sig;
} nodo;
nodo *crear(nodo *registro, int num)
{
nodo *n = malloc(sizeof(nodo));
n->num = num;
n->sig = registro;
return n;
}
void mostrar(nodo *registro)
{
if (registro)
{
printf("%d->", registro->num);
mostrar(registro->sig);
}
else puts("");
}
void free_lista(nodo *registro)
{
if (registro)
{
free_lista(registro->sig);
free(registro);
}
}
int main()
{
nodo *prin = NULL;
nodo *prin_div_3 = NULL;
for (int t; scanf("%d", &t) && t != 1000;)
{
prin = crear(prin, t);
}
nodo *tmp = prin;
while (tmp)
{
if (tmp->num % 3 == 0)
{
prin_div_3 = crear(prin_div_3, tmp->num);
}
tmp = tmp->sig;
}
mostrar(prin);
mostrar(prin_div_3);
free_lista(prin);
free_lista(prin_div_3);
return 0;
}
This isn't perfect--without tail nodes, adding to the list is a bit less than ideal, but dangling heads are eliminated, and hopefully it shows an alternate approach to organizing program logic and functions.
A few other remarks:
Always free memory that you've allocated. You can write a simple recursive routine to do so, like free_lista as shown in the above example.
Consider avoiding highly specific functions with hard-coded values like 3 and 1000. Make these parameters to maximize reusability.
crear2 never uses the cont member, and you have global constants that are unused. It's a good idea to clean these up to help clarify your debugging efforts and reduce visual clutter.
No need to cast the result of malloc.
if (registro->sig !=NULL) as the first line of a function is going to crash on a null. You don't need != NULL either. if (registro) { ... } is clearest and avoids problems with null parameters.
void crear2 (nodo *registro, int cont, nodo *registroNuevo) {
if ((registro->num % 3) == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo);
}
}
This is my approach, but you are still getting a final unexpected 0 at the last mostrar() call; and you still need to do the 'free' calls. I think you should avoid the recursive calls, there are easier ways to do it. Saludos.
My code doesn't adding second node to tree. It gives me SIGSEGV fault when i'm adding the second node.I think its about strcmp function but when i'm trying to understand how it works properly at the very bottom of main func it returns -1 so i've wrote it like this.And most of my variables named Turkish so here are the translations of them to make you understand more easily
dugum=node,kok=root;sol=left;sag=right;anne=mother
// C program to demonstrate insert operation in binary search tree
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tree {
char *harf;
char *morskodu;
struct tree *left;
struct tree *right;
} agac;
agac *kok = NULL;
void ekle(char *harf, char *morskodu) {
if (kok == NULL) {
kok = (agac *)malloc(sizeof(agac));
kok->harf = harf;
kok->morskodu = morskodu;
kok->left = NULL;
kok->right= NULL;
} else {
agac *yeni = (agac *)malloc(sizeof(agac));
yeni->harf = harf;
yeni->morskodu = morskodu;
yeni->left = NULL;
yeni->right = NULL;
agac *dugum = kok, *anne;
while (dugum != NULL) {
anne = dugum;
if (harf <= dugum->harf)
dugum = dugum->left;
else
dugum = dugum->right;
}
if (harf <= dugum->harf)
anne->left = yeni;
else
anne->right = yeni;
}
}
void dolas(agac *dugum) {
if (dugum != NULL) {
printf(" %s ", dugum->harf);
dolas(dugum->left);
dolas(dugum->right);
}
}
void main() {
ekle("a", "-");
ekle("b", "-.");
dolas(kok);
int x = strcmp("A", "B");
printf("%d", x);
}
You try to dereference a NULL pointer.
while (dugum != NULL) {
anne = dugum;
if (harf <= dugum->harf)
dugum = dugum->sol;
else
dugum = dugum->sag;
}
This loop ends when dugum is NULL.
Directly after you try to access dugum->harf:
if (harf <= dugum->harf)
This leads to undefined behavior.
Also note that this comparisons compare the pointers to string literals, and is therefore also undefined behavior. To compare two C strings you should use strcmp.
After hours of thinking and tinkering I almost gave up but decided to turn to the community for their help. I'm new to C and I just learned bubble sort. For example the following code sorts by name, what I would like to implement is a sub sort where it also sorts by person ID, how would I do that or change the following code to do just that? (This is structure problem).
struct human {
char name;
char id;
}
function sorting(struct human person)
{
struct human temp
int i, unsorted;
do{
unsorted = 0;
for(i = o; i<count-1; i++)
{
if(strcmp(person[i].name, person.name) > 0)
{
temp = person[i];
person[i] = person[i+1];
person[i+1] = temp;
unsorted = 1;
}
}while(unsorted);
}
First, it would help to break out your comparison function into its own function:
int compare_people(struct human *person1, struct human *person2)
{
return strcmp(person1->name, person2->name);
}
Then, you can more easily change the logic to compare ID if the name is equal:
int compare_people(struct human *person1, struct human *person2)
{
int d = strcmp(person1->name, person2->name);
if (d == 0) {
return person2->id - person1->id;
} else {
return d;
}
}
I would like to implement functions where I perform a pre, in and postorder traversal of an existing binary tree.
these traversals should then be displayed by a predefined test function
here's what i got so far for the preorder traversal
uint64_t i = 0;
int *binarytree_prefix(binarytree *tree) {
uint64_t *prefixArray = malloc(inputArrayLength_helper * sizeof(uint64_t));
prefixArray[i] = tree->value;
i++;
if (tree->left != NULL) {
return (binarytree_prefix(tree->left));
}
if (tree->right != NULL) {
return (binarytree_prefix(tree->right));
}
}
what I thought about it that it would insert the value of the current node into the array and then increent the position within the array and do a recursion on the left and then the right tree
however this does not work.
i hope someone is able to help me to make it running
What i did was a depth first search with a preorder traversal and then included the array to fill it with the current value
test function within main:
int *prefixArray = bintree_prefix(tree);
printf("Prefix notation : ");
for(uint64_t i = 0; i < inputArrayLength; i++) {
printf(" %d", prefixArray[i]);
}
printf("\n");
free(prefixArray);
ok after a few different variations of the code i finally got the right solution
for those interested
int *bintree_prefix(bintree *tree)
{
int *prefixArray = malloc(17*sizeof(uint64_t));
return (bintree_prefix_visited(tree, prefixArray));
}
int bintree_prefix_visited(bintree *tree, int *prefixArray)
{
if (tree!=NULL)
{
prefixArray[a]=tree->value;
a++;
bintree_prefix_visited(tree->left, prefixArray);
bintree_prefix_visited(tree->right, prefixArray);
}
return prefixArray;
}
I want to print out into my sorted tree on which level this number was and that must be a recursion function.
Here is my code:
void printout(KNOTEN *start) {
if (start == NULL)
return;
printout(start->left);
printf("%d\n", start->number);
printout(start->right);
free(start);
}
Here is an example of the output:
My input Numbers 41, 18467, 6334 , 26500, 19169
Outprint is 41,6334,18467,19169,26500
What I want is:
41 Level 1 , 6334 level 3 , 18467 level 2 , 26500 level 3 , 19169 level 4
I would modify it to this:
void printout(KNOTEN *start, int depth)
{
if(start == NULL)
return;
printout(start->left, depth+1);
printf("%d(%d) \n",start->number, depth);
printout(start->right, depth+1);
free(start);
}
here is a hint. your prototype is this
printout(KNOTEN *start, int the_level)
and this is how you call it to start your search.
printout(node, 1);
and there is a the_level + 1 in two places in your code.
good luck
This sounds like homework, so I'm not going to give you complete code. But the idea is to keep count of how many recursive calls you've made:
int myRecursiveFunction(Node *node, int thingToFind, int level)
{
if (someCondition())
{
return level;
}
else
{
if (goLeft())
{
return myRecursiveFunction(node->left, thingToFind, level+1);
}
else
{
return myRecursiveFunction(node->right, thingToFind, level+1);
}
}
}
...
int level = myRecursiveFunction(root, thingToFind, 0);