Linked List output not showing correctly - c

I can't figure out where is the problem in my code:
typedef struct list List;
struct list {
int data;
List* next;
};
void insert_sorted(List** head, int value);
int main() {
List* head = NULL;
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
insert_sorted(&head, 3);
insert_sorted(&head, 2);
insert_sorted(&head, 40);
insert_sorted(&head, 10);
//insert_sorted(&head, 40);
List* temp = head;
while (temp != NULL) {
printf("%d\t", temp->data);
temp = temp->next;
}
printf("\n\n");
return 0;
}
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) {
node->next = *head;
*head = node;
} else {
temp = *head;
while (temp->next != NULL) {
if (temp->data < value && (temp->next)->data > value) {
node->next = temp->next;
temp->next = node;
} else
temp = temp->next;
}
temp->next = node;
}
}
1:
Run the code and see results. (Running and running...) after sorting data it is repeating some values forever.
2:
Go to
//insert_sorted(&head, 40);
this line an remove comment symbols.
Run the code and mark the result.(Time limit exceeded)
3:
Find this and remove comments:
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
Run and see results; (Again some problems)
Finally:
Remove all comments symbols and run it, this time it is working without any error but not as expected (List is not sorted correctly);
But why this is happening? Any help will be appreciated, and I am not at home at this but a learner.

Your void insert_sorted(List** head, int value) function is doing too much work.
void insert_sorted(List** head, int value) {
List* node = malloc(sizeof *node);
node->data = value;
for( ; *head ; head = &(*head)->next) {
if ((*head)->data > value) break; // we should insert before *head
}
// When we get here *head points to the pointer that needs to get node's value
// This can either be the original head (as supplied as argument tothe function)
// or some of the -> next pointers, or even the last ->next pointer.
node->next = *head;
*head = node;
}

The problem can be fixed as follows. If the node is inserted in the middle, the function can return and does not need to append the value at the end.
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) { // <-- fix
node->next = *head;
*head = node;
}
else {
temp = *head;
while (temp->next != NULL) {
if ( (temp->next)->data > value ) {
node->next = temp->next;
temp->next = node;
return; // <-- fix
}
else
temp = temp->next;
}
temp->next = node;
}
}

Your code sometimes inserted value twice (when value was not placed at the end of the list). This should fix the problem:
while(temp->next != NULL)
{
if(temp->data < value && (temp->next)->data > value)
{
node->next = temp->next;
temp->next = node;
break;
}
else
temp = temp->next;
}
if(temp->next == NULL)
temp->next = node;

Related

I cannot print delete_first result in C (circular linkedlist)

I want to print delete_first result and delete_last result. But it can only print delete_last code. How can i solve this matter?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int element;
typedef struct ListNode {
element data;
struct ListNode* link;
} ListNode;
void print_list(ListNode* head)
{
ListNode* p;
if (head == NULL) return;
else {
p = head->link;
do {
printf("%d ", p->data);
p = p->link;
} while (p != head->link);
}printf("\n");
}
ListNode* insert_first(ListNode* head, element data)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = data;
if (head == NULL) {
head = node;
node->link = head;
}
else {
node->link = head->link;
head->link = node;
}
return head;
}
ListNode* insert_last(ListNode* head, element data)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = data;
if (head == NULL) {
head = node;
node->link = head;
}
else {
node->link = head->link;
head->link = node;
head = node;
}
return head;
}
I want to print delete_first result and delete_last result. But I can only print delete_last result. How can i print delete_first result?
This is my delete_first code.
ListNode* delete_first(ListNode* head) {
if (head == NULL)
{
return head;
}
if (head->link == head) {
free(head);
head = NULL;
return head;
}
ListNode* p = head->link;
head->link = p->link;
free(head);
head = NULL;
return head;
}
ListNode* delete_last(ListNode* head) {
if (head == NULL)
return head;
ListNode* p = head->link;
if (head->link == head) {
free(head);
head = NULL;
return head;
}
while (p->link != head) {
p = p->link;
}
p->link = head->link;
free(head);
head = p;
return head;
}
int main() {
ListNode* head = NULL;
head = insert_first(head, 10);
head = insert_first(head, 20);
head = insert_first(head, 30);
head = insert_first(head, 40);
head = insert_last(head, 50);
print_list(head);
head=delete_last(head);
print_list(head);
head = delete_first(head);
print_list(head);
return 0;
}
If you want to print the element being removed, then you cannot free() it, or you have to copy it to a local variable and return it by value.
If you want caller to be able to print what remains of the list, then you need to find the last node which has a link that points at head and have it point at head->next instead. Then return that value (instead of NULL):
ListNode* delete_first(ListNode* head) {
if(!head)
return NULL;
if(head == head->link) {
free(head);
return NULL;
}
ListNode* last;
for(last = head; last->link != head; last = last->link);
last->link = head->link;
free(head);
return last->link;
}
There is no point of setting head = NULL as the copy of that variable is lost the caller anyways.

