I have to code some methods for a BST and I have some problems, let me explain.
I have the following structures :
struct node {
struct node *lChild;
struct node *rChild;
int value;
};
and
struct tree {
struct node *root;
};
along with the following functions :
struct tree* constructNewTree()
{
struct tree *T=malloc(sizeof(struct tree));
T->root=NULL;
return T;
}
and
struct node* constructNewNode(int i)
{
struct node *N=malloc(sizeof(struct node));
N->value=i;
N->lChild=NULL;
N->rChild=NULL;
return N;
}
And in my main I must call this (for example) :
int main()
{
struct tree *T;
T=constructNewTree();
insertKey(5,T);
insertKey(2,T);
insertKey(9,T);
return 0;
}
What I have to do is to create the function insertKey(int i, struct tree *T) using the recursion.
I wanted to do something like
void insertKey(int i, struct tree *T)
{
if (T->root==NULL) {
T->root=constructNewNode(i);
return;
}
else {
if (i<=T->root->value) {
T->root->lChild=constructNewNode(i);
else if (i>T->root->value) {
T->root->rChild=constructNewNode(i);
}
}
}
But it doesn't get very far, using the recursion would allow me to call insertKey again but I can't seem to use a node and a tree the same way.
Does anyone know how I could do that without altering the given structures?
Thank you very much.
Your insertKey takes a Tree as its argument. A Tree is only a pointer to the very top.
What I recommend you do is write a insertKey function that takes a Node for its argument. Also in this function, you have to check to see if there is another tree on the left/right child.
Currently you just construct a new node regardless of what is there. This will overwrite any previous insertions.
Related
typedef struct sTree {
int key;
struct sTree* p;
struct sTree* left;
struct sTree* right;
} sTree;
typedef sTree* tree;
void treeInsert(tree* root);
int main(){
srand((unsigned)time(NULL));
tree *root = NULL;
treeInsert(&root);
return 0;
}
void treeInsert(tree* root){
......
}
I don't understand why I have to pass '&' when calling tree insert (&root instead of root).
I've created a struct representing a node of binary tree and I declared a pointer to the root of the tree as 'tree*'.
So 'root' is double pointer. The function 'treeInsert' expects a double pointer. If I pass simply 'root' it takes the value (NULL) else with the operator '&' it points correctly to the root. The problem is:
passing '&root' I'm not passing a triple pointer? Can someone explain why?
regarding:
treeInsert(&root);
the need for the & is because the function: treeInsert() will need to modify the contents of the pointer. Without the & any assignment to that passed parameter will only change the parameter on the call stack and not the the contents of the parameter in main()
regarding:
tree *root = NULL;
Since tree is already a pointer, this results in (effectively)
tree ** root = NULL;
which will not accomplish what is needed.
A prime example of why a pointer should NOT be hidden in a typedef statement
the following proposed code is clear about what is wanted:
struct sTree
{
int key;
struct sTree* p;
struct sTree* left;
struct sTree* right;
};
typedef struct sTree tree;
void treeInsert(tree** root);
int main( void )
{
srand((unsigned)time(NULL));
tree *root = NULL;
treeInsert(&root);
return 0;
}
void treeInsert(tree** root)
{
tree *localroot = *root; // now 'localroot' is a pointer to the variable `root` in function: `main()`
......
}
Repeated Question:
Recently I'm reading Data Structure(Binary Search Trees), I understand recursion very well and can trace it as well.
I used an approach which always worked for me i.e write a program with a loop, then eliminate loop and write a recursive function, the base condition will be same as loop exit condition.
But when it comes to writing one without my loop method, am getting failed.
I wasn't able to write a recursive function to insert a node in Binary Search Tree.(Though I understood it properly by referring the solution).
Kindly guide me, How to improve it?
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *left;//To store the address of the left child
struct node *right;//To store the address of the Right child
};
struct node * root;
struct node *createnewnode(int x)
{
struct node *n=(struct node *)malloc(sizeof(struct node));
n->data=x;
n->left=NULL;
n->right=NULL;
return n;
}
void Insert(int x)
{
struct node *a,*b;
struct node *temp=root;
if(root==NULL)
root=createnewnode(x);
else
{
while(1)
{
if(x<=temp->data)
{
if(temp->left!=NULL)
temp=temp->left;
else
{
a=createnewnode(x);
temp->left=a;
break;
}
}
else
{
if(temp->right!=NULL)
temp=temp->right;
else
{
a=createnewnode(x);
temp->right=a;
break;
}
}
}
}
}
int main()
{
root==NULL;//Empty Tree
Insert(15);
Insert(10);
Insert(20);
Insert(25);
return 0;
}
Edit: Sorry for not posting the code previously.
This is the code I have written for inserting a node, now how do I convert this into a recursive method?
The recursive Insert always asks the following question: can I insert a node in the current root? If not because root is not null then I have to check whether I have to recurse on the left or right subtree and call Insert recursively.
Something like the following should be enough to give you an idea on how to do it
Node* Insert(Node* root, int x) {
if (root == NULL)
return createnewnode(x);
else
if (x <= root->data)
root->left=Insert(root->left);
else
root->right=Insert(root->right);
}
I've a nested struct like this
typedef struct Node_link {
struct Node_base *parent, *left, *right;
}Node_link;
typedef struct Node_base {
struct Node_link link[2];
}Node_base;
typedef struct Node{
struct Node_base base;
int size;
int *address;
}Node;
Node_base *head[2] ={NULL, NULL};
//head[0] stores int size and head[1] it's corresponding address
The node has right, left and parent link, all are nested e.g node->left->link.parent=node. I've to maintain all links(parent, left and right) and delete nodes.
I've tried a lot of cases and still missing some. Can someone tell me what all cases I need to use? Or refer me to some material? I searched a lot but no success.
My insert function is as follows:
Node_base * insert(Node_base *location, Node_base *n) {
if (head[0]==NULL)
head[0]=n;
else
{
if (location==NULL){
location=n;
return location;
}
else{
if(((Node *)n)->size < ((Node *)location)->size){
if(location->link[0].left==NULL)
{
location->link[0].left=n;
location->link[0].left->link[0].parent=location;
}
else
location->link[0].left=insert(location->link[0].left,n);
return location;
}
}
And I've the same nested insert function for head[1] which stores the size of node inserted in head[0].
It's hard to tell what's going on here. Your code doesn't look remotely like any BST implementation I've ever seen. Why the need for the Node_Link struct? The pointers in the Node structs should define what the links are. Why the parent pointer? That shouldn't be needed in a standard BST implementation. All you should need is:
struct node {
node *left;
node *right;
void *data;
int size;
};
struct bst {
node *root;
};
i have written a simple code to create and insert elements into a binary search tree, when i write the code in the following manner, the chaining doesn't seem to happen, can anybody help me understand what exactly is happening in the insert function ? I know the code to insert elements into a binary search tree, just curious to know why this one doesn't work.
#include <stdio.h>
#include<stdlib.h>
struct node {
struct node *left;
struct node* right;
int element;
};
void insert(struct node *node,int x) {
if(node==NULL) {
node=(struct node *)malloc(sizeof(struct node));
node->element=x;
node->left=NULL;
node->right=NULL;
} else {
if(x<node->element) {
insert(node->left,x);}
else {
insert(node->right,x);
}
}
}
void inorder(struct node *base) {
if(base!=NULL) {
inorder(base->left);
printf("%d ",base->element);
inorder(base->right);
}
}
int main(int argc, char *argv[]) {
struct node *base;
base=(struct node *)malloc(sizeof(struct node));
base->element=1;
base->left=NULL;
base->right=NULL;
insert(base,25);
insert(base,30);
inorder(base);
return 0;
}
if the insert function is written this way, it works but still doesn't work for creation of the first node of the binary search tree, confused :/
void insert2(struct node *node,int x) {
if(node==NULL) {
node=(struct node *)malloc(sizeof(struct node));
node->element=x;
node->left=NULL;
node->right=NULL;
} else {
if(x<node->element) {
if(node->left==NULL) {
node->left=(struct node *)malloc(sizeof(struct node));
node->left->element=x;
node->left->left=NULL;
node->left->right=NULL;
} else {
insert2(node->left,x);
}
} else {
if(node->right==NULL) {
node->right=(struct node *)malloc(sizeof(struct node));
node->right->element=x;
node->right->left=NULL;
node->right->right=NULL;
} else {
insert2(node->right,x);
}
}
}
}
When you pass a value to a function in C, you're using pass-by-value. What that means is the value gets copied into another variable which becomes local to the function.
void change(struct node *n) {
n = 42;
}
int main(void) {
change(NULL); // change can't change the value of NULL, can it?
}
Now take a look at your insert function... Suppose I call insert(NULL,42);, do you think insert is trying to change NULL? Or is it trying to change some local variable, which your main function can't see?
You know what needs to be done already... Either make your insert function use an extra level of pointer indirection as you've suggested in your comments, or return the root node from insert so that you can propagate the changes made by insert into the data structure stored in main (using the assignment = operator).
C is pass-by-value. When you pass something into a function's parameter, the function makes a copy of it. So when you pass a struct node pointer into the insert function, C makes a copy of that pointer.
What you did in main is first you made a struct node* base:
base --> struct node.
When you call insert(base, 25), C makes a copy of base. So now in your memory you have something like this:
basecpy ---> [struct node] <--- base
So in your insert, you are essentially doing
if(basecpy==NULL)
{basecpy=(struct node *)malloc(sizeof(struct node));
basecpy->element=x;
basecpy->left=NULL;
basecpy->right=NULL;}
Which does not change base in anyway at all - it just changes basecpy.
This can be solved by using double pointers:
void insert(struct node **node, int x) {
if (*node == NULL) {
*node = malloc(sizeof(*node));
(*node)->element=x;
(*node)->left=NULL;
(*node)->right=NULL;
} else {
if (x < (*node)->element) {
insert(&((*node)->left), x);
} else {
insert(&((*node)->right), x);
}
}
}
And then to use it, pass in the address of base.
insert(&base, 25);
Pointers can be tricky :)
ideone
I would like to get some help with the following question.
I have a struct Node and I want to change it's insides using some method.
and I want to print the content of the changed struct inside my main method.
how do I get the struct changed and see the changed value in my main without returning the node as a return value.
I guess it might be solved with passing the struct Node as a pointer and then editing it.
what is the right way to do so?
for example:
typedef struct Node{
struct Node * right;
struct Node * left;
void * data;
}Node;
void insert(void * element, Node* root){
if(root==NULL){
root=(Node*)malloc(sizeof(Node));
root->data=element;
}
}
int main(){
Node a;
int b=8;
insert(&b,&a);
printf("%d",*(int*)a.data);
return 0;
}
printf doesn't print 8 it prints 1 (i guess some garbage)
It sounds like you are trying to do the following
Create a struct in one method, say main
Pass it to a second method, say example
Have example modify the struct and have the results visible in main
If so then the way to do this in C is by passing the struct as a pointer to example.
struct Node {
int data;
struct Node* pNext;
};
void example(struct Node* pNode) {
pNode->data = 42;
pNode->pNext = NULL;
}
int main() {
struct Node n;
example(&n);
printf("%d\n", n.data);
}
EDIT
Responding to the updated question.
To see the result of a modification of a Node you must pass a Node*. And accordingly to see the result of a Node* modification you need to pass a Node**. Essentially you need to pass one more level of indirection than the value you want to mutate / return.
void insert(void* element, Node** ppRoot){
if (NULL == *ppRoot) {
Node* pTemp = malloc(sizeof(Node));
pTemp->data = element;
*ppRoot = pTemp;
}
}