Pre/In/Postfix traversal in C including an Array - c

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;
}

Related

Recursive function to represent binary tree in C

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 -.

How can i generate a binary code table of a huffman tree?

I want to implement an function which gives me a binary code for each char in a huffman tree.
To implement the function i tried traversing the table by using a recursive function. However i don't know how to fill the result the binary code for each char so that the function returns an array of struct with all the chars and binary codes
I hope someone can point me in the right direction.
Thanks ahead!
Ok, let's see a possible solution:
#include <stdint.h>
typedef struct code {
size_t code_length;
uint32_t code;
} code;
void compute_code_table(tree_t node, code *t, code c)
{
if (node->left == NULL)
t[node->letter] = c;
else {
c.code_length++;
c.code <<= 1;
compute_code_table(node->left, t, c);
c.code += 1;
compute_code_table(node->right, t, c);
}
}
void code_print(code *c)
{
size_t n = c->code_length;
while (n --> 0)
putchar('0' + ((c->code >> n) & 1));
}
int main(void)
{
tree_t root = fixed_tree();
code table[256] = { 0 };
code c = { 0 };
compute_code_table(root, table, c);
for (size_t i = 0; i < 256; ++i) {
if (table[i].code_length) {
printf("%c\t", i);
code_print(table + i);
printf("\n");
}
}
}
Basically the idea is to have a table which is filled at every leaf. While doing the recursion we pass the current node, the table and the current code. If we are at a leaf we just store the code in the table, otherwise we need to perform the recursion: increase the code length, add a 0 in the least significant bit and do the left branch, then change that 0 to a 1 and do the right branch.
I would start by making compute_code_table recursive, this allows you to easily traverse the tree.
Secondly, it helps for every task or assignment to search online for some sources which explain (in pseudo-code or not) how to do your specific task. In this case, this yields the following explanation:
To generate a huffman code you traverse the tree to the value you
want, outputing a 0 every time you take a lefthand branch, and a 1
every time you take a righthand branch. (normally you traverse the
tree backwards from the code you want and build the binary huffman
encoding string backwards as well, since the first bit must start from
the top).
siggraph.org
In C, this could be implemented as such:
int compute_code_table_for_node(tree_t tree, node_t target_node, node_t current_node, int code_table) {
// Check for target
if ( current_node == target_node ) {
// Found target
return code_table;
}
// Check if end-node
if ( current_node->left == NULL && current_node->right == NULL ) {
// Is an end node
return -1;
}
// Try left
int left = compute_code_table_for_node(tree, target_node, current_node->left, code_table << 1 + 0);
// Try right
int right = compute_code_table_for_node(tree, target_node, current_node->right, code_table << 1 + 1);
// Find which path was taken
if ( left == -1 ) {
// Left path didn't find it, so it must be the right path:
return code_table << 1 + 1;
} else {
// Left path found it
return code_table << 1 + 0;
}
}
Then you only have to call compute_code_table_for_node(tree, node, tree->head, 0) for every node in the tree.
This piece of code won't work for your specific case, so you will have to rewrite it.

C: AVL tree search method for a certain value

I'm trying to write a function that searches in an AVL tree after a certain value and returns how many nodes contain the searched value.
Here it's my struct :
struct building{
int id;
char* streetName;
int streetNumber; };
And this is my search function :
void searchAfterStreetName(node* root, char* searchedStreet){
int counter = 0;
if (root){
if (strcmp(searchedStreet, root->info->streetName) < 0){
return searchAfterStreetName(root->left, searchedStreet);
}
else if (strcmp(searchedStreet, root->info->streetName) > 0){
return searchAfterStreetName(root->right, searchedStreet);
}
else{
if (strcmp(searchedStreet, root->info->streetName) == 0){
counter = counter + 1;
printf("%d\n", counter);
}
}
}
else{
printf("Not found");
}
}
Basically, what I want to do is to perform a search in an AVL Tree after the street name and everytime the searched value is contained in a node I will increment the value of the counter and print out the total value at the end of the search on the console.
The search function works well until I add the counter. It enters in an infinite loop. Please help !!!

Unable to create Adjacency List for an undirected Graph using C

