linked list garbage value c - c

I'm trying to do some programming puzzles to learn C and I'm having trouble with getting a linked list deletion to work when deleting the head node. I think the problem is super simple but I can't find it!! The problem I'm having is with the delete() function, when I try to remove the head of a linked list it doesn't remove it, but instead changes it to a garbage value.
Can anyone help me out please? Thank you so much!
Here's example output:
Generating list...
Inserted: 0
Inserted: 1
Inserted: 2
Inserted: 3
Inserted: 4
List:
0 1 2 3 4
Deleted: 4
List:
0 1 2 3
Deleted: 0
List:
8344720 1 2 3
Here is my source code:
#include <stdlib.h>
#include <stdio.h>
typedef struct Node {
int value;
struct Node* next;
} node;
// Append a node to the end of the linked list
int insert(node* head, int value) {
node* current = head;
/* Check for sentinel value. If first element inserted, overwrite head instead of appending. */
if (head->value == 420) {
head->value = value;
head->next = NULL;
printf("\tInserted:\t%d\n", head->value);
return 0;
}
/* Traverse to end to append node */
while (current->next != NULL)
current = current->next;
/* Build new node and append to tail*/
current->next = malloc(sizeof(node));
current->next->value = value;
current->next->next = NULL;
printf("\tInserted:\t%d\n", current->next->value);
return 0;
}
/* Accept a number and delete all nodes containing that value */
int del(node* head, int value){
node* curr = head;
node* prev = NULL;
node* del = NULL;
printf("\tDeleted:\t%d\n", value);
if (head == NULL) {
printf("Can't delete value from empty list!\n");
return 1;
}
/* Search list remove all instances of value. Watch for edge cases. */
while (curr != NULL) {
if (curr->value == value){
/* Head case (lol) */
if (curr == head) {
del = head;
head = head->next;
curr = head;
free(del);
}
/* Tail case */
else if (curr->next == NULL) {
del = curr;
curr = prev;
curr->next = NULL;
free(del);
return 0; /* End of list, break out of loop to avoid segfaulting */
}
/* Body case (base case) */
else {
del = curr;
curr = curr->next;
prev->next = curr;
free(del);
}
}
prev = curr;
curr = curr->next;
}
return 0;
}
/* Accept head pointer and print until end of list */
int traverse(node* head) {
node* current = head;
if (head == NULL){
printf("Can't traverse null list!\n");
return 1;
}
printf("List:\n");
while(current != NULL) {
printf(" %d ", current->value);
current = current->next;
}
printf("\n");
return 0;
}
/* Let's begin our crazy experiment.... */
int main() {
node* head = NULL;
head = malloc(sizeof(node));
head->value = 420;
head->next = NULL;
printf("Generating list...\n");
int value;
for (value = 0; value < 5; value++)
insert(head, value);
traverse(head);
del(head, 4);
traverse(head);
del(head, 0);
traverse(head);
return 0;
}

