Find and remove loops in a Linked list - c

Below I have written a program to detect and and remove a loop from list using C. I am getting a runtime error, but I am not able to find it?
#include <stdio.h>
#include <stdlib.h>
//node definition
struct node {
int key;
struct node *next;
};
// This function will make a new node
struct node *newNode(int key) {
struct node *temp = (struct node*)(malloc)(sizeof(struct node));
temp->key = key;
temp->next = NULL;
}
//This function will detect and remove a loop from linked list
void detect(struct node *head) {
struct node *slow = head;
struct node *fast = head->next;
while (fast && fast->next) {
if (slow == fast)
break;
slow = slow->next;
fast = fast->next->next;
}
if (slow == fast) {
slow = head;
while (slow != fast->next) {
slow = slow->next;
fast = fast->next;
}
fast->next = NULL;
}
}
//This function will print list
void print(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d ", temp->key);
temp = temp->next;
}
}
//This function is driver method
int main() {
struct node *head = newNode(10);
head->next = newNode(20);
head->next->next = newNode(30);
head->next->next->next = newNode(40);
head->next->next->next->next = newNode(50);
head->next->next->next->next->next = head->next->next;
detect(head);
print(head);
return 0;
}

The function newNode does not return anything, which is not consistent with the prototype.
Looking at your code, you should add return temp at the end of the function.

Related

Linked list implementation in C(printing only last two nodes)

#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node *next;
};
void addLast(struct node **head, int value);
void printAll(struct node *head);
struct node *head1 = NULL;
int main() {
addLast(&head1, 10);
addLast(&head1, 20);
addLast(&head1, 30);
addLast(&head1, 40);
printAll(head1);
return 0;
}
void addLast(struct node **head, int value) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
(*head)->next = NULL;
} else {
struct node **temp = head;
while ((*temp)->next != NULL) {
*temp = (*temp)->next;
}
(*temp)->next = newNode;
newNode->next = NULL;
}
}
void printAll(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d->", temp->data);
temp = temp->next;
}
printf("\n");
}
addLast() will append the new node at the end of the list, with printAll(), I am printing entire list.
Every time when I am printing the list, I can only see the last two nodes.
Can anyone please help, why loop is not iterating over entire list ?
The function addLast is too complicated and as result is wrong due to this statement
*temp = (*temp)->next;
in the while loop. It always changes the head node.
Define the function the following way
int addLast( struct node **head, int value )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = value;
newNode->next = NULL:
while( *head ) head = &( *head )->next;
*head = newNode;
}
return success;
}
Take into account that there is no need to declare the variable head1 as global. It is better to declare it inside the function main.
Also all the allocated memory should be freed before exiting the program.

Freeing linked list crashes when on last node

This is a continuation of a problem I posted yesterday, which I thought was solved, but turns out another problem has been encountered with the way I iterate through the loop and its exit condition. I felt a new question thread might be more appropriate.
The following freeAllListMembers() function seems to be working, up until the last iteration of the loop because it is trying to free "temp" but temp has already been freed, what method can I use to exit this loop and keep it from running once more, everything I have tried doesn't seem to be working.
thanks for any insight
int main() {
struct node *head = NULL;
createList(&head);
//do stuff with list
freeAllListMembers(&head);
return 0;
}
int createList(struct node **head) {
struct node *newNode= NULL;
for(int I = 0; I < 100; I++)
{
struct node *node = (struct node*)malloc(sizeof(struct node));
node->data = someData;
node->next = NULL;
//if we havent created an initial start node, create it
if (*head == NULL)
{
*head = node;
}
//otherwise, navigate to the end of the list to add a new node
else
{
newNode = *head;
while (newNode->next != NULL){
newNode = newNode->next;
}
newNode->next = node;
}
}
return 0;
}
void freeAllListMembers(struct node **head){
struct node *temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp);
}
return;
}
Cleaning up the example given to remove some small human errors, the program compiles OK, and I can step through OK in GDB. It basically ran after it compiled without errors
#include <malloc.h>
#define someData 12345
struct node
{
int data;
struct node* next;
};
int createList(struct node **head )
{
struct node *newNode= NULL;
int i;
for( i = 0; i < 100; i++)
{
struct node *node = (struct node*)malloc(sizeof(struct node));
node->data = someData;
node->next = NULL;
//if we havent created an initial start node, create it
if (*head == NULL)
{
*head = node;
}
//otherwise, navigate to the end of the list to add a new node
else
{
newNode = *head;
while (newNode->next != NULL){
newNode = newNode->next;
}
newNode->next = node;
}
}
return 0;
}
void freeAllListMembers(struct node **head)
{
struct node *temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp);
}
return;
}
int main()
{
struct node *head = NULL;
createList(&head);
//do stuff with list
freeAllListMembers(&head);
return 0;
}
I can only guess that you lost whatever your bug was in the 'abstraction' process

