Cloning an n-ary tree in C - c

My structure maintains a parent, child and sibling pointers along with other data variables.
struct semNode {
struct semNode *child;
struct semNode *parent;
struct semNode *sibling;
int data;
int tag;
};
If I have to clone an exact tree of the same data type, how do I go about it in a recursive or an iterative manner.
I planned to take a recursive approach where I traverse the tree in an in order fashion and then add to the pointers but I'm not sure if that approach will work. Please help me out.

You can clone the tree with a simple recursive function:
struct semNode {
struct semNode *child;
struct semNode *parent;
struct semNode *sibling;
int data;
int tag;
};
void free_semNode(struct semNode *node) {
if (node) {
free_semNode(node->sibling);
free_semNode(node->child);
free(node);
}
}
struct semNode *clone_semNode(struct semNode *node, struct semNode *parent) {
struct semNode *new_node = malloc(sizeof(*new_node));
if (new_node != NULL) {
new_node->data = node->data;
new_node->tag = node->tag;
new_node->parent = parent;
new_node->child = NULL;
new_node->sibling = NULL;
if (node->child) {
new_node->child = clone_semNode(node->child, new_node);
if (new_node->child == NULL) {
free_semNode(new_node);
return NULL;
}
}
if (node->sibling) {
new_node->sibling = clone_semNode(node->sibling, parent);
if (new_node->sibling == NULL) {
free_semNode(new_node);
return NULL;
}
}
}
return new_node;
}
The whole tree can be cloned with clone_semNode(tree, NULL); and a subtree can be cloned with clone_semNode(node, node->parent); but both the original subtree and the cloned subtree will point to the same parent, which may cause difficulties for proper memory management.

Related

free(data) tries to free the wrong address

I have implemented a tree with the nodes looking like that:
typedef struct node_s {
struct node_s *parent;
struct node_s *left;
struct node_s *right;
data_t *data;
}node_t;
with *data pointing to a struct of data with a key which is used to sort the tree.
when I add a new node it looks like this:
node_t *add_Item (node_t *root){ //root is the root of the tree
...
data_t *new_data;
new_data = calloc(1,sizeof(data_t));
if(!new_data){
... //Error handling
}
root = insert_Node(root, new_data);
... //modifying new_data
return root;
}
node_t insert_Node(node_t *root, data_t *data){
... \\tree traversing and searching
if(root->data->key == data->key){ \\if the key is already in the tree it should be replaced
data_t *temp_data = root->data;
root->data = data;
free(temp_data); \\freeing the old data
}
...
return root;
}
What I don't understand is that the free(temp_data) doesn't work. Additionally the debug information doesn't make sense to me:
temp_data = 0x0000024C856DA950
root->data = 0x0000024C856DA9D0
and the debug message: HEAP[Program.exe]: Invalid address specified to RtlValidateHeap( 0000024C856D0000, 0000024C856DA920 )
The address in the error message is always 0x30 smaller than temp_data.
Just if it helps anybody: Windows 10, Visual Studio
EDIT- minimal reproducable example
#include <stdio.h>
#include <stdlib.h>
typedef struct data_s {
long key;
}data_t;
typedef struct node_s {
struct node_s* parent;
struct node_s* left;
struct node_s* right;
data_t* data;
}node_t;
node_t* init_node(data_t* data) {
node_t* new_node;
if ((new_node = calloc(1, sizeof(node_t)))) {
new_node->data = data;
fprintf(stderr, "node created\n");
}
return new_node;
}
node_t* insert_node(node_t* root, data_t* data) {
node_t* node;
if (root) {
if (root->data->key == data->key) {
printf("This item alreay exists!\n%ld will be replaced!\n", data->key);
data_t* temp_data;
temp_data = root->data;
root->data = data;
free(temp_data);
}
else if (root->data->key > data->key) {
node = insert_node(root->right, data);
root->right = node;
node->parent = root;
}
else {
node = insert_node(root->left, data);
root->left = node;
node->parent = root;
}
}
else {
root = init_node(data);
}
return root;
}
int main(int argc, char** argv) {
data_t* data;
node_t* root = 0;
while (1) {
if (!(data = calloc(1, sizeof(data_t)))) {
return(EXIT_FAILURE);
}
printf("What is the key for the new data?\n");
scanf("%ld", &(data->key));
root = insert_node(root, data);
//there would be more editing of data afterwards
}
return(EXIT_SUCCESS);
}
This seems to work but I don't know why this works and my other progam not.

