I have been having trouble with this linked list specifically it seems like my head pointer is not linking to the rest of my list and I am confused as to why it is not. Where I insert my head pointer by pointer by reference it is not connected to the linked list referenced in main. unless the list is not linked together in the main function and I am missing something.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
} Node;
typedef Node * Nodeptr;
void printlist (Node * head){
Node * n = head;
while(n != NULL){
printf("%d\n",n ->number);
n = n ->next;
}
}
void sumlist (Node * head){
Node * n = head;
int sum;
while(n != NULL){
sum = n ->number +sum;
n = n ->next;
}
printf("the total of all numbers in this list is %d",sum);
}
search(head){
}
int main(){
int i =0;
Nodeptr head=NULL;
if((head = malloc(sizeof(Node))) == NULL)
return 0;
head->number =rand()%50+50;
head ->next = malloc(sizeof(Node));
int n;
Nodeptr newnode = NULL;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
}
printlist(head);
sumlist(head);
return 0;
}
The error is that you are linking everything as next of head
head -> next = newnode;
You need to use a pointer that gets updated:
Nodeptr newnode = NULL;
Nodeptr last = head;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
last -> next = newnode;
last = last->next;
}
You should also change this:
head ->next = malloc(sizeof(Node)); // otherwise you will lose this element.
into
head ->next = NULL;
You execute these steps in a loop:
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
You are setting the newnode->next to point to null, and head->next to point to newnode.
This means, each time through the loop your head gets a new next, and that's it.
Effectively, each time you pass through the loop you drop the previous newnode on the floor, and link to a new one. At the end, you'll have head pointing to 1 node, and you'll have 98 nodes dropped on the floor that you can't reach.
You need to either maintain a "tail" pointer, or a copy of "head", and set head or tail or something to the most recent value of newnode. Then, you can set tail->next = newnode; tail = newnode; which will continually extend your list, rather than overwriting the same head->next each time.
Related
I am learning how to reverse a linked list recursively. I am confused with the last 4 lines.
node *reverse_linked_list_rec(node *head){
if (head->next==NULL){
return head;
}
node *smallans= reverse_linked_list_rec(head->next);
node *tail = head->next;
tail->next = head;
head->next = NULL;
return smallans;
}
Let's say I am reversing
1 2 3 NULL
by recursion, it reaches at 3 NULL and then by base case returns
2 3 NULL
here head=2, smallans=2 (not sure).
Why we are returning smallAns here and how it is changing?
smallans is a confusing variable name because it's actually the old tail being passed back through the list to become the new head which is ultimately returned to the caller.
Its next pointer changes when these lines execute in the parent function call:
// when head->next->next == NULL ...
node *tail = head->next; // ... `tail` points to the old tail (new head) ...
tail->next = head; // ... and this sets the new tail's next pointer to
// the old second-to-last node (new second node).
tail is a misleading name here--I associate a "tail" with a single node that terminates the entire list, not a previous node. new_prev or old_next seem more appropriate here depending on whether you want to name things relative to the node roles in the new list or the original list.
As a minor point, I recommend using if (!head || !head->next) to avoid a potential null pointer dereference.
I'd write the function as follows:
node *reverse_linked_list_rec(node *head) {
if (!head || !head->next) {
return head;
}
node *old_tail = reverse_linked_list_rec(head->next);
node *old_next = head->next;
old_next->next = head;
head->next = NULL;
return old_tail;
}
Aside from intellectual curiosity, recursion is a poor choice for linked list operations since it adds function call overhead, you can blow the stack and the logic isn't any easier to follow than iterative, in most cases.
Case in point, here's a complete example with an iterative version:
#include <stdio.h>
#include <stdlib.h>
struct node {
int id;
struct node *next;
};
struct node *make_node(int id) {
struct node *n = malloc(sizeof(*n));
if (!n) exit(1);
n->id = id;
n->next = NULL;
return n;
}
struct node *reverse_linked_list(struct node *head) {
struct node *prev = NULL;
for (struct node *curr = head; curr;) {
struct node *old_next = curr->next;
curr->next = prev;
prev = curr;
curr = old_next;
}
return prev;
}
void print_linked_list(struct node *head) {
for (; head; head = head->next) {
printf("%d->", head->id);
}
puts("");
}
void free_linked_list(struct node *head) {
while (head) {
struct node *tmp = head;
head = head->next;
free(tmp);
}
}
int main() {
struct node *head = make_node(1);
head->next = make_node(2);
head->next->next = make_node(3);
print_linked_list(head); // => 1->2->3->
head = reverse_linked_list(head);
print_linked_list(head); // => 3->2->1->
free_linked_list(head);
return 0;
}
As another minor point, since the linked list is being mutated I'd probably go for a header like void reverse_linked_list(struct node **head);. Otherwise, it seems too easy to call the non-void function, ignore the return value and wind up with a memory leak or crash when head in the caller scope (which has become a tail pointing to null) is dereferenced.
Basically what title says, Im trying to append (add to end of my list). my BuildList function takes in a size parameter that determines how many nodes the list will have. my problem is with my append function. So if I have 5 as my head, how do I fix my append function so that random numbers will be added after 5?
typedef struct Node
{
int value;
struct Node* next;
} Node;
Node *createNode( int num )
{
Node *ptr;
ptr = (Node *) malloc( sizeof( Node ) );
ptr->value = num;
ptr->next = NULL;
return ptr;
}
Node* append (Node* head, Node* newNode)
{
if (head == NULL)
return newNode;
while (head -> next != NULL);
head -> next = newNode;
return head;
}
Node* buildList (int size)
{
Node* newNode = (Node*) malloc (sizeof(Node));
Node* head = NULL;
for (int i = 0; i < size; i++)
{
Node* newNode = createNode (rand () % 10);
head = append (head, newNode);
}
return head;
}
Well, the most glaring issue is this
while (head -> next != NULL);
I believe you meant to write something like this
Node *tmp = head;
while (tmp -> next != NULL) {
tmp = tmp->next;
}
tmp->next = newNode;
You don't want to modify head here since you return it later in the function. If you didn't use tmp, head would always point to the penultimate node in the list.
You just need to modify your while, why do you have an empty instruction there? If the head is not NULL then you will never exit:
while (head -> next != NULL)
{
head = head -> next;
}
Ive looked around and I'm not sure if it has been posted or not, but I am trying to create two linked lists in C. When they are supposed to be 'empty' there are zeros. I am not sure where these zeros are coming from and its confusing the hell out of me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
int price;
int bookNumber;
struct node * next;
};
void addNode(struct node* pHead, int pPrice, int pBookNumber);
void displayList(struct node* pHead);
void removeNode(struct node* pHead, int pBookNumber);
int main()
{
struct node* head1;
head1 = (struct node*)malloc(sizeof(struct node));
head1 -> next = NULL;
addNode(head1, 10, 1234);
addNode(head1, 35, 9876);
displayList(head1);
printf("\n");
struct node* head2;
head2 = (struct node*)malloc(sizeof(struct node));
head2 -> next = NULL;
// addNode(head2,13, 8888);
displayList(head2);
}
void addNode(struct node* pHead, int pPrice, int pBookNumber)
{
struct node* newNode;
struct node* ptr;
newNode = (struct node*)malloc(sizeof(struct node));
newNode -> price = pPrice;
newNode -> bookNumber = pBookNumber;
newNode -> next = NULL;
ptr = pHead;
if(pHead -> next == NULL)
{
pHead -> next = newNode;
newNode -> next = NULL;
}
else
{
while((ptr -> next != NULL))
{
ptr = ptr -> next;
}
ptr -> next = newNode;
newNode -> next = NULL;
}
}
void removeNode(struct node* pHead,int pBookNumber)
{
struct node *current, *prev;
current = pHead;
/*searching list for the desired data*/
while((current -> bookNumber != pBookNumber))
{
prev = current;
current = current -> next;
}
/*fixing links between nodes*/
prev -> next = current -> next;
/*freeing memory*/
free(current);
/*removing from end of list*/
if((current -> next = NULL))
{
prev -> next = NULL;
/*freeing memory*/
free(current);
}
}
void displayList(struct node* pHead)
{
while(pHead != NULL)
{
printf("$%d, book# %d -> ", pHead -> price, pHead -> bookNumber);
pHead = pHead -> next;
}
printf("NULL");
}
I added two entries to the first list and didn't add anything to the second list...Here is the output:
$0, book# 0 -> $10, book# 1234 -> $35, book# 9876 -> NULL
$0, book# 0 -> NULL
Process returned 0 (0x0) execution time : 0.001 s
Press ENTER to continue.
the first noticeable problem is that you appear to have a dummy node
in the beginning of the list
struct node* head1;
head1 = (struct node*)malloc(sizeof(struct node));
head1 -> next = NULL;
but you start printing from head not from head->next
ie including dummy node.
head1 and head2 are uninitialized nodes which you allocate in main. You then add two nodes to head1 and none to head2. You then print the lists from head1 and head2. So they start by printing those uninitialized nodes.
You are starting your print loop from the head, and at the very beginning you allocate the memory for your head1 node. This causes it to print the price and number of the node with unassigned price and book number.
This can be solved by passing a pointer to a pointer (struct node **pHead) into your addNode function and adding a check if the head node is NULL.
newNode -> next = NULL;
ptr = pHead;
if(pHead -> next == NULL)
{
pHead -> next = newNode;
newNode -> next = NULL;
}
else
{
while((ptr -> next != NULL))
{
ptr = ptr -> next;
}
ptr -> next = newNode;
newNode -> next = NULL;
}
This code has another issue here. You are setting the next pointer of newNode to NULL at the start, and then again prior to exiting out of your if-else. This is not necessary, because you are always going to the very end of the list.
free(current);
/*removing from end of list*/
if((current -> next = NULL))
{
prev -> next = NULL;
/*freeing memory*/
free(current);
}
This code has an issue of freeing the current node, and then I assume you are attempting to check if you are at the very end of the list. However, you are using an assignment operator here. Use == for comparison, and were you to attempt removal of nodes, this would cause a segmentation fault, because you are trying to access the memory you had just freed.
Another thing worthy of mention here is that the current->next will be NULL in fact, if this is the end of the list, so this check is not even necessary and thus can be removed all together.
The code I have is adding nodes to head but I want them added to tail. I tried pointing head to next node to null but it stops since the next node is null
if(head==NULL)
{
head=node;
}
else
{
node->next=head;
node->prev=NULL;
head->prev=node;
head=node;
}
printf("The node is inserted to linked list succesfully. \n\n");
printMenu();
You need to keep a pointer to your list's tail, and then adding an element may look like:
node -> next = NULL;
tail -> next = node;
node -> prev = tail;
tail = node;
You need to go to the end of the list first:
if(head==NULL)
{
head=node;
}
else
{
struct nodetype *p = head;
while (p->next)
p = p->next;
p->next = node;
node->prev = p;
}
// Create new node
struct nodeType *newNode = (struct nodeType *)malloc(sizeof(struct nodeType));
// Singly-linked list and new node is end of the list so the next pointer is NULL
newNode->next = NULL;
if(head==NULL){
// If head is not assigned
head = newNode;
}
else{
// Assign the next pointer in the current node to the new node
current->next = newNode;
}
// Update the current pointer to point to the newNode
current = newNode;
where head and current is,
struct nodeType *head, *current;
If the current pointer does not point to the end of the list you can iterate over the list to the end with the following line and then start appending to the linked-list:
for(current = head; current->next != NULL; current = current->next);
Below is the code for inserting a node in a doubly linked list.
struct dllist
{
int data;
struct dllist *prev, *next;
};
void DLLInsert(struct dllist **head, int position, int data)
{
int k = 1;
struct dllist *temp, *newNode;
newNode = (struct dllist *)malloc(sizeof(struct dllist));
if (!newNode)
{
printf("Memory Error\n");
}
newNode->data = data;
if (position == 1)
{
newNode->next = *head;
newNode->prev = NULL;
*head = newNode;
return;
}
else
{
temp = *head;
while (temp->next != NULL && k < position - 1)
{
k++;
temp = temp->next;
}
if (temp->next == NULL)
{
temp->next = newNode;
newNode->prev = temp;
newNode->next = NULL;
}
else
{
newNode->prev = temp;
newNode->next = temp->next;
temp->next = newNode;
temp->next->prev = newNode;
}
}
}
I am getting somewhat confused in the underlying pointer operations being a newbie. A **head is passed onto the function to modify it. But in case when the position>1, a copy of *head(temp) is used to modify the list compared to the case when position==1. Can anybody explain me why is it so?
Thanks
When position > 1, temp is set to *head, and the code iterates temp through the linked list to the node at index position. Effectively, you are modifying the node at index position.
When position = 1, you are modifying the head node, so you don't need to iterate.
In the case of position==1, your new element will become the new head. You already know exactly where it is. Otherwise, you need to find the position.
temp = *head;
while (temp->next != NULL && k < position - 1)
This is used to iterate through the list until you find the element in the position you are going to insert at.
temp = temp->next;
The first element you assign to temp is head, but it is replaced with the next element in each iteration.