C list->data doesnt show on terminal

The console doesnt show the data from my list node.I filled it with chars that i took from a text File.
#include<stdio.h>
#include<stdlib.h>
struct list_node{
char data;
struct list_node* next;
};
typedef struct list_node* node;
node insert_right(node list,char data)
{
node new_node = (node) malloc(sizeof(struct list_node));
new_node->data = data;
new_node->next = list->next;
list->next = new_node;
return new_node;
}
int main()
{
FILE *fr = fopen("dat1.txt","r");
node list = (node) malloc(sizeof(struct list_node));
int i;
while((i = fgetc(fr)) != EOF){
insert_right(list,i);
}
printf("%c",list->data);
}
The main problem i think would be in the insert method.
You are creating a linked list. Each node you create needs to point to either NULL or the next node. You were not quite making the links. Also you were not getting the new_node you you were returning. Also when printing out a list you have to go through each node (like an array).
#include<stdio.h>
#include<stdlib.h>
struct list_node{
char data;
struct list_node* next;
};
typedef struct list_node* node;
node insert_right(node list,char data)
{
node new_node = (node) malloc(sizeof(struct list_node));
new_node->data = data;
list->next = new_node;
new_node->next = NULL;
return new_node;
}
int main()
{
FILE *fr = fopen("dat1.txt","r");
node list = (node) malloc(sizeof(struct list_node));
int i;
node next = list;
while((i = fgetc(fr)) != EOF){
next = insert_right(next,i);
}
node print = list;
while(print != NULL){
printf("%c",print->data);
print = print->next;
}
}
You are allocating memory to a node called list, but yet you do not initialize any value for data, it can be garbage or any character that does not show up in the console.
When you insert a new value, a new node is created and the first one, the "head" so to speak, is still uninitialized even though it is pointing to a second node that has a meaningful data there.
This is your list:
// Node Y (X) indicates the Y-th node that has a X value.
Node1 (garbage) -> Node2 (value) -> Node3 (value) -> garbage
The last node of your list (which is also the first when you create it) should be pointing to NULL instead of being uninitialized.
I am also pretty sure that your list is poor-implemented because the new elements are always being pointed by list, so you lose track of the ones you created before.
Here is a better version, in my opinion:
#include<stdio.h>
#include<stdlib.h>
struct list_node{
char data;
struct list_node* next;
};
typedef struct list_node* node;
void insert_right(node list,char data)
{
node new_node = (node) malloc(sizeof(struct list_node));
node temp = list;
// It runs through the list until it reaches the last node
while(temp->next != NULL) temp = temp->next;
temp->data = data;
temp->next = new_node;
new_node->next = NULL;
}
int main()
{
FILE *fr = fopen("dat1.txt","r");
// List points to only the first element of the list.
node list = (node) malloc(sizeof(struct list_node));
list->next = NULL;
int i;
while((i = fgetc(fr)) != EOF){
insert_right(list,i);
}
while(list != NULL) {
printf("%c",list->data);
list = list->next;
}
}
#include <stdio.h>
#include <stdlib.h>
struct list_node {
char data;
struct list_node* next;
};
int main()
{
FILE *fr = fopen("dat1.txt","r");
struct list_node *list = malloc(sizeof(*list)), *pos = list;
int i;
while ((i = fgetc(fr)) != EOF) {
pos->data = i;
pos->next = malloc(sizeof(*list->next));
pos = pos->next;
}
pos->next = NULL;
while (list->next) {
printf("%c ", list->data);
free(list); /* important!!!! */
list = list->next;
}
putchar('\n');
return 0;
}

Implementing Simple Linked List

