Store tree structured data to an array in C - c

I am trying to write a code to transverse a tree data structure using inorder transversal and store all the nodes onto an array.
I came up with this code below but it doesn't work, as the index of any previous recursion has already been passed on in the function.
int *inorderTransversal(AVLTreeNode *node, AVLTreeNode *array[], int index)
{
if (node == NULL)
return index;
inorderTransversal(node->left, array, index);
nodesArray[index] = node;
index++;
inorderTransversal(node->right, array, index);
return index;
}
I know I could possibly declare a static 'index' value inside the function, and it might work? But the downside is it makes 'index' stays in the memory for the entire duration of the program e.g.
void *inorderTransversal(AVLTreeNode *node, AVLTreeNode *array[])
{
static int index = 0;
if (node == NULL)
return;
inorderTransversal(node->left, array);
nodesArray[index] = node;
index++;
inorderTransversal(node->right, array);
return;
}
Or I could declare the index outside the function prior? e.g.
AVLTreeNode *array[tree->size];
int index = 0;
void *inorderTransversal(AVLTreeNode *node) {
if (node == null)
return;
inorderTransversal(node->left);
array[index] = node;
index++;
inorderTransversal(node->right);
}
Could someone help me to amend the code to include the 'index' increments inside the function without using static? Much appreciated!

Your first attempt was close. You want to pass in index as an int *. Then you can dereference it and update it.
void inorderTransversal(AVLTreeNode *node, AVLTreeNode *array[], int *index)
{
if (node == NULL)
return;
inorderTransversal(node->left, treeSize, index);
nodesArray[*index] = node;
(*index)++;
inorderTransversal(node->right, treeSize, index);
}
When you call this function, you pass the address of an int which has been initialized to 0. When the recursion ends it will hold the number of elements in the list.

Related

function to create array of post order binary tree

Im trying to create a recursive function that creates an array of post order integers from a given tree. This is the code:
//structure
typedef struct node
{
// Each node holds a single integer.
int data;
// Pointers to the node's left and right children.
struct node *left, *right;
} node;
// preorder_recursive is same as postorder_recursive(), except
// array[i] comes before the recursive calls
int *postorder_recursive(node *root)
{
int *array = malloc(sizeof(node) * node_count(root)); // node_count(root) counts nodes in binary tree
int i = 0;
if (root == NULL)
return 0;
while (root != NULL)
{
postorder_recursive(root->left);
postorder_recursive(root->right);
array[i] = root->data;
i++;
}
return array;
}
// returns 1 if pre order = post order, returns 0 otherwise
int compare(node *a, node *b)
{
int i = 0;
int *preArray, *postArray;
if (node_count(a) != node_count(b))
return 0;
preArray = preorder_recursive(a);
postArray = postorder_recursive(b);
for (i = 0; i < node_count(a); i++)
{
if (preArray[i] != postArray[i])
return 0;
}
free(preArray);
free(postArray);
return 1;
}
I am not entirely sure if the error is in this function, but if it is, it's probably due to the while loop. Any help would be great.
Edit: Ive included a lot more code. The purpose of this is to compare an array of post order to an array of pre-order.
Your function postorder_recursive() is creating a new array every time it is called. Furthermore, while(root != NULL) will loop forever for non-empty trees, if it weren't for the fact that it writes past the end of array and cause a segmentation fault at some point.
The solution is to split the function into one that creates the array, and then another function that recursively fills in the array, like so:
static size_t postorder_recursive(const node *root, int *array, size_t index) {
if (root == NULL)
return index;
index = postorder_recursive(root->left, array, index);
index = postorder_recursive(root->right, array, index);
array[index++] = root->data;
return index;
}
int *postorder_to_array(const node *root)
{
int *array = malloc(sizeof(node) * node_count(root));
postorder_recursive(root, array, 0);
return array;
}

Recursion in C with an array inside and an index