You are modifying the head inside the del() function and using the old head from the main(). You need to pass the address of the head to del and modify it so that the change will reflect in main. You may need something like this.
int del(node **head, int value){
node* curr = *head;
....
And from the main
del(&head);

Related

unable to insert into ordered linked list in C

i am new to programming and C. I am trying to create an ordered linked list. For some reason which i cannot figure out, it never enters the first if block in the insert_in_order function even though my linked list is empty when i call the insert_in_order function. Would anyone have any idea what i am doing wrong?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node* next;
};
typedef struct node node_t;
void printlist(node_t *head){
node_t *temporary = head;
while(temporary != NULL){
printf("%d - ", temporary->value);
temporary = temporary->next;
}
printf("\n");
}
node_t *create_new_node(int value){
node_t *result = malloc(sizeof(node_t));
result->value = value;
result->next = NULL;
//printf("result.value = %d\n", result->value);
return result;
}
void insert_in_order (node_t *head, node_t *node_to_insert){
node_t *current_node = head;
node_t *prior_node = head;
//linked list is empty
if (head == NULL){ //never enters if block for some reason
head->next = node_to_insert;
node_to_insert->next = NULL;
break;
//printf("inside the if stmt");
}
if(node_to_insert->value <= current_node->value){
head->next = node_to_insert;
node_to_insert->next = current_node;
break;
}
current_node = current_node->next;
while (current_node->next != NULL){
if(node_to_insert->value <= current_node->value){
node_to_insert->next = current_node;
prior_node->next = node_to_insert;
break;
}
else if (node_to_insert > current_node){
current_node = current_node->next;
prior_node = prior_node->next;
}
}
//node to insert is the largest in the linked list
current_node->next = node_to_insert;
node_to_insert->next = NULL;
}
int main(){
node_t *head;
node_t *node1;
node_t *node2;
head = NULL;
node1 = create_new_node(22);
node2 = create_new_node(33);
printf("node1's value equals %d\n", node1->value);
printf("node2's value equals %d\n", node2->value);
insert_in_order(head, node1);
printlist(head);
}
First of all this code does not compile - these breaks are invalid
if (head == NULL){ //never enters if block for some reason
head->next = node_to_insert;
node_to_insert->next = NULL;
break; <<<<====
//printf("inside the if stmt");
}
and
if (node_to_insert->value <= current_node->value) {
head->next = node_to_insert;
node_to_insert->next = current_node;
break; <<<=====
}
Seems like you meant return when you said break, now compiles with those replaced by return
Now this goes wrong
//linked list is empty
if (head == NULL) { //never enters if block for some reason
head->next = node_to_insert;
You just tested to see if head is NULL and if it is you try to use it, thats never going to work
You mean this
//linked list is empty
if (head == NULL) { //never enters if block for some reason
head = node_to_insert;
node_to_insert->next = NULL;
return;
}
code now runs to completion, although there may be other errors
node1's value equals 22
node2's value equals 33

Find value occurrences and delete nodes in linked list

I really need help with a problem about linked lists in C.
I need to create a function where I have to read the nodes in the list and, for each node, I have to find occurrences. If the occurrences of the value are equals or greater than a variable value, this nodes must be deleted.
Example:
1->3->8->5->6->8->3->8->9
#of occurrences >= 3
So all the nodes with value 8 must be deleted.
Modified list:
1->3->5->6->3->9
Thank you so much.
Oh sorry my bad.
Yes I tried some solutions, but still didn't find one that works.
For delete all occurrences of a value I did this:
void deleteOccurrences(List *head, int val){
Lista *temp = *testa, *prev;
while(temp != NULL && temp->val == val){
*head = temp->next;
free(temp);
temp = *head;
}
while(temp != NULL){
while (temp != NULL && temp->val != val){
prev = temp;
temp = temp->next;
}
if(temp == NULL)
return;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
}
and for count occurrences I did:
bool countOccurrences(List head, int val, int occur){
int count = 0;
while(head != NULL){
if(head->val == val)
count++;
head = testa->next;
}
if(count >= occur)
return true;
return false;
}
Then the function I'm trying to using is something like this:
void manageList(List head){
while(head != NULL){
int val = head->val;
if(countOccurences(head, val, 3))
deleteOccurrences(&head, val);
head = head->next;
}
}
This is the main:
int main(){
List head;
head = NULL;
head = insert(head,9);
head = insert(head,8);
head = insert(head,3);
head = insert(head,8);
head = insert(head,6);
head = insert(head,5);
head = insert(head,8);
head = insert(head,3);
head = insert(head,1);
manageList(head);
return 0;
}
where insert() function is just an insert at the beginning of the list.
This is the definition of the node:
typedef struct El{
int val;
struct El *next;
}ElemList;
typedef ElemList *List;
When I compile and run this I get a segmentation fault error.
If I try to run just the deleteOccurrences() function or the countOccurrences() function, they work as expected.
The problem is in this function manageList() that I don't understand how to read the list and in the same time find the occurrences and delete nodes.
void manageList(List *head){
ElemList *cur = *head;
while(cur != NULL){
int val = cur->val;
if(countOccurences(cur, val, 3)){
deleteOccurrences(cur, val);
cur = *head;
}else
head = head->next;
}
}

Swapping neighbor linked list nodes

I have to make a function which swaps the neighbor nodes in a linked list with sentinel. Something like this: 1-2-3-4-5 -> 2-1-4-3-5, but I don't know how to do that. Can somebody help me?
#include <stdio.h>
#include <stdlib.h>
typedef struct _listelem {
int a;
struct _listelem* next;
} listelem;
void reverse_pairs(listelem* a)
{
listelem* head = NULL;
listelem* tail = NULL;
head = a->next;
tail = a->next;
while (head->next != NULL)
{
head = head->next->next;
tail = head;
}
return head;
}
You did not show how the list with a sentinel node is built.
I suppose that the sentinel node is the first node in the list pointed to by the pointer head.
In this case the function can look the following way.
void reverse_pairs( listelem *head )
{
if (head)
{
for (; head->next && head->next->next; head = head->next->next)
{
listelem *tmp = head->next;
head->next = head->next->next;
tmp->next = head->next->next;
head->next->next = tmp;
}
}
}
As for your function implementation then it is incorrect at least because a function with the return type void may not have a statement like this
return head;
Also within this while loop
while (head->next != NULL)
{
head = head->next->next;
tail = head;
}
you are changing the local variables head and tail. Such changes do not influence on the original list.
If you have a circular list when the data member next of the last node points to the head (sentinel) node then the function can look the following way.
void reverse_pairs( listelem *head )
{
if (head)
{
for ( listelem *current = head;
current->next != head && current->next->next != head;
current = current->next->next)
{
listelem *tmp = current->next;
current->next = current->next->next;
tmp->next = current->next->next;
current->next->next = tmp;
}
}
}
While the answer from #VladFromMoscow shows the proper approach for swapping nodes in the list to accomplish your objective, if you are stuck passing a single pointer, and the function return type is fixed at void, then there is another way to go about it.
Instead of swapping nodes, you simply swap the int member value between nodes. Approaching the problem that way, the address of the first node never changes, so there is no need to pass the address of the list as a parameter.
The approach is simple. Take the current node, swap the integer value between the current and next node and advance past the nodes holding the swapped integers. To do so, you advance from the current node to the next and check if the node that follows next is NULL (marking the end of the list). If it is NULL, you are done. If it is not NULL, advance again and repeat. You can write the function either with a while() loop, e.g.
void reverse_pairs (listelem *head)
{
while (head && head->next) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
head = head->next;
if (head->next)
head = head->next;
}
}
Or, slightly less readable, using a for() loop and a ternary, e.g.
void reverse_pairs (listelem *head)
{
for (; head && head->next;
head = head->next->next ? head->next->next : NULL) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
}
}
Example Use/Output
With a normal list where the last pointer is NULL, your output printing the original list, calling reverse_pairs(), and then outputting the modified list would look as follows:
$ ./bin/lls_revpairs
1 2 3 4 5
2 1 4 3 5
Complete Test Code
The complete test code is included below. Compiling as normal will use the for() loop above, or adding the define -DUSEWHILE, to your compile string will cause the while() loop form of the function to be used:
#include <stdio.h>
#include <stdlib.h>
typedef struct _listelem {
int a;
struct _listelem* next;
} listelem;
/** add node at end of list, update tail to end */
listelem *add (listelem **head, int v)
{
listelem **ppn = head, /* pointer to pointer to head */
*pn = *head, /* pointer to head */
*node = malloc (sizeof *node); /* allocate new node */
if (!node) { /* validate allocation */
perror ("malloc-node");
return NULL;
}
node->a = v; /* initialize members values */
node->next = NULL;
while (pn) {
ppn = &pn->next;
pn = pn->next;
}
return *ppn = node; /* add & return new node */
}
#ifdef USEWHILE
/** reverse node pairs in list - while loop */
void reverse_pairs (listelem *head)
{
while (head && head->next) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
head = head->next;
if (head->next)
head = head->next;
}
}
#else
/** reverse node pairs in list - for loop + ternary */
void reverse_pairs (listelem *head)
{
for (; head && head->next;
head = head->next->next ? head->next->next : NULL) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
}
}
#endif
/** print all nodes in list */
void prn_list (listelem *l)
{
if (!l) {
puts ("list-empty");
return;
}
size_t i = 0;
for (listelem *n = l; n && i < 10; n = n->next, i++)
printf (" %d", n->a);
putchar ('\n');
}
int main (void) {
listelem *list = NULL;
for (int i = 1; i <= 5; i++)
add (&list, i);
prn_list (list);
reverse_pairs (list);
prn_list (list);
}

