Node pointer to current Node during mutile function call - c

I have declared a global pointer ptr and want that it should point to current node during different function call.
This is a sample code where I am creating a new node in fun1 and inserting in link list. In func2 I want to update the other members of newNode in linklist with a different value.
Currently I am traversing the link list to get the current Node or last Node which I dont want since during insertion of new Records already we have to traverse to reach to last Node thus storing the address of last Node.
But by doing the below I am not getting the proper values. Kindly someone suggest where I went wrong.
I am doing like this :
#include<stdio.h>
#include <stdlib.h>
struct Node
{
int data1;
int data2;
struct Node* next;
};
struct Node* head=NULL;
struct Node* ptr =NULL; /* Global pointer */
void insertNode(struct Node ** , struct Node* );
void fun1();
void fun2();
void fun1()
{
struct Node* ptr1 =NULL;
ptr1 = (struct Node*)malloc(sizeof(struct Node*));
ptr1->data1=1; /* intilaizing with some values */
insertNode(&head,ptr1);
}
void fun2()
{
/* Updating the current Node in the linklist with new value . */
ptr->data2=2;
}
void insertNode(struct Node ** head, struct Node* NewRec)
{
if(*head ==NULL )
{
NewRec->next = *head;
*head = NewRec;
ptr=*head;
}
else
{
/* Locate the node before the point of insertion */
struct Node* current=NULL;
current = *head;
while (current->next!=NULL )
{
current = current->next;
}
NewRec->next = current->next;
current->next = NewRec;
ptr=current->next;
}
}
int main ()
{
fun1();
fun2();
while(head!=NULL)
{
printf("%d", head->data1);
printf("%d",head->data2);
head=head->next;
}
return 0;
}

You made a classic mistake.
This is wrong:
ptr1 = (struct Node*)malloc(sizeof(struct Node*));
The allocated space here is sizeof(struct Node*) which is the size of a pointer (usually 4 or 8 bytes depending on the platform). But you need to allocate space for the whole struct Node structure, whose size is sizeof(struct Node).
So you simply need this:
ptr1 = (struct Node*)malloc(sizeof(struct Node));
BTW: in C you don't cast the return value of malloc so you actually should write this:
ptr1 = malloc(sizeof(struct Node));

Related

linked list displays extra zero item

I am creating a list with 3 elements but when I print the list , it shows an extra zero element.I can't figure where this comes from.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
int data;
struct node *next;
} node;
void Push(struct node **head, int data)
{
struct node *newNode = (struct node*) malloc(sizeof(struct node));
newNode-> data = data;
newNode-> next = *head;
*head = newNode;
}
void createList(struct node **head)
{
Push(head, 1);
Push(head, 2);
Push(head, 3);
}
void printList(struct node *head)
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("%d \n", ptr-> data);
ptr = ptr-> next;
}
return;
}
int main() {
struct node *head = NULL;
head = (struct node*) malloc(sizeof(struct node));
createList(&head);
printList(head);
printf("\n");
return 0;
}
Output:
3
2
1
0
It's actually displaying an indeterminate value. Because right here:
head = (struct node*) malloc(sizeof(struct node));
Is where you create the first real node, which everything is inserted before. You are (un)lucky the run-time is zeroing out the memory for you. Because that's the only thing stopping you from accessing some random address. In general, the content of the memory returned from malloc is indeterminate.
Remove that line and you'll see only the items added by createList. Plus your program will be with well defined behavior.
You have four nodes in your list: the original that you malloc in "main()” plus the three added via "Push" in "createList". Presumably the data in the extra one is zero because you haven’t set it in main (although I’d expect it to be gibberish since it’s allocated memory but not cleared).

Issues with C linked list

