Inserting into a linked list not working properly - c

I want to add a insert method for my linked list that would insert onto what's already in the linked list (append values).
Here's my code now:
struct node {
char value;
struct node *next;
};
typedef struct node item;
void main() {
InsertChar('a');
InsertChar('b');
InsertChar('c');
}
void InsertChar(char s) {
item *curr, *head;
head = NULL;
curr = (item *)malloc(sizeof(item));
curr->value = s;
curr->next = head;
head = curr;
while(curr) {
printf("%c", curr->value);
curr = curr->next;
}
printf("\n");
}
The problem is that in the console it prints
a
b
c
I need it to print something more like
a
ab
abc
After calling the 3 InsertChar methods in main().
How can I do this?

Your problem is that the head is declared locally in the function, and when you leave the function, you loose it. When you come to the function again, you create it from scratch, etc.
So you need to pass head as an argument to your InsertChar function.
Also, if you want to see a, ab, abc output, you need to add elements to the tail of your list, rather than to the head as you do it now. In order to achieve that, you either need to store a separate pointer for tail or every time traverse to the last element.

You have to be keeping track of the head of your list. E.g.:
struct node {
char value;
struct node *next;
};
typedef struct node item;
item* head = NULL;
item* curr = NULL;
void InsertChar(char s) {
item* c = (item *)malloc(sizeof(item));
c->value = s;
c->next = NULL;
if (head)
curr->next = c;
else
head = c;
curr = c;
for (c = head; c; c = c->next)
printf("%c", c->value);
printf("\n");
}
void main() {
InsertChar('a');
InsertChar('b');
InsertChar('c');
}
This outputs:
a
ab
abc

There are two problems :
The list's is redefined each time the function is invoked.
you should start from the head of the list when you access the list's elements
This should fix your problem :
struct node {
char value;
struct node *next;
};
typedef struct node item;
item * head = NULL; // global
void main() {
InsertChar('a');
InsertChar('b');
InsertChar('c');
}
void InsertChar(char s) {
item *curr, *temp;
curr = (item *)malloc(sizeof(item));
curr->value = s;
curr->next = head;
head = curr;
temp = head;
while(temp) {
printf("%c", temp->value);
temp = temp->next;
}
printf("\n");
}

Related

Removing element from linked list (if found) without deleting it from memory

I have understood how deletion works in linked list, however the implementation is harder than I thought.
I have written this below but it is not working sadly
My node:
struct DLinkedList
{
double sensorData;
struct DLinkedList *prev;
struct DLinkedList *next;
};
And this is my delete function:
void delete(struct DLinkedList **first, struct DLinkedList *el)
{
struct DLinkedList* temp = *first;
if (temp != NULL && temp->sensorData == el->sensorData)
{
(*first) = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->sensorData == el->sensorData)
{
temp->prev = temp;
temp = temp->next;
}
if (temp == NULL)
{
return;
}
free(temp);
}
Is there something wrong with the code itself? The compiler is not giving me any errors but the function doesn't seem to work properly, the way I call it in main() is delete(&first, el);
Here is my main, I have added 3 elements excluding el so that I can see the list more clearly:
int main()
{
//Adding 3 nodes
struct DLinkedList* first = NULL;
struct DLinkedList* second = NULL;
struct DLinkedList* last = NULL;
struct DLinkedList* el = NULL;
//Allocating 3 nodes
first = malloc(sizeof(struct DLinkedList));
second = malloc(sizeof(struct DLinkedList));
last = malloc(sizeof(struct DLinkedList));
el = malloc(sizeof(struct DLinkedList));
first->sensorData = 1; //Assigning data for 'first' node
first->next = second; //Link first node with second node
first->prev = NULL;
second->sensorData = 2;
second->next = last;
second->prev = first;
last->sensorData = 3;
last->next = NULL;
last->prev = second;
el->sensorData = 10;
el->next = first;
el->prev = NULL;
insertFirst(&first, el);
printList(first);
isMember(&first, el);
delete(&first, el);
return 0;
}
//Printing contents of the linked list starting from the 'first' node
void printList(struct Node* first)
{
while (first != NULL)
{
printf(" %f ", first->data);
first = first->next;
}
}
Here below is my minimal example, I have made some changes in the names and main in order to be more readable
#include <stdio.h>
#include <stdlib.h>
//A linked list node
struct Node
{
double data;
struct Node* prev;
struct Node* next;
};
void delete(struct Node** first, struct Node* el)
{
if (*first == el)
{
*first = el->next;
}
if (el->prev)
{
el->prev->next = el->next;
}
if (el->next)
{
el->next->prev = el->prev;
}
free(el);
}
int main()
{
struct Node* first = NULL;
struct Node* el = NULL;
el = malloc(sizeof(struct Node));
el->data = 10;
el->next = NULL;
el->prev = NULL;
delete(&first, el);
print(first);
return 0;
}
You're complicating it much more than necessary. If you have a doubly linked list, use it's abilities.
void delete(struct DLinkedList **first, struct DLinkedList *el) {
// We only need to change the pointer to the first element
// if that's the element we're deleting
if(*first == el)
*first = el->next;
// The old switcheroo
if(el->prev)
el->prev->next = el->next;
if(el->next)
el->next->prev = el->prev;
// Free and we're done. Skip this line if you want to keep the node
// and only remove it from the list.
free(el);
}
This could be combined with a convenient find function:
struct DLinkedList *find(struct DLinkedList **first, double val) {
struct DLinkedList ret = *first;
while(ret && ret->sensorData != val)
ret = ret->next;
return ret;
}
However, you should be careful comparing float numbers. Read more here: What is the most effective way for float and double comparison?
It seems you're trying to reuse an "element" struct as the "list" struct for a doubly linked list.
Although you can reuse next/prev as head/tail, I recommend a separate header struct:
Here's what I mean. Note that I renamed the struct slightly to be more descriptive of purpose:
// element of list
typedef struct element Element;
struct element {
double sensorData;
Element *next;
Element *prev;
};
// list header
typedef struct list List;
struct list {
Element *head;
Element *tail;
};
void
delete(List *list,Element *el)
{
Element *next;
Element *prev;
next = el->next;
prev = el->prev;
if (next != NULL)
next->prev = prev;
if (prev != NULL)
prev->next = next;
if (list->head == el)
list->head = next;
if (list->tail == el)
list->tail = prev;
}