Multiple data inside a single linked list node

Is it possible to have multiple data inside a single linked list node in C? And how do you input and access data with this?
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
char name[30];
struct node *next;
};
struct node *head, *tail = NULL;
void addNode(int data, char string) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->name[30] = string;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s", current->data, current->name);
current = current->next;
}
printf("\n");
}
int main()
{
char string1[10] = "Aaron";
char string2[10] = "Baron";
char string3[10] = "Carla";
addNode(9, string1);
addNode(7, string2);
addNode(2, string3);
printf("Original list: \n");
display();
sortList();
printf("Sorted list: \n");
display();
return 0;
}
I don't understand why my code didn't work. I was trying to make use of single linked list where it can accept/input and print/output the number and the name at the same time.
What I want it to happen is to print the number and the name.
The output should be:
Carla - 2
Baron - 7
Aaron - 9
Please read my comments marked as // CHANGE HERE.
// CHANGE HERE: accept a character array as argument
void addNode(int data, char string[]) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
// CHANGE HERE: copy char array argument to name
strncpy(newNode->name, string, 30);
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
char temp1[30];
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
// CHANGE HERE: swap the name along with data
strncpy(temp1, current->name, 30);
strncpy(current->name, index->name, 30);
strncpy(index->name, temp1, 30);
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s\n", current->data, current->name);
current = current->next;
}
printf("\n");
}

double linked list with c

