I am trying to program a simple text editor in C and I am using LinkedList. I have problems with the deleteEnd function. Where did I go wrong?
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
i store the character, and the coordinates of the character in a structure like this:
struct node {
struct node *previous;
char c;
int x;
int y;
struct node *next;
}*head;
This is called whenever a letter is typed in.
void characters(char typed, int xpos, int ypos) //assign values of a node
{
struct node *temp,*var,*temp2;
temp=(struct node *)malloc(sizeof(struct node));
temp->c=typed;
temp->x=xpos;
temp->y=ypos;
if(head==NULL)
{
head=temp;
head->next=NULL;
}
else
{
temp2=head;
while(temp2!=NULL)
{
var=temp2;
temp2=temp2->next;
}
temp2=temp;
var->next=temp2;
temp2->next=NULL;
}
}
Print the new node if there are changes.
void printer() //to print everything
{
struct node *temp;
temp=head;
while(temp!=NULL)
{
gotoxy(temp->x,temp->y);
printf("%c",temp->c);
temp=temp->next;
}
}
Now here, I do not know why the last element of the head won't be deleted.
void deletesEnd()
{
struct node *temp,*last;
temp=head;
while(temp!=NULL)
{
last=temp;
temp=temp->next;
}
if(last->previous== NULL)
{
free(temp);
head=NULL;
}
last=NULL;
temp->previous=last;
free(temp);
}
This is where it all begins.
main()
{
char c; //for storing the character
int x,y; //for the position of the character
clrscr();
for(;;)
{
c=getch();
x=wherex();
y=wherey();
if(c==0x1b) //escape for exit
{
exit(0);
}
else if (c==8) //for backspace
{
deletesEnd();
// clrscr();
printer();
}
else //normal characters
{
characters(c,x,y);
printer();
}
}
}
Try this :
void deletesEnd()
{
struct node *temp,*last;
temp=head;
last = temp;
while(temp != NULL && temp->next!=NULL)
{
last=temp;
temp=temp->next;
}
if(last == temp)
{
free(temp);
head=NULL;
} else {
free(last->next);
last->next = NULL;
}
In your algorithm, you try to work with a NULL pointer, so you can't get to the previous node I think.
For finding the last node in the list, the simplest is to loop until the next pointer is NULL.
For deletion at the end you also need to keep track of the next-to-last node, and it could look something like this:
struct node *prev, *curr;
for (prev = NULL, curr = head; curr->next != NULL; prev = curr, curr = curr->next)
;
/* `curr` is now the last node in the list, `prev` is the next-to-last node */
if (prev != NULL)
prev->next = NULL; /* Unlink the last node */
else
head = NULL; /* List was only one node long */
/* Free the memory for the last node */
free(curr);
If you properly kept the list double-linked the loop would be even easier, as you don't have to keep track of the next-to-last node anymore:
struct node *node;
for (node = head; node->next != NULL; node = node->next)
;
/* `node` is now the last node in the list */
if (node->previous != NULL)
node->previous->next = NULL; /* Unlink last node */
else
head = NULL; /* List was only one node long */
/* Free the memory for the last node */
free(curr);
And keeping track of the tail from the start will make this much simpler:
if (tail != NULL)
{
struct node *node = tail;
if (node->previous != NULL)
{
node->previous->next = NULL; /* Unlink last node */
tail = node->previous;
}
else
head = tail = NULL; /* Removing last node in list */
free(node);
}
try this
void deletesEnd()
{
struct node *temp,*last;
temp=head;
while(temp!=NULL)
{
last=temp;
temp=temp->next;
}
if(last->previous== NULL)
{
free(temp);
head=NULL;
}
last->previous->next = NULL;
last=NULL;
temp->previous=last;
free(temp);
}
you see, you've put the last element in the list in last, and then did last=NULL; which just put null in last variable. temp is already NULL so temp->previous=last; has no meaning.
you need that the last item's previous item will point to NULL as the line
last->previous->next = NULL;
does
Linkedlist work with only two simple generic rules...
First Make the link
Second after make, Break the link.
Just check the condition...
If you have empty list
if list has only one node
if it has more then one node
try these rules. I hope it will work for you.
This line :
temp->previous=last;
will cause you problems since temp is null at that point already (since it was the termination condition in the while loop).
Change your method to :
void deletesEnd()
{
struct node *temp,*last;
temp=head;
while(temp!=NULL)
{
last=temp;
temp=temp->next;
}
if(last != NULL) {
if (last->previous != null) { // Last element gonig to be deleted so the previous element if exists should point his next to null (end of list)
last->previous->next = null;
}
free(last); // Free the last element in the list
}
}
Related
I need a little help removing unique characters in a doubly linked list in C. So here's the logic I tried implementing: I counted the occurrence of each character in the doubly linked list. If it's occurrence is 1 time, then it is unique element and needs to be deleted. I'll be repeating the process for all elements. But my code in remove_unique_dll() function isn't working properly, please help me fix it. Here's my code-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char data;
struct node *next;
struct node *prev;
};
struct node *head, *tail = NULL; //Represent the head and tail of the doubly linked list
int len;
void addNode(char data)
{
struct node *newNode = (struct node*) malloc(sizeof(struct node)); //Create new node
newNode->data = data;
if (head == NULL)
{ //If dll is empty
head = tail = newNode; //Both head and tail will point to newNode
head->prev = NULL; //head's previous will point to NULL
tail->next = NULL; //tail's next will point to NULL, as it is the last node of the list
}
else
{
tail->next = newNode; //newNode will be added after tail such that tail's next points to newNode
newNode->prev = tail; //newNode's previous will point to tail
tail = newNode; //newNode will become new tail
tail->next = NULL; //As it is last node, tail's next will point to NULL
}
}
void remove_unique_dll()
{
struct node *current = head;
struct node *next;
struct node *prev;
int cnt;
while (current != NULL)
{
next = current->next;
cnt = 1;
//printf("!%c ",next->data);
while (next != NULL)
{
if (next->data == current->data)
{
cnt += 1;
next = next->next;
}
else
next = next->next;
//printf("#%c %d %c\n",next->data,cnt,current->data);
}
if (cnt == 1)
{
prev = current->prev;
//printf("#%c %d",prev->data,cnt);
if (prev == NULL)
{
head = next;
}
else
{
prev->next = next;
}
if (next == NULL)
{
tail = prev;
}
else
{
next->prev = prev;
}
}
current = current->next;
//printf("#%c ",current->data);
}
head = current;
}
void display()
{
struct node *current = head; //head the global one
while (current != NULL)
{
printf("%c<->", current->data); //Prints each node by incrementing pointer.
current = current->next;
}
printf("NULL\n");
}
int main()
{
char s[100];
int i;
printf("Enter string: ");
scanf("%s", s);
len = strlen(s);
for (i = 0; i < len; i++)
{
addNode(s[i]);
}
printf("Doubly linked list: \n");
display();
remove_unique_dll();
printf("Doubly linked list after removing unique elements: \n");
display();
return 0;
}
The output is like this-
If you uncomment the printf() statements inside remove_unique_dll() you'll notice that no code below inner while loop is being executed after inner while loop ends. What's the issue here and what's the solution?
Sample input- aacb
Expected output- a<->a<->NULL
Some issues:
You shouldn't assign head = current at the end, because by then current is NULL
The next you use in the deletion part is not the successor of current, so this will make wrong links
As you progress through the list, every value is going to be regarded as unique at some point: when it is the last occurrence, you'll not find a duplicate anymore, as your logic only looks ahead, not backwards.
When you remove a node, you should free its memory.
Not a big issue, but there is no reason to really count the number of duplicates. Once you find the first duplicate, there is no reason to look for another.
You should really isolate the different steps of the algorithm in separate functions, so you can debug and test each of those features separately and also better understand your code.
Also, to check for duplicates, you might want to use the following fact: if the first occurrence of a value in a list is the same node as the last occurrence of that value, then you know it is unique. As your list is doubly linked, you can use a backwards traversal to find the last occurrence (and a forward traversal to find the first occurrence).
Here is some suggested code:
struct node* findFirstNode(char data) {
struct node *current = head;
while (current != NULL && current->data != data) {
current = current->next;
}
return current;
}
struct node* findLastNode(char data) {
struct node *current = tail;
while (current != NULL && current->data != data) {
current = current->prev;
}
return current;
}
void removeNode(struct node *current) {
if (current->prev == NULL) {
head = current->next;
} else {
current->prev->next = current->next;
}
if (current->next == NULL) {
tail = current->prev;
} else {
current->next->prev = current->prev;
}
free(current);
}
void remove_unique_dll() {
struct node *current = head;
struct node *next;
while (current != NULL)
{
next = current->next;
if (findFirstNode(current->data) == findLastNode(current->data)) {
removeNode(current);
}
current = next;
}
}
You have at least three errors.
After counting the number of occurrences of an item, you use next in several places. However, next has been used to iterate through the list. It was moved to the end and is now a null pointer. You can either reset it with next = current->next; or you can change the places that use next to current->next.
At the end of remove_unique_dll, you have head=current;. There is no reason to update head at this point. Whenever the first node was removed from the list, earlier code in remove_unique_dll updated head. So it is already updated. Delete the line head=current;.
That will leave code that deletes all but one occurrence of each item. However, based on your sample output, you want to leave multiple occurrences of items for which there are multiple occurrences. For that, you need to rethink your logic in remove_unique_dll about deciding which nodes to delete. When it sees the first a, it scans the remainder of the list and sees the second, so it does not delete the first a. When it sees the second a, it scans the remainder of the list and does not see a duplicate, so it deletes the second a. You need to change that.
Let's consider your code step by step.
It seems you think that in this declaration
struct node *head, *tail = NULL; //Represent the head and tail of the doubly linked list
the both pointers head and tail are explicitly initialized by NULL. Actually only the pointer tail is explicitly initialized by NULL. The pointer head is initialized implicitly as a null pointer only due to placing the declaration in file scope. It to place such a declaration in a block scope then the pointer head will be uninitialized.
Instead you should write
struct node *head = NULL, *tail = NULL; //Represent the head and tail of the doubly linked list
Also it is a very bad approach when the functions depend on these global variables. In this case you will be unable to have more than one list in a program.
Also the declaration of the variable len that is used only in main as a global variable
int len;
also a bad idea. And moreover this declaration is redundant.
You need to define one more structure that will contain pointers head and tail as data members as for example
struct list
{
struct node *head;
struct node *tail;
};
The function addNode can invoke undefined behavior when a new node can not be allocated
void addNode(char data)
{
struct node *newNode = (struct node*) malloc(sizeof(struct node)); //Create new node
//...
You should check whether a node is allocated successfully and only in this case change its data members. And you should report the caller whether a node is created or not.
So the function should return an integer that will report an success or failure.
In the function remove_unique_dll after this while loop
while (next != NULL)
{
if (next->data == current->data)
{
cnt += 1;
next = next->next;
}
else
next = next->next;
//printf("#%c %d %c\n",next->data,cnt,current->data);
}
if cnt is equal to 1
if (cnt == 1)
//..
then the pointer next is equal to NULL. And using the pointer next after that like
if (prev == NULL)
{
head = next;
}
else
{
prev->next = next;
}
is wrong.
Also you need to check whether there is a preceding node with the same value as the value of the current node. Otherwise you can remove a node that is not a unique because after it there are no nodes with the same value.
And this statement
head = current;
does not make sense because after the outer while loop
while (current != NULL)
the pointer current is equal to NULL.
Pay attention that the function will be more useful for users if it will return the number of removed unique elements.
Here is a demonstration program that shows how the list and the function remove_unique_dll can be defined.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char data;
struct node *next;
struct node *prev;
};
struct list
{
struct node *head;
struct node *tail;
};
int addNode( struct list *list, char data )
{
struct node *node = malloc( sizeof( *node ) );
int success = node != NULL;
if (success)
{
node->data = data;
node->next = NULL;
node->prev = list->tail;
if (list->head == NULL)
{
list->head = node;
}
else
{
list->tail->next = node;
}
list->tail = node;
}
return success;
}
size_t remove_unique_dll( struct list *list )
{
size_t removed = 0;
for ( struct node *current = list->head; current != NULL; )
{
struct node *prev = current->prev;
while (prev != NULL && prev->data != current->data)
{
prev = prev->prev;
}
if (prev == NULL)
{
// there is no preceding node with the same value
// so the current node is possibly unique
struct node *next = current->next;
while (next != NULL && next->data != current->data)
{
next = next->next;
}
if (next == NULL)
{
// the current node is indeed unique
struct node *to_delete = current;
if (current->prev != NULL)
{
current->prev->next = current->next;
}
else
{
list->head = current->next;
}
if (current->next != NULL)
{
current->next->prev = current->prev;
}
else
{
list->tail = current->prev;
}
current = current->next;
free( to_delete );
++removed;
}
else
{
current = current->next;
}
}
else
{
current = current->next;
}
}
return removed;
}
void display( const struct list *list )
{
for (const node *current = list->head; current != NULL; current = current->next)
{
printf( "%c<->", current->data );
}
puts( "null" );
}
int main()
{
struct list list = { .head = NULL, .tail = NULL };
const char *s = "aabc";
for (const char *p = s; *p != '\0'; ++p)
{
addNode( &list, *p );
}
printf( "Doubly linked list:\n" );
display( &list );
size_t removed = remove_unique_dll( &list );
printf( "There are removed %zu unique value(s) in the list.\n", removed );
printf( "Doubly linked list after removing unique elements:\n" );
display( &list );
}
The program output is
Doubly linked list:
a<->a<->b<->c<->null
There are removed 2 unique value(s) in the list.
Doubly linked list after removing unique elements:
a<->a<->null
You will need at least to write one more function that will free all the allocated memory when the list will not be required any more.
I have the following function for removing a node from a linked list at a specified position:
void deleteNodeAt(node *head, int pos) {
if(head==NULL)
return;
node *temp=malloc(sizeof(node));
int index=0;
while(head!=NULL) {
if(index==pos-1)
temp=head;
if(index==pos) {
temp->next=head->next;
head=head->next;
free(temp);
temp=NULL;
}
else
head=head->next;
index++;
}
}
It works fine if I don't try to free the temp node or if I set it to NULL, but calling free (temp) will break the function. I can't figure out what I'm doing wrong.
First I don't understand why you do a malloc in code that is supposed to free a node.
Further you are freeing the wrong node. The node you wanted to free is head - it's not temp.
Try like:
void deleteNodeAt(node *head, int pos)
{
if(head==NULL)
return;
node *temp;
int index=0;
while(head!=NULL)
{
if(index==pos-1)
temp=head;
if(index==pos)
{
temp->next=head->next;
free(head);
// Done - the node has been free'd so just return
return;
}
head=head->next;
index++;
}
}
However, there is still a problem.
Consider this:
What will happen when pos is zero (i.e. when you try to remove the current head
Answer: You will use an uninitialized temp. That's bad. Further, how will the caller know that head has changed? You need some extra code for handling this case.
Assuming pos starts at 0 for the head of the list, you need to pass a pointer to head in order to delete pos 0. After the call, the head will have changed, so any other pointer to the list would be invalid.
#define START_OF_LIST 0
void deleteNodeAt(node **phead, int pos)
{
if (pos < START_OF_LIST || !*phead)
return; /* bad pos or empty list, always check input */
node *prev = *phead;
if (pos == START_OF_LIST) {
/* special case - delete head of list */
*phead = (*phead)->next;
free(prev);
return;
}
while (1) {
node * temp = prev->next;
if (!temp) /* Not enough elements in list */
return;
pos--;
if(pos == START_OF_LIST) {
prev->next = temp->next; /* unlink temp */
free(temp);
return;
}
prev = temp; /* On to the next! */
}
}
I am studying for a test and I am having trouble debugging my linked list practice exam questions. I am having issues with the different modification to the delete functions he wants us to do. Specifically, my deleteEven is an endless look and my deleteNthNode does not work as it is supposed to. Because I am struggling with these two I'm not even sure where to start with deleting every other element in the list. I'd appreciate the help as I want to completely understand this topic before I move to stacks and queues! :)
Below is my code:
/*
Q1:
Try implementing the functions shown in class on your own:
check: node creation
check: insertion at the end of a linked list,
check: insertion at the head of a linked list,
check: a list printing function.
Q2:
check: Write a recursive printList() function.
Q3:
check: Write a recursive tailInsert() function.
Q4:
check: Write a function that inserts nodes at the beginning of the linked list.
Q5:
check: Write a recursive function that prints a linked list in reverse order.
The function signature is: void printReverse(node *head);
Q6:
check: Write an iterative destroyList() function that frees all the nodes in a linked list.
Q7:
check: Now implement destroyList() recursively.
Q8:
- Write a function that deletes the nth element from a linked list.
If the linked list doesn't even have n nodes, don't delete any of them.
The function signature is: node *deleteNth(node *head, int n).
- Try implementing the function iteratively and recursively.
- (In terms of how to interpret n, you can start counting your nodes from zero or one; your choice.)
Q9:
- Write a function that deletes every other element in a linked list.
- (Try writing it both ways: one where it starts deleting at the head of the list,
- and one where it starts deleting at the element just after the head of the list.)
- Can you write this both iteratively and recursively?
Q10:
- Write a function that deletes all even integers from a linked list.
Q11:
- Write a function that takes a sorted linked list and an element to be inserted into that linked list,
and inserts the element in sorted order.
The function signature is: node *insertSorted(node *head, int n);
Q12:
- One of the problems with the first insertNode() function from today is that it
requires us to call it using head = insertNode(head, i).
That's a bit dangerous, because we could forget the "head =" part very easily.
Re-write the function so that it takes a pointer to head,
thereby allowing it to directly modify the contents of head without any need for a return value.
The function signature is: void insertNode(node **head, int data).
The function will be called using insertNode(&head, i).
*/
//come back to
#include <stdio.h>
#include <stdlib.h>
// Basic linked list node struct; contains 'data' and 'next' pointer.
// What happens if we type "node *next" instead of "struct node *next"?
typedef struct node
{
// data field
int data;
// the next node in the list
struct node *next;
} node;
// Allocate a new node. Initialize its fields. Return the pointer.
// We call this from our insertion functions.
node *createNode(int data)
{
node *ptr = NULL;
ptr = malloc(sizeof(node));
if(ptr == NULL)
{
printf("space could not be allocated\n");
return NULL;
}
ptr->data = data;
ptr->next = NULL;
return ptr;
}
// Insert into the end of the linked list. Return the head of the linked list.
// (What is the order (Big-Oh) of this function?)
/*
node *insertNode(node *head, int data)
{
node *temp;
if (head == NULL)
return createNode(data);
for(temp = head; temp->next != NULL; temp = temp->next)
;
temp->next = createNode(data);
return head;
}
*/
node *insertNodeFront(node *head, int data)
{
node *temp;
if(head == NULL)
return createNode(data);
temp = createNode(data);
temp->next = head;
return temp;
}
// Simple function to print the contents of a linked list.
void printList(node *head)
{
if (head == NULL)
{
printf("Empty List\n");
return;
}
for(; head != NULL; head = head->next)
printf("%d ", head->data);
printf("\n");
}
void printListRecursiveHelper(node *head)
{
if (head == NULL)
return;
printf("%d%c", head->data, (head->next == NULL) ? '\n' : ' ');
printListRecursiveHelper(head->next);
}
void printListRecursive(node *head)
{
if (head == NULL)
{
printf("empty list\n");
return;
}
printListRecursiveHelper(head);
}
// Q3: - Write a recursive tailInsert() function.
node *tailInsert(node *head, int data)
{
if(head->next == NULL)
{
node *temp;
temp = createNode(data);
temp->next = NULL;
head->next = temp;
return temp;
}
return tailInsert(head->next, data);
}
//Q5: Write a recursive function that prints a linked list in reverse order.
void printReverse(node *head)
{
if (head == NULL)
return;
printReverse(head->next);
printf("%d ", head->data);
}
// Q6: - Write an iterative destroyList() function that frees all the nodes in a linked list.
// Got code from internet, memorize it
/* Function to delete the entire linked list */
void destroyList (struct node** head)
{
struct node* current = *head;
struct node* next;
while (current != NULL)
{
next = current->next;
free(current);
current = next;
}
*head = NULL;
}
// Q7: - Now implement destroyList() recursively.
// Look up online, need to examine why it deson't work
node *destroyListRecursive(node * head)
{
if (head != NULL)
{
destroyListRecursive(head->next);
free(head);
}
return NULL;
}
/* Q8:
- Write a function that deletes the nth element from a linked list.
- If the linked list doesn't even have n nodes, don't delete any of them.
- Try implementing the function iteratively and recursively.
- (In terms of how to interpret n, you can start counting your nodes from zero or one; your choice.)
*/
node *deleteNth(node *head, int n)
{
/*
int i;
node*current;
node *prev;
current = head;
while(i = 0; i < n; i++)
{
current = current->next;
}
prev = current;
current = head->next->next;
*/
return head;
}
/*
Q9:
- Write a function that deletes every other element in a linked list.
- (Try writing it both ways: one where it starts deleting at the head of the list,
- and one where it starts deleting at the element just after the head of the list.)
- Can you write this both iteratively and recursively?
*/
/* deletes alternate nodes of a list starting with head */
//got code from http://www.geeksforgeeks.org/delete-alternate-nodes-of-a-linked-list/
void deleteAltHead(struct node *head)
{
if (head == NULL)
return;
struct node *node = head->next;
if (node == NULL)
return;
/* Change the next link of head */
head->next = node->next;
/* free memory allocated for node */
free(node);
/* Recursively call for the new next of head */
deleteAltHead(head->next);
}
void deleteOtherTail()
{
}
//Q10: - Write a function that deletes all even integers from a linked list.
void deleteEvenInts(node **head)
{
}
// Q11: - Write a function that takes a sorted linked list and an element to be inserted into that linked list,
// and inserts the element in sorted order.
node *insertSorted(node *head, int n)
{
struct node *current;
struct node *newNode = createNode(n);
/* Special case for the head end */
if (head == NULL || head->data >= newNode->data)
{
newNode->next = head;
head = newNode;
}
else
{
/* Locate the node before the point of insertion */
current = head;
while (current->next != NULL &&
current->next->data < newNode->data)
{
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
return current;
//or should it return head?
}
// Q12: Re-write the insertNode() function so that it takes a pointer to head
void insertNode(node **head, int data)
{
node *newNode = createNode(data);
while (*head != NULL)
{
head = &(*head)->next;
}
newNode->next = *head;
*head = newNode;
}
// Q10: Write a function that deletes all even integers from a linked list.
void deleteEven(node **head)
{
node *current = *head;
node *next = current;
node *prev = NULL;
for ( ; current != NULL; )
{
next = current->next;
if( current->data %2)
{
if(prev != NULL)
{
prev->next = next;
free(current);
current = next;
}
else
{
free(current);
current = next;
}
}
else
{
prev = current;
current = next;
}
}
}
//Q8: Write a function that deletes the nth element from a linked list. If the linked list doesn't even have n nodes, don't delete any of them.
node *deleteNthNode(node *head, int n)
{
int i = 0;
int nBigger = 0;
node *current = head;
node *prev = current;
for ( i = 0; i < n; i++)
{
prev = current;
current = current->next;
if (current == NULL)
{
nBigger = 1;
}
}
if(nBigger == 1)
{
return head;
}
prev = current->next;
free(current);
return head;
}
int main(void)
{
int i, r;
// The head of our linked list. If we don't initialize it to NULL, our
// insertNode() function might segfault.
node *head = NULL;
srand(time(NULL));
// Populate the linked list with random integers. We are inserting into the
// head of the list each time.
for (i = 0; i < 10; i++)
{
printf("Inserting %d...\n", r = rand() % 20 + 1);
insertNode(&head, r);
}
head = insertNodeFront(head, 1);
tailInsert(head, 5);
// Print the linked list.
printList(head);
printf("\n");
printReverse(head);
printf("\n\n");
// Print the linked list using our recursive function.
printListRecursive(head);
//destroyList(&head);
deleteAltHead(head);
printf("\n");
printList(head);
{
if (head == NULL)
return;
struct node *node = head->next;
if (node == NULL)
return;
/* Change the next link of head */
head->next = node->next;
/* free memory allocated for node */
free(node);
/* Recursively call for the new next of head */
}
deleteEven(&head);
// head = destroyListRecursive(head);
printf("\n");
printList(head);
node *head2 = NULL;
insertNode(&head2, 1);
insertNode(&head2, 2);
insertNode(&head2, 4);
printf("\n");
printList(head2);
insertSorted(head2, 3);
printf("\n");
deleteNthNode(head, 1);
printList(head2);
//destroyListRecursive(head2);
system("PAUSE");
return 0;
}
While inserting node at end in linked list ,my code is running in infinite loop.
IDE Used-Eclipse
64 bit OS
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int info;
struct Node *next;
}node;
node *head;
node *ptr1;
void insert(int x);
void show();
int main()
{
int i,x,n;
puts("Enter number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
puts("Enter elements");
scanf("%d",&x);
insert(x);
}
show();
return 0;
}
//To insert the data in linked list
void insert(int x)
{
node *ptr;
ptr1=head;
ptr=(node*)malloc(sizeof(node));
ptr->info=x;
if(head==NULL)
{
ptr->next=head;
head=ptr;
}
else
{
ptr1->next=NULL;
ptr1=ptr;
}
}
//To print the details of list
//Unable to figure out this function
void show()
{
while(ptr1->next!=NULL)
{
printf("%d\n",ptr1->info);
ptr1=ptr1->next;
}
}
The ptr1 is set to head each time your code enters the insert function then setting it to ptr in the else subsection but nothing pointing to any previous items.
Here is an example in case you need one.
typedef struct Node
{
int info;
struct Node *next;
}node;
node *head = NULL;
void insert(int x);
void show();
int main()
{
int i,x,n;
puts("Enter number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
puts("Enter elements");
scanf("%d",&x);
insert(x);
}
show();
return 0;
}
void insert(int x)
{
node *ptr = (node*)malloc(sizeof(node));
ptr->info=x;
ptr->next=head; /* this will always add the new entry at the beginning of the list all you need it to initialize the head to NULL*/
head = ptr; /* move the head so that it points to the newly created list element */
}
void show()
{
node *ptr1 = head;
printf("%d\n",ptr1->info); /* print the head */
while(ptr1->next!=NULL) /* now walk the list remember it first looks if the next pointer in the list is null first then it jumps on next element in case it is not*/
{
ptr1=ptr1->next;
printf("%d\n",ptr1->info);
}
}
Remember to create a function to free up the list elements before exiting the main.
Your two functions can be simplified. A singly linked list is very easy to implement. I would also improve the functions by taking the list pointer as an argument, and in the case of insert() return the new head of the list: but get it working first! Note there is no reason or need to declare global variables when their only use is local to a function.
// insert new node at head of the list
void insert(int x) {
node *ptr = malloc(sizeof(node));
if (ptr == NULL) {
printf ("malloc failure\n");
exit (1);
}
ptr->info = x;
ptr->next = head; // append existing list
head = ptr; // new head of list
}
// show the linked list
void show() {
node *ptr = head; // start at head of list
while (ptr != NULL) {
printf("%d\n", ptr->info);
ptr = ptr->next; // follow the link chain
}
}
EDIT here is code to add to the tail of a linked list
// insert new node at tail of the list
void insert2(int x) {
node *tail = head;
node **last = &head;
node *ptr;
while (tail) {
last = &tail->next;
tail = tail->next;
}
ptr = malloc(sizeof(node));
if (ptr == NULL) {
printf ("malloc failure\n");
exit (1);
}
ptr->info = x;
ptr->next = NULL;
*last = ptr;
}
I am inserting node at the end of the list but my code is printing only the first element and running in infinite loop.
I am unable to figure out the error in my code.
typedef struct nodetype
{
int info;
struct nodetype* next;
}node;
node *head=NULL;
void insertatend(int x);//x is the key element.
void print();
void insertatend(int x)
{
node *ptr;
ptr=(node*)malloc(sizeof(node));
ptr->info=x;
if(head==NULL)
{
ptr->next=ptr;
head=ptr;
}
else
ptr->next=ptr;
}
void print() //To print the list
{
node *temp=head;
printf("List is-");
while(temp!=NULL)
{
printf("%d",temp->info);
temp=temp->next;
}
}
Consider your insert method (I will take head as a parameter here instead of a global)
void insertatend(node **hd, int x) {
node *ptr = NULL, *cur = NULL;
if (!(ptr = malloc(sizeof (node)))) {
return;
}
if (!*hd) {
*hd = ptr;
} else {
cur = *hd;
while (cur->next) {
cur = cur->next;
}
cur->next = ptr;
}
}
You need to traverse your list from the end to its back in order to perform the insertion correctly. (Hence the while loop in the above function).
Your "temp != NULL" will never become false after the insertion, because in that insertion you set the next pointer to itself, thus creating a link loop.
it should be more like this:
void insertatend(int x)
{
node *ptr;
ptr=malloc(sizeof(node)); //don't cast pointers returned by malloc
ptr->info=x;
ptr->next=NULL; //set next node pointer to NULL to signify the end
if(head==NULL)
{
head=ptr;
}
else
{
node* tmp = head;
while(tmp->next) tmp = tmp->next; //get last node
tmp->next=ptr; //attach new node to last node
}
}
also your else branch was incorrect, creating another link loop.
You need to pass the last element of the list:
void insertatend(node *last, int x)
Or put a a tail node as global:
node *head = NULL;
node *tail = NULL;
void insertatend(int x)
{
node *ptr;
ptr = malloc(sizeof(node)); /* Don't cast malloc */
ptr->info = x;
ptr->next = NULL;
if (head == NULL) {
head = ptr;
} else {
tail->next = ptr;
}
tail = ptr;
}
You could also redefine your node struct to include next, prev, head, and tail pointers and manipulate them appropriately.
In your case, you should only need to set the head pointer on the tail node and the tail pointer on the head node. Set next and prev on all nodes. head pointer on head node should point to itself; tail pointer on tail node should point to itself. Head->prev = NULL; Tail->next = NULL;
Then just pass the head pointer always to your insertatend func.