I'm simply trying to delete a node from the linked list and seem to be having trouble. I was wondering if someone could please have a look at what could be wrong? Thanks!
struct ets {
struct node *equip_head;
struct node *member_head;
struct node *loan_head;
const char *equip_fname;
const char *member_fname;
const char *loan_fname;
};
struct node {
void *data; /* Accepts all data, yay */
struct node *next;
};
BOOLEAN deleteMember(struct ets *ets, char MemberID[]) {
struct node *current = ets->member_head;
struct node *tmpNode = current;
struct member_data *member_data = NULL;
while (current != NULL) {
member_data = current->data;
if (strcmp(member_data->MemberID, MemberID) == 0) {
tmpNode = current;
current = current->next;
free(tmpNode->data);
free(tmpNode);
return TRUE;
}
current = current->next;
}
return FALSE;
}
You are not removing the node from list. You can do this to remove a node from a list:
BOOLEAN deleteMember(struct ets *ets, char MemberID[]) {
struct node *current = ets->member_head;
struct node *prev=NULL;
struct member_data *member_data = NULL;
while(current != NULL) {
member_data = current->data;
if(strcmp(member_data->MemberID, MemberID) == 0) {
if(prev==NULL) // removing 1st node
ets->member_head=current->next;
else
prev->next=current->next; // removing current node from list
free(current->data);
free(current);
return TRUE;
}
prev = current;
current = current->next;
}
return FALSE;
}
As you have a single linked list you delete algorythm is broken. Here is what your are currently doing :
locate member to delete. Fine. You have node-1 -> node -> node+1
you delete the member. Why not. But you list would become node-1 -> unallocated node and no way to find next nodes
You should instead test if next node has the correct id to have something like : prev_node(current) -> node_to_delete -> next_node`
Then you can do :
tmpNode = current->next;
current->next = tmpNode->next; /* ok for the chaining */
free(tmpNode->data); /* deletion will be ok */
free(tmpNode);
With of course a special management for first and last nodes ...
Edit : Ali already gave the answer. I leave this one as a comment on why OP's algo was broken
Related
I'm writing a program to create a linked list(a node), then reverse it. The linked list contains data and the address of the next.
typedef struct node{
int data;
struct node *next;
}node;
Firstly, I create the linked list.
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
After that, i create a function to print these data. (i called it PrintNode)
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
Finally, a function created to reverse the linked list.
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
It's my full program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
struct node *Insert_value(int dataInput,node* head);
struct node * Reversing(node **head);
void PrintNode(node *head);
main()
{
node *head = NULL;
int i=0,dataInput;
while(i!=5)
{
printf("input your elements: ");
scanf("%d",&dataInput);
head = Insert_value(dataInput,head);
i++;
}
PrintNode(head);
head = Reversing(&head);
PrintNode(head);
}
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
void PrintNode(node* head)
{
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
After debugging lots of times, I know that these functions are fine. However, after the reverse function, the address of the next node of the head variable is NULL. Can you explain and give me some pieces of advice?
The one line change that will solve your problem will be (you visualized it a bit wrong).
current->next =previous;
in place of
previous->next = current;
Your code will blowup for single element linked list. Add a proper check for that in the function Reversing(). In case there is single element first->next will be NULL. But you wrote first->next->next which will be undefined behavior in case first->next is NULL.
In earlier case you were just creating a linked list in Reversing() with the links unchanged but head was pointing to the last node. So the next of it was NULL.
Modify Reversing such that new nodes are appended at the end. When going through the list, you need to save the next node ahead of time (node *next = current->next)
struct node* Reversing(node **head)
{
node *current = *head;
node *reverse = NULL;
while(current)
{
node *next = current->next;
if(!reverse)
{
reverse = current;
reverse->next = NULL;
}
else
{
current->next = reverse;
}
reverse = current;
current = next;
}
return reverse;
}
I need to implement a function that reverses a linked list but i don't know how to return a newly formed linked list as a result.
typedef struct node_t* Node;
struct node_t {
int n;
Node next;
};
// create a new node with value n
Node nodeCreate(int n)
{
Node node = malloc(sizeof(*node));
if (node == NULL) return NULL;
node->n = n;
node->next = NULL;
return node;
}
// reversing the linked list
Node reverseList(Node list)
{
if (list == NULL) return NULL;
Node current, prev, next;
current = rev_head;
prev = NULL;
while( current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
list = prev;
return list;
}
This is the code I have written so far.
How do I insert this reverse linked list into a different new linked list within the function reverseList it self?
You are juggling around your nodes on the original list, and modifying then in place - which means you have only one list, and modify its nodes.
If that is what you want, your code might work (as soon as you fix things like the rev_head variable that appears from nowhere) - and the new head of the list, which is on your prev variable: which means your code should just work.
(It is important that the typedef don't hide the pointer though, I'd suggest changing that.)
What you seem not to have understood quite well is that for this kind o structure, any node works as the head of a list - there is no "list" type, just "node" types - and if you happen to pick any node in the middle of a list, that will just represent a partial list, starting from that node as well. So when you change your previous "last" node to point to its previous "antecessor" as its "next", that is it: that node is now the head.
(The exception to this "node == list" equality is while the reversing algorithm is running - at that point you have nodes that point in one direction and nodes that point in another, and the extra "next" and "prev" variables provide the needed information to fix things. If this was production code, this part of the code would have to be protected in a thread-lock)
Otherwise, if you want to produce a reversed copy of the list, you will have to copy the old nodes along the way, and just fix where they are pointing.
#include <stdlib.h>
#include <string.h>
typedef struct node_t Node;
struct node_t {
int n;
Node next;
};
// create a new node with value n
Node *nodeCreate(int n) {
Node *node = malloc(sizeof(*node));
if (node == NULL) return NULL;
node->n = n;
node->next = NULL;
return node;
}
void nodeCopy(Node *node_dst, Node *node_src) {
if (node_src == NULL || node_dst == NULL || abs(node_dst - node_src) < sizeof(Node)) {
return
}
memcpy(node_dst, node_src, sizeof(Node));
}
// reversing the linked list
Node *reverseList(Node *list) {
Node *new_list, *prev;
if (list == NULL) return NULL;
new_list = nodeCreate(0);
nodeCopy(new_list, list);
new_list->next=NULL;
prev = new_list;
while(list->next != NULL) {
list = list->next;
new_list = nodeCreate(0);
nodeCopy(new_list, list);
new_list->next=prev;
prev = new_list;
}
return new_list;
}
You can simply create a new node for every node in the original list and set the link in opposite order. Code could be:
Node createReversedList(Node node) {
Node result = NULL;
while (node != NULL) {
Node n = nodeCreate(node->n);
n->next = result;
result = n;
node = node->next;
}
return result;
}
There is a simple way in which you can reverse linked list
You can simply create a new linked list and add each node at the start of linked list which will create same linked list in reverse order
Node* revList(Node *start){
Node *startRev=NULL,*temp,*newNode;
temp = start;
while (temp->next!=NULL){
newNode = (Node *) malloc (sizeof(Node));
//Code for copying data from temp to new node
if(startRev == NULL){
startRev = newNode;
}
else {
newNode->next = startRev;
startRev = newNode;
}
temp = temp->next;
}
return startRev;
}
I am trying to make a doubly linked list that loops around, so the last link is connected to the first one.
However, I cannot figure out what I am doing wrong with the backlink, as I can print my list forwards but not backwards.
Any tip/help would be much appreciated.
This is my structure definition:
struct NODE {
union {
int nodeCounter;
void *dataitem;
} item;
struct NODE *link;
struct NODE *backlink;
};
//function to create a list
struct NODE *InitList() {
struct NODE *temp = (struct NODE*)malloc(sizeof NODE);
temp->item.nodeCounter = 0;
temp->link = NULL;
temp->backlink = NULL;
return temp;
}
This is my insert function:
void Add2List(struct NODE *start, struct NODE *NewNode) {
struct NODE *current = start;
while (current->link != NULL && current->link != start) {
current = current->link;
}
current->link = NewNode;
NewNode->link = start;
NewNode->backlink = current;
start->backlink = NewNode;
start->item.nodeCounter++;
}
and this is my print backwards function:
void PrintBackwards(struct NODE *start) {
struct NODE * current = start;
while(current->backlink != start) {
DisplayNode((struct inventory*)current->item.dataitem);
current = current->backlink; //go one node back
}
}
The rest of your functions look reasonable but there are least two mistakes in your PrintBackwards function.
If you had intended to print it starting at the end, you should be starting at start->backlink, not at start.
You should not be checking for NULL in the while loop because your list is circular, so there should not be NULL.
The code below fixes those two mistakes, but I am not sure if there are others.
void PrintBackwards(struct NODE *start)
{
if(start == NULL || start->backlink == NULL)
return;
struct NODE * current = start->backlink;
while(current->backlink != start)
{
DisplayNode((struct inventory*)current->item.dataitem);
current = current->backlink; //go one node back
}
}
Maybe....
while(current->backlink != start)
{
DisplayNode((struct inventory*)current->item.dataitem); //dangerous
current = current->backlink; //go one node back
}
I am trying to make my linked list program into a doubly linked list, however, am encountering a problem when I am trying to print my list backwards.
At the moment when I try to print backwards, it just runs a never ending loop, and I can't quite figure out where the error is.
If anyone can point out what I'm doing wrong it'd be very helpful.
EDIT: I believe the problem is in the displaybackwards method, but I do not know how to change it, as removing it would cause the program to crash.
These are the parts of my current code that I think the problem may be in:
struct NODE
{
union
{
int nodeCounter;
void *dataitem;
}item;
struct NODE *link;
struct NODE *backlink;
};
struct NODE *InitList()
{
struct NODE *temp = (struct NODE*)malloc(sizeof NODE);
temp->item.nodeCounter = 0;
temp->link = NULL;
temp->backlink = NULL;
return temp;
}
void Add2List(struct NODE *start, struct NODE *NewNode)
{
struct NODE *current = start;
while (current->link != NULL)
{
current->backlink = current; //problem should be this line
current = current->link;
}
current->link = NewNode;
NewNode->link = NULL;
NewNode->backlink = current;
start->item.nodeCounter++;
}
void DisplayList(struct NODE *start)
{
struct NODE *current = start->link;
while (current != NULL)
{
DisplayNode((struct inventory *)current->item.dataitem);
current = current->link;
}
}
void DisplayBackwards(struct NODE *start)
{
struct NODE *current = start->link;
while(current != NULL && current->link != NULL) //goes until current == last node
{
current = current->link;
current->backlink = current;
}
//when current == last node
while(current != start)// && current->backlink != NULL)
{
DisplayNode((struct inventory*)current->item.dataitem);
current->link = current;
current = current->backlink;
}
}
void DisplayBackwards(struct NODE *start)
{
struct NODE *current = start; //current points to first node
if(current==NULL) //if empty list, return
return;
//now we are sure that atleast one node exists
while(current->link != NULL) //goes until current == last node
{
current = current->link; //keep on going forward till end of list
}
//start from last node and keep going back till you cross the first node
while(current != NULL)
{
DisplayNode((struct inventory*)current->item.dataitem);
current = current->backlink; //go one node back
}
}
I need to remove a node from a singly linked list. I know this is a simple thing to do, but my mind is blank and I've searched both Google and Stackoverflow, but I seriously haven't found anything that will help me.
basically the list of nodes is contained in a bucket; like this:
struct node{
unsigned char id[20];
struct node *next;
};
struct bucket{
unsigned char id;
struct node *nodes;
};
and I have a function
struct bucket *dht_bucketfind(unsigned char *id); // return bucket with id[20]
to find the correct bucket. So I know how to find the correct bucket, but I don't know how to remove a given node. I would like to remove the node by nodeid (I think, I haven't really written the code that will call the remove function yet ;) but I think I'll be able to modify the code if necessary). I think that's all that's needed to solve this. Thanks in advance.
If you know the item you want to remove, you must do two things:
Change all pointers that point to the target item to point to the target item's next member. This will be the preceding item's next pointer, or the head of the list bucket.nodes.
Free the node you just made unreachable.
The code for manipulating a linked list is really not that tricky, once you understand what you are doing.
Your nodes don't have any payload other than an id, so, depending on the data payload of a node, you might not actually need to iterate the list in the standard way. This is useful if deleters are going to know the address of only the node they want to delete.
If your payload is a pointer to other data:
struct _node {
void *data;
unsigned char id[20];
struct _node *next
}
Then you could "delete" a node by stealing the payload of the next node, and then delinking the next node:
int delete (struct _node *node)
{
struct _node *temp;
memcpy(node->id, node->next->id, 20);
free_function(node->data);
node->data = node->next->data;
temp = node->next;
node->next = node->next->next);
free(temp);
return 0;
}
/* define your two pointers, prev and cur */
prev=NULL;
cur=head;
/* traverse the list until you find your target */
while (cur != NULL && cur->id != search_id) {
prev=cur;
cur=cur->next;
}
/* if a result is found */
if (cur != NULL) {
/* check for the head of the list */
if (prev == NULL)
head=cur->next;
else
prev->next=cur->next;
/* release the old memory structure */
free(cur);
}
public void Remove(T data)
{
if (this.Head.Data.Equals(data))
{
this.Head = this.Head.Next;
this.Count = this.Count - 1;
}
else
{
LinkedListNode<T> node = this.Head;
bool found = false;
while (node.Next != null && !found)
{
if (node.Next.Data.Equals(data))
{
found = true;
node.Next = node.Next.Next;
this.Count = Count - 1;
}
else
{
node = node.Next;
}
}
}
}
Its been a long time ago since I worked with C, but this should be compile clean.
Basically, you need to keep track of the previous pointer while you iterate through the linked list. When you find the node to delete, just change the previous pointer to skip the delete node.
This function deletes all nodes with id (find). If you want to delete only the first occurrence, then put a return after the free statement.
void delete(struct bucket *thisBucket, unsigned char find[20]) {
struct node *prev = null;
struct node *curr = thisBucket->nodes;
while (curr != null) {
if (!strcmp(curr->id, find)) { // found the node?
if (prev == null) { // going to delete the first node (header)?
thisBucket->nodes = curr->next; // set the new header to the second node
} else {
prev->next = curr->next;
}
free(curr);
// if deleted the first node, then current is now the new header,
// else jump to the next
curr = prev == null? thisBucket->nodes : prev->next;
} else { // not found, keep going
prev = curr;
curr = curr->next;
}
}
}
The following does not contain any error checking and only removes the current node from the list ...
pPrev->next = pCurrent->next;
Your preferences may vary, but I tend to put my linked list node at the start of the structure (whenever practical).
struct node{
struct node *next;
unsigned char id[20];
};
struct bucket{
struct node *nodes;
unsigned char id;
};
I find this generally helps to simplify pointer arithmetic and allows simple typecasting when needed.
This removes a node given its address; you can modify it to remove a node given its id, but you haven't specified the form of an id -- is it a NUL-terminated string, or is it 20 bytes?
// remove node from bucket and return true
// or return false if node isn't in bucket
int dht_rmnode(struct bucket* bucket, struct node* node)
{
struct node** ppnode = &bucket->nodes;
for( ;; ){
struct node* pnode = *ppnode;
if( pnode == NULL ) return 0;
if( pnode == node ){
*ppnode = pnode->next;
return 1;
}
ppnode = &pnode->next;
}
}
Or, more compactly,
// remove node from bucket and return true
// or return false if node isn't in bucket
int dht_rmnode(struct bucket* bucket, struct node* node)
{
struct node** ppnode = &bucket->nodes;
struct node* pnode;
for( ; (pnode = *ppnode); ppnode = &pnode->next )
if( pnode == node ){
*ppnode = pnode->next;
return 1;
}
return 0;
}
typedef struct node
{
int id;
struct node* next;
}Node;
void delete_element(void)
{
int i;
Node* current=head;
Node* brev=NULL;
if(i==head->id){
head=current->next;
free(current);}
else{
while(NULL!=current->next)
{
if(i==current->next->id){
brev=current;
current=current->next;
break;}
else
current=current->next;
}
if(i==current->id)
{
if(NULL==head->next){
head=NULL;
free(current);}
else
brev->next=current->next;
free(current);
}
else
printf("this id does not exist\n");
}
}