I have a function to insert a struct into a queue implemented as a linked list.
I am passing an array element as the process.
void q_insert (queue *q, process p) {
printf("before insert attemp\n");
if (q->head == NULL) {
q->head = malloc(sizeof(struct Node));
q->head->process = &p;
q->head->next = NULL;
q->tail = q->head;
printf("After insertion into empty\n");
}
else {
struct Node* temp;
temp = malloc(sizeof(struct Node));
temp->process = &p;
temp->next = NULL;
q->tail->next = temp;
q->tail = temp;
printf("after insertion into non empty\n");
}
}
When I call this function the first time on an empty list, it seems to work fine. When I try to insert a second item it adds the second entry, but it also replaces the first entry with a copy of the second. These are the structs used:
typedef struct {
char name[80];
int arrival_time;
int execution_time;
int priority; // high number is high priority
} process;
struct Node{
process* process;
struct Node* next;
} q_node;
typedef struct {
struct Node* head;
struct Node* tail;
} queue;
C only supports pass by value and when you pass the address of variable through pointer, the copy of the address that variable passes,and in your insert function When q == NULL, you're allocating memory and assigning that memory to q, but this won't change q outside your function: only the copy of q inside your function will be changed.
In order to change what the argument q points to, and have those changes reflected outside your function, you'll need to pass a pointer to a pointer like this:
void q_insert (struct node **q, process p) {
if (q->head == NULL) {
struct node* new_head = (struct node*)malloc(sizeof(struct node));
new_head->head->next = NULL;
.
.
*q=new_head;
.
.
}

Connect preorder predecessor with its successor in a binary search tree

Actually in an interview i was asked to write a code through which every node in a binary search tree is having a extra pointer namely "next" we have to connect this pointer of every node to its pre order successor ,can any one suggest me the code as i was not able to do so. the tree nodes has above structure :-
struct node {
int data ;
struct node *left,*right;
struct node *next; //this pointer should point to pre order successor
};
thank you .
Cracked the the solution thanks to you guys ,below is the whole code written in c :-
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left,*right,*next;
};
struct node* getNode(int data)
{
struct node* temp=(struct node*)malloc(sizeof(struct node));
temp->left=temp->right=NULL;
temp->data=data;
return temp;
}
void insert(struct node**root,int data)
{
if(!*root)
{
*root=(struct node*)malloc(sizeof(struct node));
(*root)->left=(*root)->right=NULL;
(*root)->data=data;
}
else if(data<(*root)->data)
insert(&((*root)->left),data);
else if(data>(*root)->data)
insert(&((*root)->right),data);
}
struct node* preorderSuccessor(struct node* root,struct node* p)
{
int top,i;
struct node *arr[20];
if(!root || !p)
return NULL;
if(p->left)
return p->left;
if(p->right)
return p->right;
top=-1;
while(root->data!=p->data)
{
arr[++top]=root;
if(p->data<root->data)
root=root->left;
else
root=root->right;
}
for(i=top;i>=0;i--)
{
if(arr[i]->right)
{
if(p!=arr[i]->right)
return arr[i]->right;
}
p=arr[i];
}
return NULL;
}
void connect(struct node* parent,struct node *r)
{
if(r)
{ connect(parent ,r->left);
r->next = preorderSuccessor(parent,r);
connect(parent,r->right);
}
}
int main()
{
struct node* root=NULL,*temp=NULL;
int arr[]={10,11,2,3,9,8,4,5},size,i;
size=sizeof(arr)/sizeof(arr[0]);
for(i=0;i<size;i++)
insert(&root,arr[i]);
connect(root,root);
struct node *ptr = root;
while(ptr){
// -1 is printed if there is no successor
printf("Next of %d is %d \n", ptr->data, ptr->next? ptr->next->data: -1);
ptr = ptr->next;
}
return 0;
}
As Eugene said: So traverse the tree with preorder traversal and connect. To do that, you need to know which node, if any, you visited last.
You can do that with the usual recursive approach by passing a reference to the previous node. This must be the address of a variable that is valid throughout the recursion, because the previous node is not necessarily closer to the root. You could use a global variable, but a variable created in a wrapper function may be better:
void connect_r(struct node *node, struct node **whence)
{
if (node) {
if (*whence) (*whence)->next = node;
*whence = node;
connect_r(node->left, whence);
connect_r(node->right, whence);
}
}
void connect(struct node *head)
{
struct node *p = NULL;
connect_r(head, &p);
if (p) p->next = NULL;
}
The pointer p in connect, whose address is passed to the recursive function connect_r holds the node whose next pointer should be updated next. The update doesn't happen on the first visited node. and the next member of the last visited node must explicitly be set to NULL after the recursion.
Alternatively, you can connect the nodes iteratively by using a stack:
void connect(struct node *head)
{
struct node *p = NULL;
struct node **prev = &p;
struct node *stack[32]; // To do: Prevent overflow
size_t nstack = 0;
if (head) stack[nstack++] = head;
while (nstack) {
struct node *node = stack[--nstack];
*prev = node;
prev = &node->next;
if (node->right) stack[nstack++] = node->right;
if (node->left) stack[nstack++] = node->left;
}
*prev = NULL;
}
The connected next pointers are a snapshot of the current tree. Insertions, deletions and rearrangements of nodes will render the next chain invalid. (But it can be made valid again by calling connect provided that the tree's left and right links are consistent.)

Passing a linked list head through a function as address in C

I have a question regarding passing the head of a linked list in C through a function. So the code goes something like this:
#include <stdio.h>
//Defining a structure of the node
struct node {
int data;
struct node* next;
};
void insert (struct node* rec, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
rec = temp; // head and rec is now pointing to the same node
}
void print(struct node* rec){
printf("%d", rec->data); //error occurs here
puts("");
}
main(){
struct node *head = NULL; //head is currently pointing to NULL
insert (head, 5); //Passing the head pointer and integer 5 to insert()
print(head);
}
So as you see, the error occurs when I tried printing rec->data. Why did the error occur? I thought since the pointer rec and head are all pointing to the same node in the heap, there should not be any problem?
Thank you.
You could pass a struct node** as suggested by #sje397.
However, I would suggest the following design (which, in my opinion is easier to reason about too):
/* returns the new head of the list */
struct node *insert (struct node* current_head, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = current_head;
return temp;
}
and use it like
head = insert(head, 5);
In this case I would also rename the function something like push_front.
Just for completeness, I think #sje397 meant something like the following (Typical linked list code rewritten again and again by every C programmer...):
void insert(struct node **head, int x) {
struct node* new_head = (struct node*)malloc(sizeof(struct node));
new_head->data = x;
new_head->next = *head;
*head = new_head;
}
In C there is no pass by reference.
Your insert function isn't inserting a node in the list, its just changing the node which the head points to. Because of temp->next = NULL the list will always contain two nodes.
Another error is that you're just modifying a local copy of the head node.
To fix this You have 3 choices:
-You can make the head node global
-You can pass a pointer to the head node(pointer to pointer) to the function.
-You can return the modified head node by the function.
Redefine the insert function to:
void insert (struct node** rec, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
*rec = temp; // head and rec is now pointing to the same node
}

C Linked lists with global variables

Hi I'm new to C and I'm struggling to get a linked list working I'm having to use global variables because I can't change the parameters of the function that is being called. I declare the struct and two global pointers to keep track of the root address and last address like this.
struct node {
char* pointer;
struct node *next;
};
struct node** rootNode;
struct node** lastNode;
Then inside the function I malloc a new struct and try to setup the first node in the list. To try and save the location of this node I think I'm assigning the global pointer lastNode to the pointer of root.
struct node *root = malloc(sizeof(struct node));
...
root->pointer=ptr;
root->next = 0;
rootNode = &root;
lastNode = &root;
Then I try to add aditional nodes by mallocing another node and then linking the previous node using the address stored in my lastNode pointer.
struct node *newNode = malloc(sizeof(struct node));
newNode->pointer=ptr ;
(*lastNode)->next = newNode;
newNode->next = 0;
lastNode = &newNode;
However this doesn't really seem to work. When I run the following the program matches the first two items in the list but then returns null for all nodes after that. I've been stuck on this for 2 days now and any help would really be appreciated :)
struct node* test;
test = (*rootNode);
enter code here
while (test) {
if (test->pointer == ptr) {
printf("MATCH!!");
notFound = 0;
break;
}
else {
test = test->next;
}
}
EDIT A couple of people have asked me to supply some more code. This is the function in which I would like to create the linked list. It's called multiple times while my program is running and I'm trying to add a new node to my linked list every time it gets called. I've also included the global variables at the top.
struct node** rootNode;
struct node** lastNode;
int firstRun = 1;
struct node {
char* pointer;
struct node *next;
};
void malloc(size_t sz) {
size_t maxSize = (size_t)-1;
char * payloadPtr = NULL;
if (sz > maxSize - sizeof(struct node)+sizeof(int)) {
return ptr;
}
if (firstRun) {
struct node *root = malloc(sizeof(struct node));
ptr = malloc(sizeof(size_t)+sz);
if (ptr == NULL) {
return ptr;
}
memcpy(ptr, &sz, sizeof(int));
payloadPtr = ptr+1;
root->pointer=payloadPtr;
root->next = 0;
rootNode = &root;
lastNode = &root;
firstRun = 0;
}
else {
struct node *newNode = malloc(sizeof(struct node));
ptr = malloc(sizeof(size_t)+sz);
if (ptr == NULL) {
return ptr;
}
memcpy(ptr, &sz, sizeof(int));
payloadPtr =ptr+1;
newNode->pointer= payloadPtr;
(*lastNode)->next = newNode;
newNode->next = 0;
lastNode = &newNode;
}
return payloadPtr;
}
There's a little clarification about changing the parameters into a function. In C you can only pass by pointers on function calls so if you want to modify the value of a struct node - you pass it like struct node * in the function. Similarly if you want to change the value of a struct node * in the function (as in allocate it or delete it) you may want to pass it like struct node **.
Your function prototype will probably have to look like this:
void addNode(struct node** root, char* value)
But you can also make that root node a local and also just a struct node * instead of struct node **. And then simply call it like:
addNode(&root, value);

Resources