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! */
}
}
Related
I wrote code to remove the node at the tail of a linked list. The code works properly in different testcases, but I think I made my code a bit cumbersome. However, I don't see what I can do differently?
node_t *remove_t (node_t *l){
if (l==NULL){
return l;
}
else {
node_t *curr=l;
node_t *ret=l;
if (curr->next==NULL){
l=NULL;
return l;
}
else {
while (curr->next->next!=NULL){
curr=curr->next;
}
curr->next=NULL;
free(curr->next);
return ret;
}
}
}
It is much, much easier if you keep a pointer-to-pointer to node, then iterate to the end of list and simply free the last pointer and set it NULL, e.g.
/** delete last node */
void del_last_node (node_t **l)
{
node_t **ppn = l; /* pointer to pointer */
node_t *pn = *l; /* pointer to node */
for (; pn->next; ppn = &pn->next, pn = pn->next) { } /* iterate to last */
free (*ppn); /* free node */
*ppn = NULL; /* set pointer NULL */
}
I'm not sure that you can change the logic much - as your approach of 3 different cases (empty list, list with 1 item, and list with >1 items) is reasonable. You can format the code for easier reading: Something like:
node_t *remove_t (node_t *l){
// case 1: Empty list
if (l==NULL){
return l;
} ;
// case 2: List with one item. Return empty list.
node_t *curr=l;
if (curr->next==NULL){
// Remember to free this element.
free(curr) ;
l=NULL;
return l;
} ;
// case 3: list > one item
// Move curr to last item
while (curr->next->next!=NULL){
curr=curr->next;
}
// Note order of free/null setting.
free(curr->next);
curr->next=NULL;
return l;
}
You didn't seem to free the tail node.
curr->next=NULL;
free(curr->next);
You won't be able to free curr->next if you already make it NULL.
My implementation:
void remove_tail(node_t *l) {
if (l == NULL) return;
if (l->next == NULL) {
free(l);
l = NULL;
return;
}
node_t *prev = l;
node_t *curr = l->next;
while (curr->next != NULL) {
prev = curr;
curr = curr->next;
}
prev->next = NULL;
free(curr);
}
I am receiving an error on Xcode when for my delete function for a single linked list in c and at this point im not sure why. The error im receiving is
"malloc: * error for object 0x7ffeefbff5d8: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug"
int delete (node ** list, int delete)
{
node * current= *list;//declares current
//stop at node that is one before i will need to delete (in this case iam deleting the 2node)
if (*list != NULL)
{
node * temp= *list;
temp = temp->next;
free(list);
*list=temp;
}
while (current->next->data != delete)
{
current=current->next;
}
node * temp;//Declares temp
temp=current->next->next;
free(current->next);//one after current free'd
current->next=temp;
return 0;
}
There are number of things which is not clear or unnecessary
Why you want to free the free(list); list is double pointer, if you free this headpointer of linked list will loose. after delete operation How will print/access the list again if needed ?
list is the headpointer which is holding the link and you didn't allocated any memory for list in main() or calling function so you can't free it. thats why error is
pointer being freed was not allocated
If you want to free only then first you should do free(*list) and then free(list)
From your code segment
free(list); /* list is freed here */
*list=temp; /* How will you access again *list */
As per my thinking your if block should be
if (*list != NULL) {
node * temp= *list;
temp = temp->next; /* temp holds 2nd node address & you need that only */
}
First of all Your question was very unclear, for the next time please post all of the necessary code and explain the purpose of the function in a few line.
I guess what you are trying to do is to remove a specific item from a linked list according to the value of the parameter data.
From the site learn-c:
"
Removing a specific item
To remove a specific item from the list, either by its index from the beginning of the list or by its value, we will need to go over all the items, continuously looking ahead to find out if we've reached the node before the item we wish to remove. This is because we need to change the location to where the previous node points to as well.
Here is the algorithm:
Iterate to the node before the node we wish to delete
Save the node we wish to delete in a temporary pointer
Set the previous node's next pointer to point to the node after the node we wish to delete
Delete the node using the temporary pointer
There are a few edge cases we need to take care of, so make sure you understand the code. "
Then they posted the code, I think you should go there and read the entire post.
Good luck
Your code have a faulty logic plus obvious errors.
Once list is freed you have no right to access it again.
free(list);
*list=temp;
Managing the linked list is not difficult but it requires attention to details.
When you delete the node in the list you have a responsibility to connect the nodes.
If you delete the head you have a responsibility to move the head.
If the head is the node you are looking for and this is the only node in the list than after removal that node has to be marked as NULL.
The test program below uses struct node *find(struct node *start, int data) function to find a node which matches your criteria and uses delete to delete it. All edge cases have been taken care of.
#include <stdio.h>
#include <stdlib.h>
// Basic simple single list implementation to illustrate
// a proper deletion of the node which has a specfic data value.
// Node in List
typedef struct node {
int data;
struct node* next; // pointer to next node
}node;
// List structure
typedef struct list {
node* head; // The entry point into a linked list. If the list is empty then the head is a null reference.
} list;
// Create list
list* list_create()
{
list* new_list = malloc(sizeof(list));
if(new_list == NULL)
return NULL; // protection
new_list->head = NULL; // If the list is empty then the head is a null reference. no elements in the list
return new_list; // return created new list
}
// returns newly created node
node* node_new(int data)
{
node* new_node = malloc(sizeof(node)); // allocate memory for the node
if (new_node == NULL)
return NULL; // protection
new_node->data = data; // remember the data
new_node->next = NULL; // no next node
return new_node; // return new created node
}
// The method creates a node and prepends it at the beginning of the list.
//
// Frequently used names for this method:
//
// insert at head
// add first
// prepend
//
// returns new head or NULL on failer
node* prepend_node(list* in_list, node* new_node)
{
// Add item to the front of the in_list, return pointer to the prepended node (head)
if(in_list == NULL)
return NULL;
if(new_node == NULL) // problem, not enough memory
return NULL; // in_list->head has not changed
/*
new_node
|*| --> NULL
next
*/
if(in_list->head == NULL) // if list is empty
{
in_list->head = new_node; // the new_node becomes a head
}
else // list already have a head node
{
/*
|2|-->|1|-->NULL
^
|
*
head (2) (list pointer)
*/
new_node->next = in_list->head; // now, the new node next pointer points to the node pointed by the list head, see below:
/*
new_node
|3|--> |2|-->|1|-->NULL
^
|
*
head (list pointer)
*/
in_list->head = new_node; // the list head has to move to new_node ( a new prepanded node)
/*
new_node
|3|--> |2|-->|1|-->NULL
^
|
*
head (3) (list pointer)
*/
}
return in_list->head; // we are returning pinter to new_node
}
// Print out list
void print_list(list* in_list)
{
node* node;
if (in_list == NULL)
{
return;
}
if (in_list->head == NULL)
{
printf("List is empty!\n");
return;
}
printf("List: ");
node = in_list->head;
while(node != NULL)
{
printf(" %d", node->data);
node = node->next;
}
printf("\n");
}
struct node *find(struct node *start, int data) // find p to be removed
{
node* node;
if (start == NULL)
return NULL;
node = start;
while(node != NULL)
{
if (node->data == data)
return node;
node = node->next;
}
return NULL;
}
int delete(struct node **start, int data)
{
struct node *p, *prev, *next, *to_free;
if (start == NULL) // protection
return 0;
p = find(*start, data); // find p to be removed
if (p == NULL)
return 0;
if (*start == NULL)
return 0; // protection
if(*start == p) // head == p
{
if((*start)->next !=NULL)
{
*start = (*start)->next; // remember next
free(p);
printf("Head removed\n");
return 1;
}
else // the only node
{
free(p);
printf("Last node removed\n");
*start = NULL;
return 1;
}
}
// p != start:
next = *start;
while (next != NULL)
{
prev = next;
to_free = next->next; // candidate to be freed
if( to_free == p )
{
prev->next = to_free->next; // connect nodes before deletion
free(to_free); // now free the remembered `next`
to_free = NULL; // so it does not point to the released memory
return 1;
}
next = next->next; // this node was not a match
} //while
return 0;
}
int main() {
list* new_list = list_create();
node *n1 = node_new(1);
node *n2 = node_new(2);
node *n3 = node_new(3);
// list is empty
print_list(new_list);
prepend_node(new_list, n1);
prepend_node(new_list, n2);
prepend_node(new_list, n3);
// list has 3 elements
print_list(new_list);
delete(&new_list->head, 3);
print_list(new_list);
delete(&new_list->head, 1);
print_list(new_list);
delete(&new_list->head, 2);
// list has 2 elements
print_list(new_list);
printf("head: %p\n",new_list->head);
print_list(new_list);
free (new_list); // after deleting all elements, delete the list itself
return 0;
}
Output:
List is empty!
List: 3 2 1
Head removed
List: 2 1
List: 2
Last node removed
List is empty!
head: (nil)
List is empty!
Im new to c programming. I wanted to create a linked list from a given file and then randomly get a node from linked list then delete that node.
So the code works great but for the position 0 in linked list does not work.
Please help me
here's the code:
typedef struct node{
int *name;
struct node *next;
}node;
delete node:
void deleteNode(node **head_ref, int position){
if(*head_ref == NULL){
return;
}
node * temp = *head_ref;
if(position == 0)
{
*head_ref = (*head_ref)->next;
return;
}
int h;
for(h=0 ; temp!=NULL && h<position-1 ; h++){
temp = temp->next;
}
if(temp == NULL || temp->next == NULL)
return;
node * next = temp->next->next;
free(temp->next);
temp->next = next;}
getting random node:
void RandomFromList(node *head){
// IF list is empty
if (head == NULL){
return -1;
}
word = head->name;
// Iterate from the (k+1)th element to nth element
node *current = head;
int n;
for (n=2; current!=NULL; n++)
{
// change result with probability 1/n
if (rand() % n == 0)
word = current->name;
// Move to next node
current = current->next;
}
sprintf(words , "%s" , word);
deleteNode(&head , search(head , word));
printf("Randomly selected key is %s\n", words);}
and the file Reader:
node* fileReader(FILE *file){
node *t = malloc(sizeof(node));
char TopicName[20];
int fileRead = fscanf(file,"%s",TopicName);
if(fileRead != EOF){
t->name = strdup(TopicName);
tedad++;
t->next = fileReader(file);
}
if(fileRead == EOF) {
return NULL;
}
return t;}
EDIT:
When the code run's and when the position randomly got 0 the 0 position of linked list doesn't delete and continues with that node in linked list.
EDIT2:I changed my delete node and it works well without any problem, thank you guys!
node* deleteNode(node* head, unsigned i){
node* next;
if(head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next)
: (head->next = delete_at_index(next, i - 1), head);
}
The major logical problem I see with your delete function is that it is void, i.e. it returns nothing. This is fine if the node being deleted is in the middle (or end) of the list, because the head does not change. But for the case of deleting the head, the caller might expect that his reference would then point to the next node (or null, if a list of one element) after making the call. Consider this code:
node* deleteNode (node *head_ref, int position)
{
// passing in a NULL list returns NULL
if (head_ref == NULL) {
{
return NULL;
}
// deleting the first element returns the second element as the new head
node* temp = head_ref;
if (position == 0)
{
node* ret = temp->next;
free(head_ref);
return ret;
}
// otherwise walk down the list to one before the deletion position
for (int h=0; temp != NULL && h < position-1; h++) {
temp = temp->next;
}
// if found, delete the node at the desired position
if (temp != NULL && temp->next == NULL) {
node* next = temp->next->next;
free(temp->next);
temp->next = next;
}
// for cases other than deleting the head, just return the current
// (unmodified) head
return head_ref;
}
This isn't related to your problem, but don't forget to free the memory:
node * temp = *head_ref;
if(position == 0)
{
*head_ref = temp->next;
free(temp); // <--------
return;
}
Also, you already have a pointer (temp) to *head_ref, it looks cleaner to me to just use that pointer instead of dereferencing head_ref again.
void deleteNode(node **head_ref, int pos){
node *del;
for ( ; *head_ref; head_ref = &(*head_ref)->next) {
if (pos-- <= 0) break;
}
if (!*head_ref) return; // Reached end of list: nothing found
del = *head_ref;
*head_ref = del->next;
free(del);
return;
}
If you want to keep deleteNode void, then the problem is with your RandomFromList function. You are just changing the * head that exists in the function body not the pointer you passed to the function, so it's still pointing to the previous node.
It's because that pointers are passed by value (copied) like other things in C.
Try making RandomFromList return the head pointer.
P.s. I think you also have some memory leaks in the delete function.
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;
}
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
}
}