Linked List in C: Accessing current->next is neither NULL or !NULL; problem with adding new nodes

So I encounter this problem where when I add nodes to an empty head in a specific sequence it doesn't work.
If I insert 2,1,3,4 so the second number is smaller than the first number, then it works. But if I add 2,3,4,5, then it doesn't work. I get a Segmentation fault (core dumped).
Can somebody tell me whats wrong here?
This is my struct and adding-method:
struct list_node{
int value;
struct list_node* next;
};
typedef struct list_node node_t;
node_t* add_element_sorted(node_t* head, int v){
node_t* current = head;
node_t* new = NULL;
new = (node_t *) malloc (sizeof(node_t));
if (new == NULL) {
printf("error");
exit(1);
}
new->value = v;
printf("%d\n", new->value);
if (current != NULL){ //check if first node is empty
while(current->value < v){
current = current->next;
printf("broke \n");
if(current->next == NULL){ // check if current node is the last then its next shoud be null
break;
}
}
}
if (current == head) {
new->next = head;
return new;
} else {
new->next = current->next;
current->next = new;
return head;
}
}
At this part it returns me current->next is neither NULL or !NULL. What is current->next now?
if(current->next == NULL){ // check if current node is the last then its next shoud be null
break;
}
My main looks like this:
int main(){
node_t* head = NULL;
head = add_element_sorted(head, 2);
head = add_element_sorted(head, 3);
head = add_element_sorted(head, 4);
head = add_element_sorted(head, 5);
return 0;
}

