I have done insert a node and delete a tree with a tutorial. I test it and it works fine. However I can't understand why I need to pass by reference the root in insert, but in deleteAll just the pointer. Because I think that passing just the pointer its a value reference and then every change is only seen in the function.
typedef struct node{
int element;
struct node *left;
struct node *right;
}*tTree;
void insert(tTree *myTree, int element){
if(*myTree == NULL){
myTree= (tTree)malloc(sizeof(*myTree));
myTree->element = element;
myTree->left = NULL;
myTree->right = NULL;
}
else{
int treeElement = (*myTree)->element;
if( treeElement > element){
insert(&(*myTree)->left, element);
}
else{
insert(&(*myTree)->right, element);
}
}
}
void deleteAll(tTree myTree){
if(myTree != NULL){
deleteAll(myTree->right);
deleteAll(myTree->left);
free(myTree);
}
}
int size(tTree myTree){
if (myTree != NULL){
return 1 + size(myTree->right) + size(myTree->left);
}
else
return 0;
}
int main(){
tTree root = NULL;
insert(&root,3);
insert(&root,2);
insert(&root,4);
insert(&root,1);
printf("Number of nodes: %d\n",size(root));
deleteAll(root);
root = NULL;
printf("Number of nodes: %d\n",size(root));
return 1;
}
The deletion needs only the pointer for the statements it executes. It is not passing any information back to the calling function. However, your insertion function allocates if needed, and in that case must pass back the allocated pointer to the caller.
Related
There is a insert function which inserts in the tree recursively and display function for displaying the output.
the display() function is not displaying anything? Is there any error which I'm missing out?
please help
#include <stdio.h>
#include<stdlib.h>
typedef struct node
{ int val;
struct node *left;
struct node *right;
} node;
node *root=NULL;
void insert(node *root1,int value)
{
if(root==NULL)
{
node *temp=(node*)malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
root=temp;
root1=root;
return;
}
if(root1==NULL && root!=NULL)
{
node *temp=(node*)malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
root1=temp;
return;
}
if(root1->val >value)
{
insert(root1->left, value);
}
else
{
insert(root1->right, value);
}
return;
}
void display(node *root1)
{
if(root1==NULL)
{
return;
}
while(root1 !=NULL)
{
printf("%d\n", root1->val);
display(root1->left);
display(root1->right);
return;
}
}
int main()
{
insert(root,4);
insert(root,12);
insert(root,2);
insert(root,55);
display(root);
return 0;
}
Actually I'm new to programming and trying to implement trees. New suggestions are also welcome! Thank you
//EDIT
void sayHi(int* nums){
printf("hello");
printf("my address is %d \n",nums);
printf("val of nums[2] is%d\n", nums[2]);
nums[2]=30;
}
void someFunct(int* nums, int numsSize){
nums[2]=50;
sayHi(nums);
printf("address is %d\n",nums);
printf("val of nums[2] is%d\n", nums[2]);
}
input i.e., nums =[0,0,0,0,0]
output for above code is
hellomy address is 16
val of arr[2] is50
address is 16
val of arr[2] is30
Here we are passing sayHi(nums)?and it still works? Address of nums is same in someFunct and sayHi?
Does passing arg like someFunct(&ptr) only happens for structures?
Method 1
In this method the root pointer is declared as a local variable in main, and the address of the pointer is passed to the insert function. This allows the insert function to change the value of root in main.
The downside of this method is that it involves some of the nastiest syntax in the C language, with *s and &s sprinkled everywhere, along with an inordinate number of mandatory parentheses.
void insert(node **root, int value)
{
if (*root == NULL)
{
node *temp=malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
*root = temp;
}
else
{
if((*root)->val > value)
insert(&(*root)->left, value);
else
insert(&(*root)->right, value);
}
}
int main(void)
{
node *root=NULL;
insert(&root,4);
insert(&root,12);
insert(&root,2);
insert(&root,55);
display(root);
}
Method 2
Similar to method 1, this method also passes the address of the root pointer to the insert function, but to avoid some of the nasty syntax imposed by pointers-to-pointers, a local pointer item is used to access structure contents. This eliminates most of the *s and parentheses that were needed in method 1.
The downside of this method is that there are still &s sprinkled throughout the code, and it's easy to forget the line *root = temp; which updates the caller's pointer.
void insert(node **root, int value)
{
node *item = *root;
if (item == NULL)
{
node *temp=malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
*root = temp;
}
else
{
if(item->val > value)
insert(&item->left, value);
else
insert(&item->right, value);
}
}
int main(void)
{
node *root=NULL;
insert(&root,4);
insert(&root,12);
insert(&root,2);
insert(&root,55);
display(root);
}
Method 3
In this method, we return the new root pointer from the insert function. Thus, the first function parameter can be a simple pointer. This eliminates the nasty syntax found in method 1. There are fewer *s, absolutely no &s, and no inordinate parentheses.
The downside to this method is that the return value from the function needs to be assigned to the appropriate pointer. That results in a couple of assignments in the insert function (at the recursive calls), as well as assignments in main.
node *insert(node *root, int value)
{
if (root == NULL)
{
root=malloc(sizeof(node));
root->val=value;
root->left=NULL;
root->right=NULL;
}
else
{
if(root->val > value)
root->left = insert(root->left, value);
else
root->right = insert(root->right, value);
}
return root;
}
int main(void)
{
node *root=NULL;
root = insert(root,4);
root = insert(root,12);
root = insert(root,2);
root = insert(root,55);
display(root);
}
Boilerplate
Here's the code that when combined with the insert and main functions from any method above gives a complete set of code that can be compiled and run.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{ int val;
struct node *left;
struct node *right;
} node;
void display(node *root)
{
if(root != NULL)
{
printf("%d\n", root->val);
display(root->left);
display(root->right);
}
}
I am making Binary Tree is C. I know how to make Binary trees, that's not the issue over here.
I was using void pointers for root and all the elements that will be added to the tree.
When the binary tree is empty(root is pointing to NULL) I was simply making the root point towards the element that will be becoming the first element of the tree. But root wasn't getting the address of the element it should be pointing to. It was just a simple re-assignment.
As I mentioned above, I was trying simple re-assignment for void pointers to assign a new address for the root.
But when I was assigning the individual values of the element to the root, everything seemed worked perfectly fine.
Represent all the elements for the binary tree.
struct node {
void * key;
void * value;
struct node * left;
struct node * right;
};
First approach: simple re-assignment which fails
void map_tree_put(struct node * root, struct node * ele){
if(root==NULL) {
root = ele;
}
else {
/* some other code*/
}
}
Second approach: individual value assignment works fine
void map_tree_put(struct node * root, struct node * ele){
if(root==NULL) {
root->key = ele.key;
root->value = ele.value;
root->left = NULL;
root->right = NULL;
}
else {
/* some other code*/
}
}
Test code
int main() {
struct node * r = NULL;
int key = 10;
int value = 100;
struct node ele = {&key, &value, NULL, NULL};
map_tree_put(r, &ele);
printf("%d\n", *(int*)r->key); /* I get segmentation fault over here with the first approach but work fine with the second approach */
return 0;
}
Try
void map_tree_put(struct node ** root, struct node * ele){
if((*root)==NULL) {
(*root) = ele;
}
else {
/* some other code*/
}
}
and call from main should be
map_tree_put(&r, &ele);
This is about passing by value and reference.
That's because in this code:
void map_tree_put(struct node * root, struct node * ele){
if(root==NULL) {
root = ele;
}
else {
/* some other code*/
}
}
the function receives a copy of the pointers. To make the root pointer remember the re-assignment when the function returns, you need to do it like this:
void map_tree_put(struct node **root, struct node *ele){
if (root) {
if(*root==NULL) {
*root = ele;
}
else {
/* some other code*/
}
}
}
I know how pointers works.
I done similar problem with this way
deleteNode(struct node *head_ref, int key);
which is working and # here http://quiz.geeksforgeeks.org/linked-list-set-3-deleting-node/ they have used
deleteNode(struct node **head_ref, int key);
which also correct but is there reason to do so , will 1st one fails in any condition or is it bad way etc.
struct linked_list *deleteNode(struct linked_list *head, int key )
{
struct linked_list *prevNode,*current,*temp;
if( head==NULL)
return head;
if(head->data==key)
{
if(head->next==NULL)
{ free(head);
return NULL;
}
else
temp=head->next;
free(head);
return temp;
}
prevNode= head;
current=head->next;
printf("\n %d\n",(current->data));
while((current!=NULL) && (current->data!=key))
{ printf("\n here");
prevNode= current;
current=current->next;
}
if(current==NULL){
printf("\n element not present in list !\n");
return head;
}
if(current->next==NULL)
prevNode->next=NULL;
else
prevNode->next=current->next;
free(current);
return head;
}
head=deleteNode(head,key);
If you need to delete the head node, the first function won't work because you can't change the head node. The second function takes the address of the head node so it can be changed if need be.
The deleteNode function in the link contains the following:
struct node* temp = *head_ref, *prev;
// If head node itself holds the key to be deleted
if (temp != NULL && temp->data == key)
{
*head_ref = temp->next; // Changed head
free(temp); // free old head
return;
}
You can see here that it dereferences head_ref to change what it points to.
Let's forget the linked list and just think of updating a variable. There are two, equally valid ways to do it:
// 1. pass back
int update_int1(int val) {
return val + 1;
}
void caller1() {
int var = 1;
var = update_int1(var);
}
// 2. write back
void update_int2(int *val) {
*val += 1;
}
void caller2() {
int var = 1;
update_int2(&var);
}
This is easy to understand, so let's do the same thing with a pointer:
// 1. pass back
char *update_ptr1(char *ptr) {
return ptr + 1;
}
void caller1() {
char *ptr = malloc(10);
ptr = update_ptr1(ptr);
}
// 2. write back
void update_ptr2(char **ptr) {
*ptr += 1;
}
void caller2() {
char *ptr = malloc(10);
update_ptr2(&ptr);
}
It works exactly the same as for int! The key is there's always one more star if you want to write back, not pass back.
Which pattern you choose is up to you. The write-back approach is popular for linked lists.
When you write *b==>access contents of address contained in b.
When you write **c==>Access contents of contents of address contained in c.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node_{
int val;
struct node_ *left;
struct node_ *right;
}node;
node* insert(node* root,int val);
void inorder(node* root);
int main(void)
{
int i;
int item;
node* root = NULL;
srand(time(NULL));
for( i = 0; i < 10; i++)
{
item = rand()%15;
insert(root,item);
}
inorder(root);
return 0;
}
node* insert(node* root,int val)
{
if(root == NULL)
{
root = malloc(sizeof(node));
if(root!= NULL)
{
(root)->val = val;
(root)->left = NULL;
(root)->right = NULL;
}
else
printf("%d not inserted. No memory available.\n",val);
}
else
{
if(val < (root)->val)
{
insert((root->left),val);
}
if(val>root->val)
{
insert(((root)->right),val);
}
}
}
void inorder(node* root)
{
printf("%p",root);
if(root != NULL)
{
inorder(root->left);
printf("%3d",root->val);
inorder(root->right);
}
}
I am trying to create a binary tree and print out the values in order. However when I run this code the printf of the address prints out nil obviously meaning that my tree is empty so the printf and recursion below does not run. I cannot figure out where I went wrong, any suggestions or answers would be appreciated because I can't figure out why the root would be null after calling all of those inserts in main.
You pass root as a parameter to insert() (which says it is going to return something but doesn't). Inside insert you malloc your node and assign it to the local variable root. Nothing you ever do makes it out of the insert function.
Try returning something from insert, or using a global root.
As #JoshuaByer hints in the comments below, another approach is to make your insert method "pass by reference" so it can effectively modify what was passed to it.
void insert(node** rootp,int val)
{
if(*rootp == NULL)
{
*rootp = malloc(sizeof(node));
}
/* and so on */
If you don't understand what this is saying, google "Pass by reference in C" and I'm positive you'll get some good information.
In main() after declaring and initializing root (node* root = NULL;) you're never assigning it. In order to fix you should probably change the lin insert(root,item); to root = insert(root,item);.
Also note that although insert is defined as returning node * it does not return any value.
Here is my implementation of count:
int count(node *start)
{
static int l ;
node *current; /* Node for travelling the linked list*/
current=start;
if(current->next!=start)
{
l = 1 + count ( current->next ) ;
return ( l ) ;
}
else
{
return(1);
}
}
Here is a fragment of main function where I am calling it:
void main()
{
node *head;
printf ( "Length of linked list = %d", count ( head ) ) ;
}
Here is the structure:
struct cirdoublelinklist
{
struct cirdoublelinklist *prev; /** Stores address of previous node **/
int value; /** stores value **/
struct cirdoublelinklist *next; /** stores address of next node **/
};
/** Redefining list as node **/
typedef struct cirdoublelinklist node;
On running and trying to see the length of a list, it crashes with out of bound memory. Please help me with this, I have been working on this for a long time now.
Method to add the first node:
void initialize(node *start)
{
start->prev=start;
printf("\nEnter Value\n");
scanf("%d",&start->value);
start->next=start;
}
Method to add subsequent nodes after the location specified:
void insert_after(node *start)
{
int num; /* value for inserting a node */
int flag=0;
node *newnode; /* New inputed node*/
node *current; /* Node for travelling the linked list*/
newnode=(node*)malloc(sizeof(node));
printf("\nEnter the value after which you want to insert a node\n");
scanf("%d",&num);
init(newnode);
current=start;
while(current->next!=start)
{
if(current->value==num)
{
newnode->next=current->next;
current->next->prev=newnode;
current->next=newnode;
newnode->prev=current;
flag=1;
}
current=current->next;
}
if(flag==0 && current->next==start && current->value==num)
{
/*** Insertion checking for last node ***/
newnode->next=current->next; /* Start is being copied */
current->next->prev=newnode;
current->next=newnode;
newnode->prev=current;
flag=1;
}
if(flag==0 && current->next==NULL)
printf("\nNo match found\n");
}
Every time you call count, it has a new start, so current->next!=start is always comparing a node to its successor, which will only ever end if the list has length 1. What you most likely want to do is have two functions:
int count(node *start)
{
if(start == NULL)
return 0;
return count_helper(start, start);
}
int count_helper(node *start, node *current)
{
static int l;
if(current->next!=start)
{
l = 1 + count (start, current->next);
return ( l ) ;
}
else
{
return(1);
}
}
As others have mentioned, the static variable is not necessary. A better way of writing what I have called count_helper would be:
int count_helper(node *start, node *current)
{
if(current->next!=start)
{
return 1 + count (start, current->next);
}
else
{
return 1;
}
}
Finally, a more efficient implementation would be non-recursive:
int count(node *start)
{
if(start == NULL)
return 0;
node *current = start->next;
int c = 1;
while(current != start)
{
c++;
current = current->next;
}
return c;
}
Well, the problem is that you call the function in the main on a NULL pointer. Infact node *head; is declared but never assigned to something. So when you execute this line:
if(current->next!=start)
the program crashes because it will check for NULL->next that, obviously, doesn't exist.
You need to pass a pointer to start pointer in insert_after function
void insert_after(node **start)
instead of
void insert_after(node *start)
Otherwise you'll be just updating the local copy of *start.
Similarly for initialize
void initialize(node **start)
Put simply, the recursive calls don't know the original start node. You will need to add a second node* argument and pass the start node via it.
Here's a recursive solution that doesn't use static or helper variables:
int count(Node* head) {
// Base cases:
// 0 nodes
if (!head)
return 0;
// 1 node
if (head->next == next)
return 1;
// Keep a pointer to the node to be removed
Node* rest = head->next;
// Remove the node
head->next = head->next->next;
// Get the length of the new list
int result = 1 + count(head->next);
// Reconnect the node
head->next = rest;
return result;
}