Reversing a Singly Linked List

I know there are multiple questions on the same problem on SO. But somewhere, I am not able to get the logic.
The function that reverses the Linked List is as follows:
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
I am using a global head pointer and the structure of a node in the linked list is:
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
Here, every time the curr node will point to the prev node and at the end when the list is traversed by the curr node, prev node will point to the last node in the list which I make as the head pointer.
But, this logic doesn't reverse the list and only prints the first node. So, I think the code is executed only once but I am not able to catch the mistake.
The other functions to make the program complete:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
void add(int n)
{
struct node *temp = (struct node*)malloc(sizeof(struct node));
temp->data = n;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
temp->next = head;
head = temp;
}
void print()
{
struct node *temp = head;
printf("\n The List is : ");
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp = temp->next;
}
}
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
int main(void)
{
add(1);
add(2);
add(3);
add(4);
add(5);
print();
reverse();
print();
return 0;
}
You are overwriting the curr->next pointer which is then used to iterate the list. Code should be more like this:
void reverse()
{
struct node *curr=head, *prev=NULL;
struct node *next;
while(curr!=NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}

reverse printing of linked list in c

I am trying to print the reverse linked list. But I am getting only one value. Where am I going wrong? Please bear with me as I am new to C.
#include<stdio.h>
#include<stdlib.h>
struct itemlist {
int value;
struct itemlist *next;
};
typedef struct itemlist item;
int main(void) {
itemlist *curr,*head,*tail;
head=NULL;
tail=NULL;
for (int i = 1; i < 10; i++) {
curr=(itemlist *)malloc(sizeof(itemlist));
curr->value=i;
curr->next=tail;
tail=curr;
if (!head)
head=curr;
}
curr=head;
while (curr) {
printf("Curr value is:%d\n",curr->value);
curr=curr->next;
}
return 0;
}
This code prints 1 to 9
#include<stdio.h>
#include<stdlib.h>
struct itemlist
{
int value;
struct itemlist *next;
};
typedef struct itemlist item;
int main(void)
{
itemlist *curr,*head,*prev;
head=NULL;
curr=NULL;
prev=NULL;
for(int i=1;i<10;i++)
{
curr = new itemlist;
curr->value = i;
curr->next = NULL;
if (head == NULL)
head = curr;
if(prev != NULL)
prev->next = curr;
prev = curr;
}
curr=head;
while(curr)
{
printf("Curr value is:%d\n",curr->value);
curr=curr->next;
}
return 0;
}
Seems like you should start print your list from tail, not from head.
Change
curr=head;
with
curr = tail;
Change curr=head to curr=tail
Below is a simple example illustrating a bi-directional linked list which should get you on your way to understanding linked lists
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int value;
struct itemlist *next;
struct itemlist *prev;
}itemlist;
void forward(itemlist *head)
{
itemlist *curr = head;
while(curr)
{
printf("Curr value is: %d\n", curr->value);
curr = curr->next;
}
}
void backward(itemlist *tail)
{
itemlist *curr = tail;
while(curr)
{
printf("Curr value is: %d\n", curr->value);
curr = curr->prev;
}
}
int main(void)
{
itemlist *curr,*head,*tail;
head=NULL;
tail=NULL;
for(int i=1;i<10;i++)
{
curr=(itemlist *)malloc(sizeof(itemlist));
curr->value=i;
curr->next = NULL;
if(tail)
{
curr->prev = tail;
tail->next = curr;
}
tail=curr;
if(!head)
head=curr;
}
printf("Forwards\n");
forward(head);
printf("Backwards\n");
backward(tail);
return 0;
}
You don't need a tail at all, but only need a recursive function. The function points to next by itself before the printf.
void print_reverse(Itemlist *it){
if(it !=NULL){
print_reverse(it->next);
printf("Current value is:%d\n",it->value);
}
}
When you exit the loop your head (which was updated only once and when the first element was added) points to the last element.
The problem is that, in the first iteration, when you assign the next element of the current item:
curr->next=tail;
the value of tail is NULL, so the head of your list can't reach the rest of it
At least as I understand it, your plan is to create a linked list in reverse order, then print out its contents. If so, you probably want something like this:
#include <stdlib.h>
#include <stdio.h>
struct itemlist {
int value;
struct itemlist *next;
};
int main() {
struct itemlist *head = NULL;
struct itemlist *pos;
int i;
for (i=0; i<10; i++) {
struct itemlist *node = malloc(sizeof(*node));
node->value = i;
node->next = head;
head = node;
}
for (pos=head; NULL != pos; pos = pos->next)
printf("%d\n", pos->value);
return 0;
}
Note that you don't need a pointer to the "tail". The basic idea is pretty simple: start with head as an empty list (i.e., a null pointer). Insert each new node at the beginning of the list by setting its next pointer to the current beginning of the list, then setting the beginning of the list to point to the new node.
You're head and tail are mixed up:
The first Node (Node 0):
Value = 1
next = tail = NULL;
tail = Node 0
head = Node 0
The second Node (Node 1):
Value = 2
next = tail = Node 0
tail = Node 1
head = Node 0
Now you have
Node 1 -> Node 0 -> NULL
and head = Node 0 and tail = Node 1
So when you print you start at Node 0 (the "head" but it's actually the tail) Print the first node then end
You have to either switch head and tail to be the correct names or start printing with tail
Edit: Since you say you want them in order you can do this:
int main(void)
{
itemlist *curr,*head,*tail;
head=NULL;
tail=NULL;
for(int i=1;i<10;i++)
{
curr=(itemlist *)malloc(sizeof(itemlist));
curr->value=i;
curr->next = NULL;
//if there is something in the list add the current node after it
if(tail)
tail->next = curr;
//Update the tails so it's pointing to the current last node
tail = curr;
//Set the head ONCE
//this will happened the first time when if(tail) fails
if(!head)
head=curr;
}
//start at the head
curr=head;
while(curr)
{
printf("Curr value is:%d\n",curr->value);
curr=curr->next;
}
return 0;
}

C: How to free nodes in the linked list?

How will I free the nodes allocated in another function?
struct node {
int data;
struct node* next;
};
struct node* buildList()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
return head;
}
I call the buildList function in the main()
int main()
{
struct node* h = buildList();
printf("The second element is %d\n", h->next->data);
return 0;
}
I want to free head, second and third variables.
Thanks.
Update:
int main()
{
struct node* h = buildList();
printf("The element is %d\n", h->next->data); //prints 2
//free(h->next->next);
//free(h->next);
free(h);
// struct node* h1 = buildList();
printf("The element is %d\n", h->next->data); //print 2 ?? why?
return 0;
}
Both prints 2. Shouldn't calling free(h) remove h. If so why is that h->next->data available, if h is free. Ofcourse the 'second' node is not freed. But since head is removed, it should be able to reference the next element. What's the mistake here?
An iterative function to free your list:
void freeList(struct node* head)
{
struct node* tmp;
while (head != NULL)
{
tmp = head;
head = head->next;
free(tmp);
}
}
What the function is doing is the follow:
check if head is NULL, if yes the list is empty and we just return
Save the head in a tmp variable, and make head point to the next node on your list (this is done in head = head->next
Now we can safely free(tmp) variable, and head just points to the rest of the list, go back to step 1
Simply by iterating over the list:
struct node *n = head;
while(n){
struct node *n1 = n;
n = n->next;
free(n1);
}
One function can do the job,
void free_list(node *pHead)
{
node *pNode = pHead, *pNext;
while (NULL != pNode)
{
pNext = pNode->next;
free(pNode);
pNode = pNext;
}
}
struct node{
int position;
char name[30];
struct node * next;
};
void free_list(node * list){
node* next_node;
printf("\n\n Freeing List: \n");
while(list != NULL)
{
next_node = list->next;
printf("clear mem for: %s",list->name);
free(list);
list = next_node;
printf("->");
}
}
You could always do it recursively like so:
void freeList(struct node* currentNode)
{
if(currentNode->next) freeList(currentNode->next);
free(currentNode);
}

Rotate a linked list

I want to rotate a linked list that contains a number. 123 should be rotated to 231. The function created 23 but the last character stays empty, why?
typedef struct node node;
struct node{
char digit;
node* p;
};
void rotate(node** head){
node* walk= (*head);
node* prev= (*head);
char temp= walk->digit;
while(walk->p!=NULL){
walk->digit=walk->p->digit;
walk= walk->p;
}
walk->digit=temp;
}
How I create the list:
node* convert_to_list(int num){
node * curr, * head;
int i=0,length=0;
char *arr=NULL;
head = NULL;
length =(int) log10(((double) num))+1;
arr =(char*) malloc((length)*sizeof(char)); //allocate memory
sprintf (arr, "%d" ,num); //(num, buf, 10);
for(i=length;i>=0;i--) {
curr = (node *)malloc(sizeof(node));
(curr)->digit = arr[i];
(curr)->p = head;
head = curr;
}
curr = head;
return curr;
}
Your linked list actually has 4 elements.
You should change this line:
for(i = length; i >= 0 ; i--) {
to:
for(i = length - 1; i >= 0; i--) {
because with the former line you're going out of the array (you're accessing arr[length] on the first iteration).
With this change your rotate function works correctly.
You can solve most problems by breaking them down into simpler ones.
Here, I'd write your rotate as follows:
void rotate(node **list) {
node *head = pop_head(list);
push_at_end(list, head);
}
node *pop_head(node **list) {
assert(*list);
node *head = *list;
*list = head->p;
head->p = 0;
return head;
}
void push_at_end(node **list, node *head) {
node *end = get_end(*list);
if (!end) {
*list = head;
} else {
end->p = head;
}
}
node *get_end(node *head) {
node *last = 0;
while (head) {
last = head;
head = head->p;
}
return last;
}
The problem with your question is that the list is stored backwards, and you have a pointer to previous, instead next. This should have been part of the question (it took me a while to understand that).
Actually, you use head when probably tail would have been better. You should consider storing a pointer to the actual head, and avoid this way copying. In that case, you would only need to adjust pointers. If rotation is going to be a common task, then keeping and updating an extra pointer, may be in a list struct, would pay the effort (could change the task from O(n) to O(1)).
struct _list {
node * tail;
node * head;
};
typedef struct _list list;
In any case, the problem with your rotate function is that you are starting with walk and prev at the same node, head.
void rotate(node** head){
node* walk= (*head);
node* prev=(*head)->p;
char temp= walk->digit;
while(prev!=NULL){
walk->digit=prev->digit;
walk= prev;
prev = prev->p;
}
walk->digit=temp;
}
I have written the code for linked list rotation by k nodes in c++. It worked for me perfectly. If you pass k as 1, it will rotate the liked list by 1 node and here it solves the given problem. If you want to rotate the linked list by k nodes, it will still work fine. Please find it below.
Header file :
public:
typedef struct node {
int data;
node *next;
} *Node;
Node head;
void rotateByk(int k);
Following code is for .cpp file.
void DList::rotateByk(int k){
Node current = head;
Node kthNode;
int count = 1;
while(count<=k && current!=NULL){
kthNode = current;
current = current->next;
count++;
}
Node kthNextNode = current;
while(current->next!=NULL){
current = current->next;
}
current->next = head;
head = kthNextNode;
kthNode->next = NULL;
Node printNode = head;
while(printNode!=NULL){
cout << printNode->data << "\t";
printNode = printNode->next;
}
}
Pass k as argument in main method for linked list d1.
d1.rotateByk(1);
Please let me know if you have any queries.

Resources