ok, now i have to make double linked list on c.
there are 7 functions which act on main.
append.
insertAt.
deleteAt.
print.
print_revers.
newnode.
newDLL.
i can amend only 5 functions
append, insertAt, deleteAt, print, print_reverse
finally i can make append,print,print_reverse
however, i can't make insertAt,deleteAt, because of index.
1. i can't understand why the code
else {
while (index-- >= 0) {
temp = temp->next;
}
make memory collide. for using index, i need to move node to collect position and connect to newnode. but it doesn't work...
2. also what's return; 's role? i have not seen such type of return.
3. how can i make deleteAt using index? i think deleteAt and insertAt have quiet similar algoritum. so i try to make insertAt first and deleteAt last. but what i write doesn't work well..
i can find a lot of data of doublelinkedlist on internet. but i can't find using index.... i have been listening c language lecture on only two month, so sorry about the spagettii code...
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int val;
struct Node *prev;
struct Node *next;
} Node;
typedef struct {
Node *head;
int size;
} DLL;
Node *newnode(int n)
{
Node *temp = (Node *)malloc(sizeof(Node));
temp->val = n;
temp->prev = NULL;
temp->next = NULL;
return temp;
}
DLL *newDLL() {
DLL *temp = (DLL *)malloc(sizeof(DLL));
temp->head = NULL;
temp->size = 0;
return temp;
}
void append(DLL *list, Node *newnode) {
struct Node* temp = list->head;
struct Node* newNode = newnode;
if (list->head == NULL) {
list->head = newNode;
list->size++;
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
list->size++;
temp->next = newNode;
newNode->prev = temp;
}
void insertAt(DLL *list, int index, Node *newnode) {
struct Node* temp = (Node *)malloc(sizeof(Node));
if (index < 0 || index >= list->size + 1) {
printf("out of range\n");
}
else if (index == 0) {
newnode->next = list->head;
list->head->prev = newnode;
list->head = newnode;
}
else {
while (index-- >= 0) {
temp = temp->next;
}
temp->val = newnode->val;
temp->next = list->head->next;
list->head->next = temp;
temp->prev = list->head;
if (temp->next != NULL)
temp->next->prev = temp;
}
}
void deleteAt(DLL *list, int index) {
//save reference to first link
struct Node* temp = (Node *)malloc(sizeof(Node));
//if only one link
if (list->head->next == NULL) {
list->head->prev = NULL;
}
else {
list->head->next->prev = NULL;
}
list->head = list->head->next;
//return the deleted link
return;
}
void print(DLL *list) {
struct Node* temp = list->head;
printf("Forward: ");
while (temp != NULL) {
printf("[%d] ", temp->val);
temp = temp->next;
}
printf("\n");
}
void print_reverse(DLL *list) {
struct Node* temp = list->head;
if (temp == NULL) return; // empty list, exit
// Going to last Node
while (temp->next != NULL) {
temp = temp->next;
}
// Traversing backward using prev pointer
printf("Reverse: ");
while (temp != NULL) {
printf("[%d] ", temp->val);
temp = temp->prev;
}
printf("\n");
}
int main() {
DLL *list = newDLL();
int i;
for (i = 1; i < 6; i++) {
append(list, newnode(i));
}
print(list);
deleteAt(list, -1);
deleteAt(list, 5);
deleteAt(list, 0);
print(list);
deleteAt(list, 2);
print(list);
deleteAt(list, 2);
print(list);
insertAt(list, -1, newnode(6));
insertAt(list, 3, newnode(6));
insertAt(list, 0, newnode(7));
print(list);
insertAt(list, 1, newnode(8));
print(list);
insertAt(list, 4, newnode(9));
print(list);
print_reverse(list);
return 0;
}
The part where you insert at index has problems:
temp = malloc is wrong, it should start with temp = head.
in the insertion:
temp->val = newnode->val;
temp->next = list->head->next;
list->head->next = temp;
temp->prev = list->head;
temp->next should not be head->next, it should be newnode. newnode->next should be temp->next etc.

Can't delete a node using a condition in circular linked list in c

I have a circular linked list as follows which keeps a status of data to be processed. The status is used to decide to delete from the list which could be at the beginning, middle or end. The list might not even have any data at all at times or might have more than one node to delete.
struct data
{
bool status;
char other_info[20];
struct data *next;
};
I tried the following code
struct data* delete_nodes(struct data *head)
{
struct data* first = NULL, *prev = NULL, *temp = NULL;
first = head;
temp = head;
prev = head;
do
{
//prev = temp;
if (temp != NULL && temp->next == head)
{
head->next = NULL;
free(temp);
head = NULL;
return head;
}
if (temp != NULL && temp->status == true)
{
//temp = prev;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
else if(temp != NULL)
temp = temp->next;
if (temp == NULL)
return head;
} while (temp != NULL && first != temp);
head = temp;
return head;
}
Now, pushing data into it works fine. deleting also works fine if there is only one node. but when there are more than one node to be deleted it crashes.
The delete_nodes() function is invoked by a thread which processes data if there is any and invokes delete_nodes()
This code block
if (temp != NULL && temp->status == true)
{
//temp = prev;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
is for sure wrong when doing the first iteration.
At the first iteration prev and temp are both the same as head. So prev is pointing to the same memory as you are free-ing.
Consider to drop all the checks for NULL and only have a check in the start, i.e.
struct data* delete_nodes(struct data *head)
{
if (head == NULL) return NULL;
// Hereafter no further checks for NULL is needed
A complete function could look like:
struct data* delete_nodes(struct data *head)
{
if (head == NULL) return NULL;
struct data *prev = NULL;
struct data *temp = head;
struct data *first = head;
do
{
struct data *next = temp->next;
if (temp->status)
{
if (prev == NULL)
{
// Delete head element
head = temp->next;
}
else
{
// Delete middle element
prev->next = temp->next;
}
free(temp);
}
else
{
prev = temp;
}
temp = next;
} while (temp != first);
if (prev == NULL)
{
// List is empty
return NULL;
}
return head;
}
Below statement is causing the problem
prev->next = temp->next; // what is prev here ?
It should be
if (temp != NULL && temp->next !=NULL && temp->status == true) {
prev = temp;//current node which you want to delete
temp->next = prev->next;//this statement should be done before next statement..current node next should be prev node next
prev->next = temp->next;//
free(temp);
temp = prev->next;
}

Linked list reverse function leads to infinite printing loop

I was writing a C code to reverse a link list. I got into one problem.
If I do not make my next pointer NULL my reverse function works fine, but if I make it null the linked list always keeps printing in the while loop.
Below is the correct program, which works fine.
But if I make *next = NULL, the display function will keep printing in the while loop.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
} *head;
/*************************************************************/
/* */
/* create - Function to create Nodes and add them at last */
/* */
/*************************************************************/
int create(int data)
{
struct node *temp,*ptr = NULL;
//int data = 0;
ptr = head;
//Printf(" Enter the Data for Node : ");
//scanf(" %d ", data);
temp = (struct node *)malloc(sizeof(struct node));
if (ptr == NULL) {
// this is the first node
temp->next = NULL;
temp->data = data;
head = temp;
} else {
// this is not the first node
while (ptr != NULL) {
if (ptr->next == NULL) {
temp->next = NULL;
temp->data = data;
ptr->next = temp;
break;
}
ptr = ptr->next;
}
}
return 0;
}
/*************************************************************/
/* */
/* create_in_front - Function to add Node in Front */
/* */
/*************************************************************/
int create_in_front(int data)
{
struct node *temp,*ptr = NULL;
ptr = head;
temp = (struct node *)malloc(sizeof(struct node));
if (ptr == NULL) {
// this is the first node
temp->next = NULL;
temp->data = data;
head = temp;
} else {
// this is not the first node
temp->next = ptr->next;
temp->data = data;
head = temp;
}
return 0;
}
/*************************************************************/
/* */
/* create_in_between - Function to add Node in between nodes*/
/* */
/*************************************************************/
int create_in_between(int data,int pos)
{
struct node *temp, *ptr = NULL;
int i = 0;
ptr = head;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = data;
for (i = 0; i < pos; i++) {
if (i == pos-1) {
temp->next = ptr->next;
ptr->next = temp;
}
ptr = ptr->next;
}
return 0;
}
/*************************************************************/
/* */
/* delete_in_between - Function to add Node in between nodes*/
/* */
/*************************************************************/
delete_in_between(int pos)
{
struct node *ptr, *prev = NULL;
ptr = head;
int i = 0;
for (i = 0; i < pos; i++) {
if (i == pos-1) {
prev = ptr->next;
free(ptr);
break;
}
prev = ptr;
ptr = ptr->next;
}
return 0;
}
/*************************************************************/
/* */
/* reverse - Function to reverse link list */
/* */
/*************************************************************/
int reverse()
{
struct node *prev = NULL;
struct node *curr = head;
struct node *next = NULL;
curr = head;
while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
return 0;
}
/*************************************************************/
/* */
/* display - Function to diplay link list */
/* */
/*************************************************************/
// Function to display Link List
int display()
{
struct node *temp = head;
while (temp != NULL) {
printf("%d->",temp->data);
temp = temp->next;
}
return 0;
}
int main()
{
create(10);
create(20);
create(30);
create(40);
create(50);
create_in_front(34);
create_in_between(55,2);
//delete_in_between(4);
reverse();
display();
return 0;
}
Let me know the logic behind this.
Function create_in_front() is bogus: temp->next = ptr->next; should be changed to temp->next = ptr;
create_in_between() does not handle the case of pos==0.
delete_in_between() is completely dysfunctional: the node is frees but its predecessor still points to it.
reverse() seems correct to me, it could be simplified this way:
int reverse() {
struct node *prev = NULL;
struct node *curr = head;
while (curr != NULL) {
struct node *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
return 0;
}
The problem seems unrelated to your modifying the reverse() function, maybe a side effect of bugs in the other functions.
Your reverse() function seems correct, but the rest of the code is somewhat overcomplicated. Try something like this:
void create(int data) {
struct node *temp = malloc(sizeof(struct node));
if (temp != NULL) {
temp->next = NULL;
temp->data = data;
if (head == NULL) { // this is the first node
head = temp;
} else {
// this is not the first node
struct node *last = head;
while (last->next)
last = last->next;
last->next = temp;
}
}
}
void create_in_front(int data) {
struct node *temp = malloc(sizeof(struct node));
if (temp != NULL) {
temp->next = head;
temp->data = data;
head = temp;
}
}

Resources