Hi I wish to implement a simple linked list and all the values to the end of the list. As simple as that but I am not able to do so. Can you please tell me where I am doing it wrong ? Initially I am declaring a pointer and assigning NULL value to it. Later in each iteration I am allocating memory to the pointer that was initially NULL.
#include <stdio.h>
#include <malloc.h>
struct node{
int a;
struct node* next;
};
struct node* insert(struct node* start,int value);
void print(struct node* head);
int main()
{
int a;
struct node* head = NULL;
while(scanf("%d",&a) != EOF)//taking input
{
head = insert(head,a);
print(head);
}
return 0;
}
struct node* insert(struct node* start,int value)
{
struct node* head = start;
while(start != NULL)
{
start = start->next;//getting upto the end of the linked list
}
start = (struct node*)malloc(sizeof(struct node));//allocating memory at the end
start->a = value;
start->next = NULL;
if(head == NULL)
{
return start;//for the base case when list is initally empty
}
return head;
}
void print(struct node* head)
{
while(head != NULL)
{
printf("%d\n",head->a);
head = head->next;
}
return;
}
You're losing your linkage between your tail and your new node, try this instead
struct node* insert(struct node* head,int value)
{
struct node* tail = head;
while(tail != NULL && tail->next != NULL)
{
tail= tail->next;//getting upto the end of the linked list
}
struct node* start = (struct node*)malloc(sizeof(struct node));//allocating memory at the end
start->a = value;
start->next = NULL;
if(head == NULL)
{
return start;//for the base case when list is initally empty
}
else
{
tail->next = start;
}
return head;
}
struct node* insert(struct node* start,int value){
struct node* head = start;
struct node* np = (struct node*)malloc(sizeof(struct node));
np->a = value;
np->next = NULL;
if(head == NULL)
return np;
while(start->next != NULL){
start = start->next;
}
start->next = np;
return head;
}
What makes the approach I am using buggy ?
nodeX
|
+a
|
+next(address to OtherX)
nodeX.next = new_node;//update link(case of OK)
tempPointer = nodeX.next;//address to OtherX set to tempPointer
tempPointer = new_node;//contents of tempPointer changed, but orignal (nodeX.next not change)

Want to make linked list function that deletes first Node

This is my code. I made three functions for adding a new node, inserting a new node between two others, and one deleting, but I dont know how to delete the first node. I dont even have any idea.
#include <stdlib.h>
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
void insert(Node* insertafter, Node* newNode);
void add(Node* llist,Node* newNode);
void deleteafter(Node *llist);
void deletefirts();
int main()
{
struct Node *llist;
struct Node *newNode;
newNode = (Node*)malloc(sizeof(struct Node));
newNode->data = 13;
struct Node *newNode2;
newNode2 = (Node*)malloc(sizeof(struct Node));
newNode2->data = 14;
llist = (Node*)malloc(sizeof(struct Node));
llist->data = 10;
llist->next = (Node*)malloc(sizeof(struct Node));
llist->next->data = 15;
llist->next->next = NULL;
insert(llist,newNode);
add(llist,newNode2);
if(llist->next == NULL)
printf("shecdoma");
struct Node *cursor = llist;
while (cursor != NULL)
{
printf("%d\n", cursor->data);
cursor = cursor->next;
}
system("pause");
return 0;
}
void insert(Node* insertafter, Node *newNode)
{
newNode->next = insertafter->next;
insertafter->next = newNode;
}
void add(Node* llist,Node *newNode)
{
if(llist->next == NULL)
{
llist->next = newNode;
newNode->next = NULL;
}
else
{
while(llist->next != NULL)
{
llist = llist->next;
}
add(llist,newNode);
}
void deleteafter(Node *llist)
{
if(llist->next != NUll)
llist->next = llist->next->next;
}
void deletefirst();
{
}
You can use something like:
void deletefirst (struct Node **head) {
struct Node *tmp = *head; // save old head for freeing.
if (tmp == NULL) return; // list empty? then do nothing.
*head = tmp->next; // advance head to second node.
free (tmp); // free old head.
}
You pass in the pointer to the head so that you can change it. Deleting nodes other than the first does not require this but deleting the first node does.
You set up a temporary pointer to the head so you free it, then you change the head to point to its next element. Then you free the old head and return.
void deleteFirst(Node** list)
{
Node* temp = *list;
if (*list != NULL)
{
*list = (*list)->next;
free(temp);
}
}

Resources