I'm faced with a problem which I've been unable to tackle for quite some time.
I've been given a graph as follows,in a M x N matrix:
2 2
a b
a c
Note
I've interpreted the graph above as a matrix,only consisting of non-diagonal edges.
Here the first line represents values of M and N respectively.
The graph is only connected either along vertical,or adjacent direction,i.e.,up,down,left and right. diagonal edges not present.
In order to find the adjacency list of the graph(the desired output here):
a-b-c
b-a-c
c-a-b
Steps followed by me in the code:
1.Read M x N matrix into a 2D array.
2.Created a list of unique vertices of the graph as Unode[arrmax].
3.For each element of the matrix,if the character matches with an element of the unique vertices list,I've called the modify Adjacency List procedure that searches the neighbours of the concerned matrix vertex and populates/appends to the the Adjacency list if distinct nodes are found.
It takes as arguments, i,j,M,N,AdjList,number of elements in the list and makes the changes.
5.I've kept the list of nodes to be global for easy modification.
6.Next I intend to use the adjacency list produced to use in DFS procedure and find the DFS forest.
The Problem statement:
the input consists of a grid of size M X N. Each cell in the grid
contain a lower case letter of the English alphabet.In a natural way,
the cells are of two types: boundary cells and internal cells. Each
internal cell in the grid has four neighbours in one of the left,
right, top, down directions. A string of characters can be formed by
starting at any cell and traversing the grid through the neighbours.
You have to print all the possible strings subject to the following
constraints:
**No two characters in a string can be same
**No two strings can be same in the final output
**The strings should be printed in alphabetically sorted order.
INPUT:
First line contains two integers M and N
Next M lines contains N space separated characters each
OUTPUT:
Print all possible strings in sorted order and obeying the above constraints.
INPUT SIZE:
1 <= M, N <= 20
SAMPLE INPUT:
2 2
a b
a c
SAMPLE OUTPUT:
a ab abc ac acb b ba bc bca c ca cb cba
[UPDATE]:
Completely redesigned the code,used structures for the graph nodes,and one for handling indices.
Yet the result I'm getting:
a--b-a
b--a
a
c--a
My code[Relevant Portion]:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define ADJMAX 20
#define arrmax 400
typedef struct uniq_node{
char ch;
char AdjList[ADJMAX];
int numofelem;
int visited;
}unode;
unode Ulist[arrmax];
int uniq_tot=0;
typedef struct index
{
int i,j;
}Ind;
Ind indx;
int charcomp(char sch,char arr[],int arrlim);
void adjModify(unode*,char*,int,int,Ind);
int chIndex(int,int,int,int);
int main(void) {
int mvar,nvar;
char str[15],*token;
long integer;
/*To scan the values of M & N*/
scanf("%d %d\n",&mvar,&nvar);
int iter,iterv,jterv;
/*To create the character matrix of M x N*/
char cmat[mvar][nvar];
/*Initializing the unique nodes list*/
/*To read-in the matrix from the stdin:-A LOT OF HARD WORK*/
for(iterv=0;iterv<mvar;iterv++)
{
fgets(str,50,stdin);
jterv=0;
token=strtok(str," ");
while(token)
{
/*Assigning value to the character matrix*/
cmat[iterv][jterv]=*token;
/*Code to populate the list of unique elements*/
if(charcomp(*token,Ulist[uniq_tot].AdjList,uniq_tot)==3)
{
Ulist[uniq_tot].ch=*token;
uniq_tot++;
Ulist[uniq_tot].numofelem=1;
Ulist[uniq_tot].AdjList[0]=*token;
//Ulist[uniq_tot].visited=0;
}
jterv++;
token = strtok(NULL, " ");
}
}
/*To populate the adjacency lists */
char ch;
for(iterv=0;iterv<mvar;iterv++)
{
for(jterv=0;jterv<nvar;jterv++)
{
ch=cmat[iterv][jterv];
indx.i=iterv;
indx.j=jterv;
for(iter=0;iter<uniq_tot;iter++)
{
if(ch==Ulist[iter].ch)
break;
}
adjModify(&Ulist[iter],(char*)cmat,mvar,nvar,indx);
}
}
/*for(iter=0;iter<uniq_tot;iter++)
{
printf("%c",Ulist[iter].ch);
printf("\n%s\n",Ulist[iter].AdjList);
for(iterv=0;iterv<Ulist[iter].numofelem;iterv++)
{
printf("-%c",Ulist[iter].AdjList[iterv]);
}
printf("\n");
}*/
return 0;
}
int chIndex(int i,int j,int mvar,int nvar)
{
return (i>=0 && i<mvar && j>=0 && j<nvar);
}
void adjModify(unode* Unode,char* mat,int mvar,int nvar,Ind mind)
{
int idum,jdum;
if(chIndex(mind.i,mind.j-1,mvar,nvar))
{
idum=mind.i;
jdum=mind.j-1;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
if(chIndex(mind.i,mind.j+1,mvar,nvar))
{
idum=mind.i;
jdum=mind.j+1;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
if(chIndex(mind.i-1,mind.j,mvar,nvar))
{
idum=mind.i-1;
jdum=mind.j;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
if(chIndex(mind.i+1,mind.j,mvar,nvar))
{
idum=mind.i+1;
jdum=mind.j;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
}
/*Comparison routine*/
int charcomp(char fchar,char arr[],int ucindex)
{
int ivar;
for(ivar=0;ivar<ucindex;ivar++)
{
if(arr[ivar]==fchar)
return;
}
return 3;
}
I think you can skip creating individual nodes for every element in the 2D array. Having the 2D array implies a structured connectivity. When it starts getting large, traversing all these elements may become cumbersome.
My recommended approach would be the following:
Scan of the matrix and pull unique nodes. i.e. start with a scan and have the simple list a,b,c (you'll need to sort them).
Create a struct for each unique node consisting the number of paths you currently have and an array of char arrays to store each one in. i.e. char** myArray={{a},{ab},{abc},{ac},{acb}} would be the one for a (This is of course unknown when you start).
Loop through your unique nodes, and one by one find the location in the 2D array. Don't save them, just go through them one by one and do a scan function to look for all their paths.
The scan function should be recursive so it can go as far as it needs to while checking every possible path (recursive will help you check every direction at every node you traverse). Keep track of where you've been, and at ever step check that you have not already encountered that character.
When you can't go any further, make sure the string has not already been included, if it has continue to the next path, if not add it to the list.
this is my code in c++ without any library that can work in c but you just have to use in c printf instead of cout and instead of class use struct that's all. I also write code for breadth first traversal see below.
and include the header file also
// #include <stdio.h>
//#include<stdlib.h>
#include<iostream
using namespace std;
class Node {
public:
int data;
Node* next;
Node(int data) {
this->data=data;
this->next=NULL;
// cout<<"from node file"<<endl;
}
};
class Queue {
Node * head;
Node * tail;
int length;
public:
Queue() {
head=NULL;
tail=NULL;
length=0;
}
bool isEmpty() {
return length==0;
}
int size() {
return length;
}
int front() {
if(head==NULL) {
cout<<"Empty Queue"<<endl;
return 0;
}
return head->data;
}
void enqueue(int element) {
Node * newNode =new Node(element);
if(head==NULL) {
head=newNode;
tail=newNode;
}else{
tail->next=newNode;
tail=newNode;
}
length++;
}
int dequeue() {
if(head==NULL) {
cout<<"Empty queue"<<endl;
return 0;
}
int output= head->data;
Node * temp=head;
head=head->next;
temp->next=NULL;
delete temp;
length--;
return output;
}
};
class AdjList{
public:
Node * head;
AdjList() {
head=NULL;
//cout<<"from adlist"<<endl;
}
void add (int data) {
Node * newNode=new Node(data);
if(head==NULL) {
head=newNode;
}else {
Node* temp=head;
while(temp->next!=NULL) {
temp=temp->next;
}
temp->next=newNode;
}
}
};
class Graph{
public:
int v;
AdjList* adjList;
Graph(int v) {
this->v=v;
adjList=new AdjList[v];
}
void addEdge(int src, int dest) {
adjList[src].add(dest);
///for bidrectional add below code
//adjList[dest].add(src);
}
void print(){
for(int i=0;i<v;i++){
Node *temp = adjList[i].head;
cout << i << " -> ";
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
}
void bfs(int src) {
// using a queue also in this file how to add queue structure
Queue q;
bool* visited=new bool [v]{0};
q.enqueue(src);
visited[src]=true;
while(!q.isEmpty()) {
int node= q.front();
cout<<node<<" ";
q.dequeue();
Node *temp = adjList[node].head;
while(temp!=NULL){
if(!visited[temp->data]) {
q.enqueue(temp->data);
visited[temp->data]=true;
}
// cout<<"data "<<temp->data;
temp=temp->next;
/// how to traverse
}
}
}
};
int main(){
Graph g(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(3,4);
g.addEdge(4,5);
g.bfs(0);
// g.print();
return 0;
}

Returning error when traversing through a tree

I am trying to calculate the frequency of each node as I add them to the tree, instead of inserting a new element. For some reason when a comparing a new key to every element in the current tree, the if statement will not return 1 if they are both identical. BUT, the function will still add 1 to the frequency of the existing node. This is very puzzling to me, as I don't know why it would skip over the return 1, and continue searching through the tree. Thank you for help/advice in advance.
struct:
typedef struct node {
char* key;
struct node *left;
struct node *right;
int height;
int frequency;
}node;
This is my parsing function:
while(fgets(str, 100, textFile)) {
token = strtok(str," \n");
while (token != NULL)
{
key = strdup(token);
if((sameFrequency(root, key)==1)&&root!=NULL) {
printf("%s", key);
free(key);
token = strtok (NULL, " \n");
}
else {
root = insert(root, key);
//printf("%s\n", key);
free(key);
token = strtok (NULL, " \n");
}
}
if(ferror(textFile))
{
printf("you done messed up a-a-ron");
return(0);
}
}
Function to check the frequency of each node:
int sameFrequency(node *node, char* key) {
if (node != NULL) {
if(strcmp(key, node->key)==0){ //This statement is true in some cases, but will not return the 1
node->frequency = node->frequency+1;
printf("%d\n",node->frequency);
return 1;
}
sameFrequency(node->left, key);
sameFrequency(node->right, key);
}
else return 0;
}
Input would look something like this:
wrn69 flr830 flr662 flr830 flr830
flr231
The output (after printing in preOrder):
key: wrn69, frequency: 1
key: flr830, frequency: 3
key: flr662, frequency: 1
key: flr231, frequency: 1
key: flr830, frequency: 1
key: flr830, frequency: 1
I want this to print everything shown, but I don't want the same key to be inserted into the tree, just incremement its frequency by 1.
TL;DR: Function skipping over return value, but still running code in the if statement, have no idea whats wrong, even after debugging.
I'm not sure what your code is trying to do, since you do not define your node struct, however your function int sameFrequency(node *node, char* key) has an obvious bug: not all code paths return a value. Reformatting a bit for clarity, you can see that if strcmp(key, key)!=0 then the return is undefined:
int sameFrequency(node *node, char* key) {
if (node != NULL) {
if(strcmp(key, node->key)==0){
node->frequency = node->frequency+1;
printf("%d\n",node->frequency);
return 1;
}
else {
sameFrequency(node->left, key);
sameFrequency(node->right, key);
// Continue on out of the "if" statements without returning anything.
}
}
else {
return 0;
}
// NO RETURN STATEMENT HERE
}
My compiler generates a warning for this:
warning C4715: 'sameFrequency' : not all control paths return a value
Surely yours must be doing so as well, unless you intentionally disabled them. Such warnings are important, and should always be cleared up before finishing your code.
I'm guessing you want to do something like this, perhaps?
int sameFrequency(node *node, char* key) {
if (node != NULL) {
if(strcmp(key, node->key)==0){
node->frequency = node->frequency+1;
printf("%d\n",node->frequency);
return 1;
}
else {
int found;
if ((found = sameFrequency(node->left, key)) != 0)
return found;
if ((found = sameFrequency(node->right, key)) != 0)
return found;
return 0;
}
}
else {
return 0;
}
}
This clears the compiler warning.
Incidentally, the following if statement is probably in the wrong order:
if((sameFrequency(root, key)==1)&&root!=NULL) {
Since && statements in C execute left to right the following makes more sense:
if(root!=NULL && (sameFrequency(root, key)==1)) {

Resources