I am trying to do a function that receives the root of a supposed BST and I want to know if the tree in question is a BST.
Problem is that, I am traveling the tree with recursion and what I'm trying to do is, put inside an array all the values of the tree. I searched for how to put a BST into an array (AddtoArray), but the answers I've found on stackoverflow and other websites didn't solve my problem. (I got seg fault).
Here's what I got so far:
#include<stdio.h>
#include<stdlib.h>
struct node{
int key;
struct node *left, *right;
};
struct node *newNode(int item){
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
struct node* insert(struct node* node, int key){
if(node == NULL) return newNode(key);
if(key < node->key)
node->left = insert(node->left, key);
else if(key >= node->key)
node->right = insert(node->right, key);
return node;
}
void check(struct node *root, int *array, int i){
if(root != NULL){
check(root->left, array, i);
array[i++] = root->key;
//I tried to put i++, ++i in every place of this function (trying table test) and I realized it was too difficult to realize what to do here, I've found some functions returning an integer, the "i" in question, but they didn't work out for me.
check(root->right, array, i);
}
}
int main(){
int *array;
int array_length = sizeof(array)/sizeof(array[0]);
int i = 0;
array = (int*)malloc(array_length*sizeof(int));
struct node *root = NULL;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 20);
check(root, array, i);
printf("PRINTING ARRAY TO SEE IF THE BST IS IN ARRAY:\n");
for(i = 0; i < array_length; i++){
printf("VALUE: %d ", array[i]);
}
free(array);
return 0;
}
I'd like to solve this problem WITHOUT using global variables. How can I do it?
I see two issues in your check-code and its usage (did not analyse the other functions):
First, your malloc does not work as intended, because sizeof(array)/sizeof(array[0]) will always give the same (small) value, probably 1 or 2, regardless of the size of your BST.
So you'd rather introduce a function getting the number of nodes and use this as the length for your array:
int array_length = getNrOfNodes(root); // function to be coded
int *array = malloc(array_length*sizeof(int));
Second, you pass an integral value i by value to a recursive function. As it is passed by value, any i++ will take effect only for the respective function call instance, but will not influence the other ones on the call stack. So it is very likely that the keys of the complete left part of your tree (the one before i is altered), will be written to array[0].
I'd suggest to share the array index among the function instances on the call stack. This can be achieved by passing a pointer to some i rather than passing i-s value around. And I'd introduce an internal version that does the work, because the user of the function needs not to be aware of the helper variable i:
void writeToArray_internal(struct node *root, int *array, int *i){
if(root != NULL){
writeToArray_internal(root->left, array, i);
array[*i] = root->key;
(*i)++;
writeToArray_internal(root->right, array, i);
}
}
void writeToArray(struct node *root, int *array) {
int i=0;
writeToArray_internal(root, array, &i);
}
This line here
int array_length = sizeof(array)/sizeof(array[0]);
is wrong. This only works with pure arrays, because sizeof returns the amount
of bytes of the expression/variable. Your variable array is a pointer, so
sizeof array returns you the size of a pointer and it doesn't matter where the
pointer is pointer, you always will get the same size.
Besides trying to get the number of elements of the "array" before knowing how
many nodes you have, makes no sense, because the number of elements that you need in array depend on the number of nodes, so
you've got write a function that returns you the number of nodes and then
you can allocate space for array.
Also note that your check function is not correct either. The variable i is
local to every call of check so you are going to overwrite values of the
array, because the i++ of the n-th iteration only affects the i of the
n-the iteration, the n-1-th iteration does not see that change and thus
overwrites the value of the n-th iteration.
You'll need to pass i as a pointer as well:
void check(struct node *root, int *array, size_t *i, size_t maxlen) {
if(root != NULL){
check(root->left, array, i, maxlen);
if(*i < maxlen) // checking that you don't step out of bounds
array[(*i)++] = root->key;
check(root->right, array, i, maxlen);
}
}
and the you call it like this:
size_t i = 0;
size_t nodes_number = get_number_of_nodes(root); // you have to write this function
int *array = malloc(nodes_number * sizeof *array);
if(array == NULL)
{
// error handling
// do not continue
}
check(root, array, &i, nodes_number);

