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);
Related
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*/
}
}
}
So I am trying to learn how to create a binary tree in C so far I have got this.
void addRecordsToTree(struct date *in, struct date *root) {
if (root == NULL) {
root = malloc(sizeof(struct date));
root = in;
return;
} else {
//Right side of tree processing
if (compareTwoRecords(in, root) >= 0) {
addRecordsToTree(in, root->right);
return;
} else {
root->right = in;
return;
}
//Left side of tree processing.
if (compareTwoRecords(in, root) < 0) {
addRecordsToTree(in, root->left);
return;
} else {
root->left = in;
return;
}
}
}
int main() {
loadFiles();
struct date treeRoot;
struct date *old = malloc(sizeof(struct date));
old = loadContentsIntoHeap(files[file2014]);
addRecordsToTree(&old[0], &treeRoot);
addRecordsToTree(&old[1], &treeRoot);
addRecordsToTree(&old[2], &treeRoot);
addRecordsToTree(&old[3], &treeRoot);
addRecordsToTree(&old[4], &treeRoot);
addRecordsToTree(&old[5], &treeRoot);
printRecord(7, old);
return 0;
}
The problem is when I check the state of the program in a debugger there is just jumbled up data. I think it could be a type problem somewhere, I find pointers are bit of a mind boggling concept. Im not sure if I have used them right. So here is a screen shot of the debugger.
As you can see at the bottom struct called 'old' is the data I am trying to make the tree out of and treeRoot is where I am trying to place it but I can't understand why I get these garbage values.
Also what is up with the memory address of left and right? am I not creating them correctly.
Another observation I made is when I watch my code in the debugger it seems that root is never == NULL and never gets set, why?
You just did the following:
int x = 2;
int y = x;
y = 5;
Is the second line here necessary or the third one. It is a totally illogical program if you did this. You just did the same thing with a pointer instead of integer. You firstly had a pointer to the base address of dynamic memory then you just overwrote it by initializing it the second time.
And, the iterative approach is far better in comparison to the recursive one. I share the code for inserting a node in a binary tree both recursively and iteratively:
void insert(struct node *temp, struct node **root)
{
while (*root != NULL)
root = (*root)->element < temp->element ? &(*root)->left : &(*root)->right;
*root = temp;
}
#if 0
/* Recursive approach */
void insert(struct node *temp, struct node **root)
{
if(*root == NULL)
*root = temp;
else if ((*root)->element < temp->element)
insert(temp, &(*root)->left);
else
insert(temp, &(*root)->right);
}
#endif
void create_node(int x, struct node **root)
{
struct node *temp = (struct node *) malloc(sizeof(struct node));
if (temp == NULL)
printf("Unable to allocate memory. Free some space.\n");
else
{
temp->left = NULL;
temp->right = NULL;
temp->element = x;
insert(temp, root);
}
}
int main()
{
struct node *root = NULL;
create_node(1, &root);
create_node(2, &root);
create_node(3, &root);
return 0;
}
I saw an additional Problem in your "addRecordsToTree"-function:
the IF-block of the
"//Right side of tree processing"
will allways return from the function. regardless wether the "IF"-Expression is true or false.
So your left-leaves of thew tree will never be inserted. So you probalby should check/debug that function.
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'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**