Inorder traversal for binary search tree, shows some errors

This is the function which I am using for BST inorder Traversal
void inOrder(struct node* root)
{
if(root==NULL)
{
return;
}
inOrder(root->left);
printf("Key:%d,Pointer:%p\n",root->key,root);
inOrder(root->right);
}
The structure for the same is
struct node{
int key;
struct node *left,*right;
};
When I run the function I get two 0 extra elements for the following inserts:
root=insert(root,7);
insert(root,4);
insert(root,10);
insert(root,3);
insert(root,5);
insert(root,1);
insert(root,2);
insert(root,0);
insert(root,8);
insert(root,14);
insert(root,6);
insert(root,9);
insert(root,16);
insert(root,12);
insert(root,15);
insert(root,17);
inOrder(root);printf("\n");
And the insert function is given below:
struct node *insert(struct node * root,int ele)
{
struct node *temp=newNode(ele);
struct node *tree=root;
struct node *saver;
if(root==NULL)
{
root=temp;
}
else
{
while(tree!=NULL)
{
saver=tree;
if(ele<tree->key)
tree=tree->left;
else
tree=tree->right;
}
if(ele<saver->key)
{
saver->left=temp;
}
else
{
saver->right=temp;
}
}
return saver;
}
The output shows two 0s apart from the main elements, which I added. I have recently learned the Binary-Search-Tree, and I tried to implement it, Can someone please help me rectify this error. Thank you in advance
in insert
if(root==NULL)
{root=temp;
}
must be
if(root==NULL)
{
saver=temp;
}
because you return saver (not initialized in your version)
I suppose also in your main the code is not what you give but something like
struct node * root = NULL;
root=insert(root,7);
insert(root,4);
...
If I define newNode like that :
struct node * newNode(int ele)
{
struct node * r = malloc(sizeof(struct node));
r->key = ele;
r->left = r->right = NULL;
return r;
}
and I do the other changes :
pi#raspberrypi:/tmp $ gcc -g -pedantic -Wextra n.c
pi#raspberrypi:/tmp $ ./a.out
Key:0,Pointer:0xf04078
Key:1,Pointer:0xf04058
Key:2,Pointer:0xf04068
Key:3,Pointer:0xf04038
Key:4,Pointer:0xf04018
Key:5,Pointer:0xf04048
Key:6,Pointer:0xf040a8
Key:7,Pointer:0xf04008
Key:8,Pointer:0xf04088
Key:9,Pointer:0xf040b8
Key:10,Pointer:0xf04028
Key:12,Pointer:0xf040d8
Key:14,Pointer:0xf04098
Key:15,Pointer:0xf040e8
Key:16,Pointer:0xf040c8
Key:17,Pointer:0xf040f8
The full code is :
#include <stdio.h>
#include <stdlib.h>
struct node{
int key;
struct node *left,*right;
};
void inOrder(struct node* root)
{
if(root==NULL)
{return;}
inOrder(root->left);
printf("Key:%d,Pointer:%p\n",root->key,root);
inOrder(root->right);
}
struct node * newNode(int ele)
{
struct node * r = malloc(sizeof(struct node));
r->key = ele;
r->left = r->right = NULL;
return r;
}
struct node *insert(struct node * root,int ele)
{
struct node *temp=newNode(ele);
struct node *tree=root;
struct node *saver;
if(root==NULL)
{
saver=temp;
}
else
{
while(tree!=NULL)
{
saver=tree;
if(ele<tree->key)
tree=tree->left;
else
tree=tree->right;
}
if(ele<saver->key)
{
saver->left=temp;
}
else
{
saver->right=temp;
}
}
return saver;
}
int main()
{
struct node * root = NULL;
root=insert(root,7);
insert(root,4);
insert(root,10);
insert(root,3);
insert(root,5);
insert(root,1);
insert(root,2);
insert(root,0);
insert(root,8);
insert(root,14);
insert(root,6);
insert(root,9);
insert(root,16);
insert(root,12);
insert(root,15);
insert(root,17);
inOrder(root);printf("\n");
}