How to iterate through a list in c

Let "List" be a struct that represents a singly-linked list, i have the following function:
int List_contains(List node, const char* key) {
List *search;
search=node.next;
assert(search->key!=NULL);
return 1;
}
and List is the following struct:
typedef struct List { /*A new node*/
char* key;
void* value;
struct List *next;
} List;
The function "List_contains" should tell me if "key" is contained in the list or not. Problem is, i can't iterate through the list, and the line
assert(search->key != NULL);
throws a Segfault. How can i iterate through the list with what i have?
(Note: The function is, obviously, not "completed".)
Here is an example of a search I wrote a while back.
struct node
{
int data;
struct node *next;
};
int
search_list(struct node *head, int search)
{
if (!head)
{
fprintf(stderr, "Invalid head\n");
return 1;
}
struct node *temp = head;
while (temp)
{
if (temp->data == search)
{
printf("Found %d\n", search);
break;
}
temp = temp->next;
}
return 0;
}
int List_contains(List node, const char* key) {
List *search;
search=node.next;
assert(search->key!=NULL);
return 1;
}
so a lot to parse here...
Generally you would pass in a pointer to the node so that it isn't copied, but it is actually safe to do what you have done, in this instance, assuming no multithreaded shenanigans go on...
but in the future I would look for:
int List_contains(List* node, const char* key) {
next line you make a pointer without a value... which is fine, because you assign it the next line, but that could be condensed...
// List *search;
// search=node.next; # could easily become:
List *search = node.next;
now at this point you actually know if you are at the end of the list...
if(search == null)
{
return 0;
}
after that you need to do some sort of compare...
if (strcmp(key,search->key) == 0)
{
//found it;
return 1;
}
now you have code that will match the key against the first element of the list, so you would need to put the whole thing in a loop, each iteration swapping search with search->next and checking for null

Deleting a linked list node in a C function doesn't transfer to the calling function

I have this C function which is supposed to find an element in the linked list which has a specific "pos" value, delete it, and return the deleted value to the calling function. It does delete the item, but the change isn't saved in the calling function, the list just doesn't get updated with the new changes.
My list is structured like this:
struct list{
int value;
int pos;
struct list * next_ptr;
};
And my C function is this:
bool findDeleteElement(struct list **ptr, int position, int *value){
struct list** temp = ptr;
if(*ptr!=NULL){
while((*ptr)->pos!=position) ptr=&(*ptr)->next_ptr; //Gets to desired node
temp=ptr;
value=&(*ptr)->value; //saves the value
temp=&(*temp)->next_ptr; //Goes to next node
ptr=temp; //Makes ptr point to next node
return 1;
}
else return 0;
}
I just can't see what I'm missing.
I'm a beginner so I probably made a simple mistake.
Change to:
*value = (*ptr)->value; //saves the value
You only set value, the local copy of your external variable's address. This does not change your external variable in the calling function.
Some question:
What happens when position has the wrong value, such that no node is found?
What's the purpose of temp = ptr;, because temp is overwritten by temp = &(*temp)->next_ptr; without having been used.
Disclaimer: I've not further checked this function.
I kindly advise you to take on other code formatting rules that add more air and make things more readable. Here's an example:
bool findDeleteElement(struct list **ptr, int position, int *value)
{
struct list** temp = ptr;
if (*ptr != NULL)
{
// Gets to desired node
while((*ptr)->pos != position)
{
ptr = &(*ptr)->next_ptr;
}
temp = ptr;
*value = (*ptr)->value; // Saves the value
temp = &(*temp)->next_ptr; // Goes to next node
ptr = temp; // Makes ptr point to next node
return 1;
}
else
{
return 0;
}
}
You are confused about pointers and dereferencing and what & and * actually do. This is a normal state of affairs for a beginner.
To start with, ptr and value when used without * preceding them are function arguments and like automatic (local) variables they disappear when the function scope exits. So this statement:
value=&(*ptr)->value;
Merely changes the value of value i.e. what it points to and has no visible effect to the caller. What you need to change is the thing that value points to. i.e. the statement should look like this:
*value = (*ptr)->value;
The difference is that instead of setting value to the address of (*ptr)->value it sets what valuepoints to to (*ptr)->value.
You have a similar problem with ptr. But your problems are more subtle there because you are also trying to use it as a loop variable. It's better to separate the two uses. I'd write the function something like this:
bool findDeleteElement(struct list **head, int position, int *value)
{
struct list* temp = *head;
struct list* prev = NULL;
while(temp != NULL && temp->pos != position)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) // position not found
{
return false;
}
else
{
*value = temp->value;
// Now need to delete the node.
if (prev != NULL)
{
// If prev has been set, we are not at the head
prev->next = temp->next; // Unlink the node from the list
}
else // We found the node at the head of the list
{
*head = temp->next;
}
free(temp); // Assumes the node was malloced.
return true;
}
}
The above is not tested or even compiled. I leave that as an exercise for you.
int delete(struct llist **pp, int pos, int *result)
{
struct llist *tmp;
while ( (tmp = *pp)) {
if (tmp->pos != pos) { pp = &tmp->next; continue; }
*result = val;
*pp = tmp->next;
free(tmp);
return 1;
}
return 0;
}

