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*/
}
}
}
Related
I am completely noob when I work with C. Very weak with pointers.
I have written a struct for a binary search tree. But when I try to access it from code it throws an error:
Process terminating with default action of signal 11 (SIGSEGV).
Bad permissions for mapped region at address 0x0`.
Here is my struct (in bst.h):
typedef struct tree Tree;
typedef struct tree{
Node * root;
Data * (*insert)(Tree * bst, Data value); //i get error in main when I make a call
Data * (*search)(Tree * bst, Data value);
void (*sort)(Tree *, Data *);
int (*compare)(Tree *t, Tree * copy);
Tree * (*clone)(Tree *t);
void (*delete)(Tree *bst);
void (*removeData)(Tree * bst, Data value);
}Tree;
Member functions (in bst.c):
Node * newNode(Data data, Node * parent) {
printf("inside new node\n");
Node * node = malloc(sizeof(Node));
if(parent!=NULL) {
if((parent->data.value)> data.value) {
parent->left=node;
}
else {
parent->right=node;
}
}
node->parent=parent;
node->left=NULL;
node->right=NULL;
node->data=data;
printf("after inside newNode\n");
return node;
}
Tree * newTree() {
Tree *tree;
tree = (Tree*)malloc(sizeof(Tree));
tree->root=NULL;
return tree;
}
// not getting inside in this function
Data * insert(Tree * tree, Data data) {
if(tree->root==NULL) {
tree->root = newNode(data,NULL);
} else{
return insertNode(tree->root,data);
}
return NULL;
}
Here is my main() that calls this function (in main.c):
Tree *bst = newTree();
assert(bst->root == NULL);
printf("1.");
for (i = 0; i < num_data; i++){
bst->insert(bst, (Data){d[i]});
printf("inside for loop");
}
I am not sure whether this is the right way to make function pointers as members of struct.
In newTree(), you are not assigning your functions to the function-pointers inside of the allocated tree struct.
Data* insert(Tree* tree, Data data);
// other function declarations as needed...
Tree* newTree() {
Tree *tree = (Tree*) malloc(sizeof(Tree));
if (!tree) return NULL;
tree->root = NULL;
tree->insert = &insert; // <-- ADD THIS!
// and do the same for your other function pointers...
tree->search = ...;
tree->sort = ...;
tree->compare = ...;
tree->clone = ...;
tree->delete = ...;
tree->removeData = ...;
return tree;
}
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.
here's my code , i don't understand the way of these pointers and & works in here.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct node {
int x;
struct node * left;
struct node * right;
} node;
void add_Element(node **,int);
node * getNewNode();
void main(){
node * root = NULL;
add_Element(&root,4687);
inorder_tra_recursive(root);
if(root == NULL) printf("still Nulll\n");
else printf("not null , working\n");
}
node * getNewNode(){
node * newNode = (node*)malloc(sizeof(node));
newNode->left = NULL;
newNode->right = NULL;
newNode->x = 0;
return newNode;
}
void add_Element(node ** root,int data){
*root = getNewNode();
(*root)->x = data;
// I did not write all function !! this is just a prototype and this is working
}
void inorder_tra_recursive(node * root){// looking for elements to print !
if(root==NULL)
return ;
inorder_tra_recursive(root->left);
printf("----%d----\n", root->x);
inorder_tra_recursive(root->right);
}
This is my code and here's the thing that i don't understand when i change my add_Element function to this.
void add_Element(node * root,int data){
if(root==NULL){
root = getNewNode();
root->x = data;
}else{
if(root->x <= data)
add_Element(root->right,data);
else
add_Element(root->left,data);
}
}
It doesn't add element to the tree . but if i do it like this
node * add_Element(node * root,int data){
if(root==NULL){
root = getNewNode();
root->x = data;
return root;
}else{
if(root->x <= data)
root->right = add_Element(root->right,data);
else
root->right = add_Element(root->left,data);
}
return root;
}
It works but what's the difference here why i have to return root to get results.
void main(){
node * root = NULL;
root = add_Element(root,48464);//random number
}
i can use it like this last one but i have to learn what causing this difference .
(difference: &root to node ** root // not have to return root , works !
root to node * root // have to return root otherwise not working)
Until this day i thought this 2 way were the same but apparently it's not . So , please help me , i'm going crazy over here :D . Anyhelp will be appreciated , thanks
Don't you mean this?
void add_Element(node ** root,int data){
if(*root==NULL){
*root = getNewNode();
(*root)->x = data;
}else{
if((*root)->x <= data)
add_Element(&(*root)->right,data);
else
add_Element(&(*root)->left,data);
}
}
In your first example, you are passing a pointer variable by reference (passing &root to the node ** root parameter). In the second, you are not (passing only the pointer value root, so the pointer variable root itself cannot be changed), so the new node object is lost - unless you return it, like you ended up having to do.
oh well , i always thought it was like this ,for exp:
#include
void main(){
int Arr[50];
random(Arr,50);
printf("%d", Arr[25]);
}
void random(int * Arr,int size){
int i;
for(i=0;i<size;i++)
Arr[i] = i+1;
}
** so here i'm passing a pointer by reference but when when it's a pointer what i'm passing , i have to use "&" to pass it by reference .
i believe my exp was correct , if it's not there's still some part that i'm missing**
I want to know the reason why do we use, pointer to pointer while inserting nodes in the binary tree.
But, While traversing the binary tree, we just refer the tree by simple pointer to the root node. But why while inserting node?
Can anyone help me in providing the reason or reference link to understand why it is pointer to pointer .
/*This program clears out all the three methods of traversal */
#include<stdio.h>
#include<stdlib.h>
/* Let us basically describe how a particular node looks in the binary tree .... Every node in the tree has three major elements , left child, right child, and and the data. */
struct TreeNode {
int data;
struct TreeNode *leftChild;
struct TreeNode *rightChild;
};
void inorder(struct TreeNode *bt);
void preorder(struct TreeNode *bt);
void postorder(struct TreeNode *bt);
int insert(struct TreeNode **bt,int num);
main()
{
int num,elements;
struct TreeNode *bt;
int i;
printf("Enter number of elements to be inserted in the tree");
scanf("%d",&num);
printf("Enter the elements to be inserted inside the tree");
for(i=0;i<num;i++)
{
scanf("%d",&elements);
insert(&bt,elements);
printf("\n");
}
printf("In Order Traversal \n");
inorder(bt);
printf("Pre Order Traversal \n");
preorder(bt);
printf("Post Order Traversal \n");
postorder(bt);
return 0;
}
int insert(struct TreeNode **bt,int num)
{
if(*bt==NULL)
{
*bt= malloc(sizeof(struct TreeNode));
(*bt)->leftChild=NULL;
(*bt)->data=num;
(*bt)->rightChild=NULL;
return;
}
else{
/* */
if(num < (*bt)->data)
{
insert(&((*bt)->leftChild),num);
}
else
{
insert(&((*bt)->rightChild),num);
}
}
return;
}
void inorder(struct TreeNode *bt){
if(bt!=NULL){
//Process the left node
inorder(bt->leftChild);
/*print the data of the parent node */
//printf(" %d ", bt->data);
/*process the right node */
inorder(bt->rightChild);
}
}
void preorder(struct TreeNode *bt){
if(bt)
{
//Process the parent node first
printf("%d",bt->data);
//Process the left node.
preorder(bt->leftChild);
//Process the right node.
preorder(bt->rightChild);
}
}
void postorder(struct TreeNode *bt){
if(bt)
{
//process the left child
postorder(bt->leftChild);
//process the right child
postorder(bt->rightChild);
//process the parent node
printf("%d",bt->data);
}
}
"I want to know the reason why do we use, pointer to pointer while inserting nodes in the binary tree. But, While traversing the binary tree, we just refer the tree by simple pointer to the root node. But why while inserting node?"
We actually don't even need the code to answer this. If you want to modify (write to) data in an external function in C, you need to have the address of the data. Just like:
main() {
int x = 2;
change_me(x);
printf("%d\n", x); // prints 2
}
void change_me(int x){
x++;
}
has no meaning. You're (in this example) getting a local copy of the vairable, any changes made to the value are only within the local scope. If you want those changes to propagate back to the calling function you need the address:
main() {
int x = 2;
change_me(&x);
printf("%d\n", x); // prints 3
}
void change_me(int* x){
(*x)++;
}
The same applies to pointers. In the example of a linked list, if I want to print the values, I need to traverse the tree and read data. I don't need to change anything so just the pointer will do. However if I want to modify the tree:
struct node{
int val;
sturct node* next;
};
main() {
struct node* head = malloc(sizeof(struct node));
head->val = 3;
insert_a_node_in_front(head);
}
insert_a_node_in_front(node * ptr) {
struct node* temp = ptr;
ptr = malloc(sizeof(struct node));
ptr->val = 5;
ptr->next = temp;
}
Well, guess what? We didn't actually just insert that node because head's value never changed. It's still pointing to the original node with a val==3. The reason is the same as before, we tried to change the value of the local copy of the parameter. If we want those changes to stick it needs the address of the original copy:
insert_a_node_in_front(&head);
}
insert_a_node_in_front(node ** ptr) {
struct node* temp = (*ptr);
(*ptr) = malloc(sizeof(struct node));
(*ptr)->val = 5;
(*ptr)->next = temp;
}
It's because of the first part of insert where it mallocs a new struct treenode. If you only passed in a struct treenode * this would look something like this:
int insert(struct TreeNode *bt,int num)
{
if(bt==NULL)
{
bt= malloc(sizeof(struct TreeNode));
(bt)->leftChild=NULL;
(bt)->data=num;
(bt)->rightChild=NULL;
return;
}
...
}
The problem with that would be that bt is local to insert so the bt in main would be unchanged. So you pass in a pointer to main's bt, which allows insert to change it.
a very good tips on using pointer is given here :
Try this basics : -
http://www.geeksforgeeks.org/how-to-write-functions-that-modify-the-head-pointer-of-a-linked-list/
I am getting a segmentation fault in the following code:
void print_stack(Node * root) {
while(root != NULL) {
// print the node
root = root->next;
}
}
Whereas this works:
int print_stack(Node ** root) {
Node * tmp = *root;
while(*root != NULL) {
// print the node
*root = (*root)->next;
}
*root = tmp;
}
The question is what am I doing wrong? For both functions I am passing the address of a Node pointer to the head of the list. I am trying to get the first function to work because it seems more ideal (no pointer allocation and no permanent change to root pointer).. thanks.
EDIT: I have posted the code here: http://dpaste.com/477724/
You passed the address of a Node pointer while the function takes just a Node pointer.
This:
print_stack(&main);
should be this:
print_stack(main);
Post all your code, showing the initialization of the linked list - seems like it should work.
class Node
{
public:
Node();
Node *next;
};
Node::Node()
{
next = NULL;
}
void print_stack(Node * root)
{
while(root != NULL)
{ // print the node
root = root->next;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Node *root = new Node();
Node *begin = root;
for (int i=0;i<10;i++)
{
Node *pNew = new Node();
root->next = pNew;
root = pNew;
}
print_stack(begin);
return 0;
}
There are compilation errors in the program you posted in the link.
Error1: int print_stack(Node * root) supposed to return an int. But it's definition isn't doing so.
Error2: In switch case, while calling print_stack, supposed to pass an argument of type Node* and not Node**. So, it should be print_stack(main);.
Error3: In case u of switch function, push functions arguments should be push(&main, &d);