Code to insert node at last position in C programming language

I am writing a code on linklist in C programming language. When I am using an online compiler my code is working fine but when I am using Codeblock to run the code, the code is not working. I am posting the code kindly provide me solution. My code is to add node in a linklist on the last position.
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* Head;
void insert(int);
void print();
int main()
{
Head = NULL;
insert(2);
insert(3);
insert(4);
print();
return 0;
}
void insert(int a)
{
struct Node* temp1=(struct Node*)malloc(sizeof(struct Node));
temp1-> data = a;
temp1-> next = NULL;
if(Head == NULL)
{
Head = temp1;
return;
}
struct Node* temp = Head;
while(temp->next!= NULL)
{
temp = temp->next;
}
temp-> next = temp1;
}
void print()
{
struct Node* temp2=Head;
while(temp2 != NULL)
{
printf("%d \n", temp2->data);
temp2 = temp2->next;
}
return;
}
Here is how you can achieve what you want to do.
I suggest you to use a top-down approach when programming.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *next;
};
struct node *Insert(struct node *, int);
void Print_List(struct node *);
void Remove_List(struct node *);
int main(int argc, char **argv)
{
struct node *head;
head = NULL;
head = Insert(head, 10);
head = Insert(head, 20);
Print_List(head);
Remove_List(head);
head = NULL;
return 0;
}
struct node *Create_New_Node(int);
struct node *Head_Insert(struct node *, int);
struct node *Queue_Insert(struct node *, int);
struct node *Insert(struct node *, int);
void Print_List(struct node *);
void Remove_List(struct node *);
struct node *Insert(struct node *top, int elem)
{
if(top == NULL)
{
top = Head_Insert(top, elem);
}
else
{
top = Queue_Insert(top, elem);
}
return top;
}
struct node *Create_New_Node(int elem)
{
struct node *new_node;
new_node = (struct node *)malloc(sizeof(struct node));
if(new_node != NULL)
{
new_node -> info = elem;
new_node -> next = NULL;
}
return new_node;
}
struct node *Head_Insert(struct node *top, int elem)
{
struct node *new_node = Create_New_Node(elem);
if(new_node != NULL)
{
new_node -> next = top;
}
return new_node;
}
struct node *Queue_Insert(struct node *top, int elem)
{
if(top != NULL)
{
if(top -> next != NULL)
{
top -> next = Queue_Insert(top -> next, elem);
}
else
{
struct node *new_node = Create_New_Node(elem);
if(new_node != NULL)
{
top -> next = new_node;
}
}
}
return top;
}
void Print_List(struct node *top)
{
while(top != NULL)
{
printf("\nInfo : %d\tAddress : %u\tNext link address : %u\n", top -> info, top, top -> next);
top = top -> next;
}
return;
}
void Remove_List(struct node *top)
{
if(top != NULL)
{
Remove_List(top -> next);
top -> next = NULL;
free(top);
}
return;
}
Sample output :
Info : 10 Address : 39149584 Next link address : 39149616
Info : 20 Address : 39149616 Next link address : 0

How to clone a linked list with a head/tail implementation?

I have a linked list with the following struct implementation:
struct _node {
int item;
struct _node *next;
}
struct _list {
struct _node *head;
struct _node *tail;
int size;
}
I would like to write a function that clones the linked list and return a new list without modifying the original. I know how to do this using the _node implementation but I don't know how to do it using the _list implementation.
struct _node *cloneList (struct _node *head) {
if (head == NULL) return NULL;
struct _node *result = malloc(sizeof(struct _node));
result->item = head->item;
result->next = cloneList(head->next);
return result;
}
Here is what I have done:
struct _list *cloneList (struct _list *list) {
if (list == NULL) return NULL;
struct _list *result = malloc(sizeof(struct _list));
result->size = list->size;
result->head = list->head;
result->tail = list->tail;
return result;
}
but this is a buggy implementation because it doesn't actually clone the list because the pointers to head and tail are still the same.
You must combine your old function that does the actual cloning of the list elements with your new function that only clones the "management" part of the list.
To do this could modify your previous version a bit:
struct _node *cloneList (struct _list *list, struct _node *head) {
if (head == NULL) return NULL;
struct _node *result = malloc(sizeof(struct _node));
result->item = head->item;
if (head->next)
result->next = cloneList(list, head->next);
else
list->tail = result;
return result;
}
Then call it from within a new function
struct _list *cloneFullList (struct _list *list) {
if (list == NULL) return NULL;
struct _list *result = malloc(sizeof(struct _list));
result->size = list->size;
if (list->head != NULL) {
result->head = cloneList(result, list->head);
// tail will be set in cloneList as well.
}
else {
result->head = result->tail = NULL;
}
return result;
}