General function for sorting a linked list

Is there any general user defined function that can be used to sort any given linked list, given that it has a pointer field and a data field.
The function should not swap the data between the nodes. The swapping should be done by using the pointers.
I found one online, but it is using a user defined function. I'm not allowed to use any other functions, but the bubble sort one.
We were asked not to initialize any new variables, other than temp structs within the function. So, i can't use integers or variables like swapped.
The one that i was using is as follows:
/* Bubble sort the given linked lsit */
void bubbleSort(struct node *start)
{
int swapped, i;
struct node *ptr1;
struct node *lptr = NULL;
/* Checking for empty list */
if (ptr1 == NULL)
return;
do
{
swapped = 0;
ptr1 = start;
while (ptr1->next != lptr)
{
if (ptr1->data > ptr1->next->data)
{
swap(ptr1, ptr1->next);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
}
while (swapped);
}
/* function to swap data of two nodes a and b*/
void swap(struct node *a, struct node *b)
{
int temp = a->data;
a->data = b->data;
b->data = temp;
}
Given that my linked list structure is as follows:
struct node
{
int data;
struct node *next;
};
For your case, you can use an edited version of the function that you have provided. The swap function was omitted in here.
//Sorting according to the data, ascending order
void bubbleSortLL(struct node *header){
struct node *temp1, *temp2, *temp3, *temp4, *temp5;
temp4=NULL;
while(temp4!=header->next)
{
temp3=temp1=header;
temp2=temp1->next;
while(temp1!=temp4)
{
if(temp1->data > temp2->data)
{
if(temp1==header)
{
temp5=temp2->next;
temp2->next=temp1;
temp1->next=temp5;
header=temp2;
temp3=temp2;
}
else
{
temp5=temp2->next;
temp2->next=temp1;
temp1->next=temp5;
temp3->next=temp2;
temp3=temp2;
}
}
else
{
temp3=temp1;
temp1=temp1->next;
}
temp2=temp1->next;
if(temp2==temp4)
temp4=temp1;
}
}
}
This will work by passing your specified list as an argument. Nevertheless, i don't understand why you can't use the swap function.
To get rid of the call of the swap function, replace the
function call with its content:
Instead of
swap(ptr1, ptr1->next);
write
int temp = ptr1->data;
ptr1->data = ptr1->next->data;
ptr1->next->data = temp;
To swap the elements and not the data, you need
to to track the previous element.
Here a suggestion for the swap of the elements(without maybe needed NULL checks)
previous->next = ptr1->next;
previous->next->next=ptr1;
Instead of ptr1=ptr1->next you need:
previous=previous->next;
ptr1=previous->next;

Resources