Unable to remove lowest value from linked-list

I created a linked-list in C. I'm trying to create a function that looks at the lowest value in the linked list (which is the head) and the removes the "right-most" instance of that value in the list.
Suppose the linked-list looks like this:
2 -> 2 -> 2 -> 4 -> 5 -> 6
The head in this list is 2. But it's not the head I want to remove. I want to remove the 2 that comes before the 4 (it is the right-most instance of the head).
Here's the function I created to implement this:
double removeLowestValue() {
struct node *temp;
struct node *ptr = head;
double val = ptr->value;
if(head == tail)
{
free(head);
head = NULL;
tail = NULL;
}
else
{
while(ptr->value == ptr->next->value)
{
temp = ptr;
ptr = ptr->next;
val = ptr->value
}
temp->next = NULL;
temp->next = ptr->next;
free(ptr);
return val;
}
}
Then I tried to test if the function works:
int main() {
insertNode(18.0);
insertNode(13.0);
insertNode(11.0);
insertNode(11.0);
insertNode(22.0);
printf("%d", removeLowestValue());
return 0;
}
Unfortunately, the program doesn't print out "11" as expected. Matter of fact, it doesn't print anything at all. What's going on here?
EDIT:
Here's how I implemented the insertNode function:
void insertNode(double value) {
struct node *new_node = create_new_node(value);
struct node *temp = head;
struct node *prev;
if (head == NULL) {
head = new_node;
tail = new_node;
} else {
while (value > temp->value && temp->next != NULL) {
prev = temp;
temp = temp->next;
}
if(value < temp->value || value == temp->value)
{
/*If the value of the new node equals to the value of temp
OR if the value of the new node is less than the value of temp,
then insert the new node right before temp*/
new_node->next = temp;
prev->next = new_node;
}
else if(value > temp->value)
{
temp->next = new_node;
tail = new_node;
}
}
}
your function corrected, of course that supposes the list is sorted :
double removeLowestValue() {
if (head == NULL)
return 0; /* ???? */
else {
node * ptr = head;
node * previous = 0; /* the cell before the cell to remove */
while ((ptr->next != NULL) && (ptr->value == ptr->next->value)) {
previous = ptr;
ptr = ptr->next;
}
/* ptr is now the cell to remove */
double val = ptr->value;
if (ptr == head) {
/* remove the first cell */
ptr = head->next;
free(head);
head = ptr;
if (head == NULL)
/* the list is empty */
tail = NULL;
}
else if (ptr->next == NULL) {
/* all the values are the same in the list
ptr is the last cell */
free(ptr);
/* previous is now the last cell */
previous->next = NULL;
tail = previous;
}
else {
/* ptr is not the first nor the last cell */
previous->next = ptr->next;
free(ptr);
}
return val;
}
}
Concerning insertNode :
it is better to move the declaration of the variables temp and prev where they are useful, they are useless if head null so at the top of the definition
(value < temp->value || value == temp->value) can be just (value <= temp->value) and the else if (...) after can be just an else
when (value <= temp->value) prev can be still unset but used for prev->next = new_node, that appends when you insert 13 after 18 in your main. When (temp == head) you have to update head setting it with new_node
So the corrected version can be :
void insertNode(double value) {
struct node *new_node = create_new_node(value);
if (head == NULL) {
head = new_node;
tail = new_node;
} else {
struct node *temp = head;
struct node *prev = 0; /* = 0 to be sure to have a crash if something wrong */
while ((value > temp->value) && (temp->next != NULL)) {
prev = temp;
temp = temp->next;
}
if (value <= temp->value)
{
/* insert the new node right before temp*/
new_node->next = temp;
if (temp == head)
head = new_node;
else
/* prev was set */
prev->next = new_node;
} else {
/* insert the new node at end */
temp->next = new_node;
tail = new_node;
}
}
}
Using the additional definitions
typedef struct node {
double value;
struct node * next;
} node;
node * create_new_node(double value)
{
node * r = (node *) malloc(sizeof(node));
r->value = value;
r->next = 0;
return r;
}
int main() {
insertNode(18.0);
insertNode(13.0);
insertNode(11.0);
insertNode(11.0);
insertNode(22.0);
printf("%g\n", removeLowestValue());
printf("%g\n", removeLowestValue());
printf("%g\n", removeLowestValue());
printf("%g\n", removeLowestValue());
printf("%g\n", removeLowestValue());
printf("%g\n", removeLowestValue());
return 0;
}
the execution writes (the last 0 indicate the list is empty)
11
11
13
18
22
0

Resources