Binary Tree segmentation fault

Here i have written a code which inserts numbers in Binary tree. But it gives segmentation fault error.
And also it says " note: expected ‘struct tree *’ but argument is of type ‘struct node *’" in line 8.
Here is the code :-
#include<stdio.h>
#include<stdlib.h>
struct tree{
int data;
struct tree *left;
struct tree *right;
};
struct tree* insert(struct tree* node, int data)
{
if(!node){
node=malloc(sizeof(struct tree));
node->data=data;
node->left=node->right=NULL;
return node;
}
else {
if(data>node->data){
node->right= insert(node->right,data);
return node;
}
else{
node->left= insert(node->left,data);
}
return node;
}
}
printtree(struct tree* node)
{
if(node){
printf("%d",node->data);
}
printtree(node->left);
printtree(node->right);
}
main()
{
int i,n;
struct tree *NODE;
NODE= insert(NODE,5);
NODE= insert(NODE,3);
NODE= insert(NODE,8);
printtree(NODE);
}
You use if( node ) but better to use if( node != NULL )
You use if( !node ) but better to use if( node == NULL )
It make code more readable.
You have so many mistakes - so ... I make it in my way (my code formating, etc.).
printtree(node->left); printtree(node->right); was outside if( node != NULL ){} so it try to get NULL->left and NULL->right
Tested - code works.
#include<stdio.h>
#include<stdlib.h>
struct tree{
int data;
struct tree *left;
struct tree *right;
};
struct tree* insert(struct tree* node, int data)
{
if( node == NULL ) {
node = malloc( sizeof(struct tree) );
node->data = data;
node->left = node->right = NULL;
} else {
if( data > node->data ){
node->right = insert(node->right, data);
} else {
node->left = insert(node->left, data);
}
}
return node;
}
void printtree(struct tree* node)
{
if( node != NULL ){
printf("%d\n", node->data);
printtree(node->left);
printtree(node->right);
}
}
int main()
{
struct tree *NODE = NULL;
NODE = insert(NODE, 5);
NODE = insert(NODE, 3);
NODE = insert(NODE, 8);
printtree(NODE);
return 0;
}
The local variable: struct tree* node; is not initialized, so the if (!node) test will have undefined behavior. Unless you assign it something or use it to hold a malloc'd node, the expression in the else block tries to dereference an uninitialized pointer.
You should also get used to idea that a tree can be considered a 'recursive' structure, so any node is a tree, and the top-level tree is simply a node. There's no good reason for two separate types here.
You are still making the error of passing NODE by value. If you want to modify it, you must use a pointer to that pointer.
#include<stdio.h>
#include<stdlib.h>
typedef struct t
{
int data;
struct t *left;
struct t *right;
}tree;
tree* insert(tree **node, int data)
{
if(!(*node))
{
*node=malloc(sizeof(tree));
(*node)->data=data;
(*node)->left=(*node)->right=NULL;
return *node;
}
else
{
if(data>(*node)->data)
{
(*node)->right = insert(&((*node)->right),data);
return *node;
}
else
{
(*node)->left = insert(&((*node)->left),data);
return *node;
}
}
}
void printtree(tree *node)
{
if(node)
{
printf("%d",node->data);
printtree(node->left);
printtree(node->right);
}
}
void freeMemory(tree *node)
{
if(node)
{
freeMemory(node->left);
freeMemory(node->right);
free(node);
}
}
int main()
{
tree *NODE = NULL;
NODE= insert(&NODE,5);
NODE= insert(&NODE,3);
NODE= insert(&NODE,8);
printtree(NODE);
freeMemory(NODE);
return 0;
}
Link: http://ideone.com/OpZWiC

Resources