I have a linked list, I guess a tree looks like this:
-> grandma
-> dad
-> me
-> sister
-> niece
-> brother
-> uncle
-> cousin
and I have a struct as following
struct Node{
Node *parent;
Node *next;
Node *child;
}
How would I free that linked list?
My idea is to do a depth first search and deallocate each node?
Recursive depth-search (DFS): You're right, it's a good way to dealocate binary-tree memory:
remove(node):
if node is null: return
//else
remove(left node)
remove(right node)
free(node)
Iterative solution:
https://codegolf.stackexchange.com/questions/478/free-a-binary-tree
Since you don't want to use any recursive solution, there you can find well-described iterative one.
You can optimize allocation/deallocation of the tree.
Imagine, you want to create tree with 20 or 30 persons. You can allocate an array of 30 Node structs:
size_t currentArraySize = 30;
Node* nodes = (Node*)malloc(currentArraySize * sizeof(Node));
size_t nextFreeIndex = 0;
To add new element you can write simple function:
Node* allocateNode()
{
// Oops! There's not more memory in the buffer.
// Lets increase its size.
if (nextFreeIndex >= currentArraySize) {
currentArraySize *= 2;
Node* newNodes = (Node*)realloc(nodes, currentArraySize * sizeof(Node));
// Should correct pointers (thanks to user3386109)
if (newNodes != nodes) {
for (size_t i = 0; i < nextFreeIndex; i++) {
if (newNodes[i]->parent != NULL)
newNodes[i]->parent -= nodes += newNodes;
if (newNodes[i]->next != NULL)
newNodes[i]->next -= nodes += newNodes;
if (newNodes[i]->child != NULL)
newNodes[i]->child -= nodes += newNodes;
}
}
}
return nodes[nextFreeIndex++];
}
To deallocate all nodes you can just free the single pointer nodes.
Now the code looks a little scary as wrote user3386109, so we may simplify it a little:
Node* allocateNode()
{
// Oops! There's not more memory in the buffer.
// Lets increase its size.
if (nextFreeIndex >= currentArraySize) {
currentArraySize *= 2;
Node* newNodes = (Node*)realloc(nodes, currentArraySize * sizeof(Node));
// Should correct pointers (thanks to user3386109)
if (newNodes != nodes)
correctPointers(newNodes, nodes);
}
return nodes[nextFreeIndex++];
}
#define correctPointer(pointer, oldOffset, newOffset) if (pointer != NULL) { \\
pointer -= oldOffset; \\
pointer += newOffset; \\
}
void correctPointers(Node* newNodes, Node* nodes)
{
for (size_t i = 0; i < nextFreeIndex; i++) {
correntPointer(newNodes[i]->parent, nodes, newNodes);
correntPointer(newNodes[i]->child, nodes, newNodes);
correntPointer(newNodes[i]->next, nodes, newNodes);
}
}
Iterative version, inspired by Day–Stout–Warren algorithm:
void removetree(Node *node)
{
while(node != NULL)
{
Node *temp = node;
if(node->child != NULL)
{
node = node->child;
temp->child = node->next;
node->next = temp;
}
else
{
node = node->next;
remove(temp);
}
}
}
This algorithm somewhat like tries to convert the tree into a list single-linked with next pointers, which is very simple to destroy just by iterative unlinking and destroying the first item. However it never completes the conversion, because it unlinks and removes the head node as soon as it can, despite the rest of tree not being converted yet. So to say, it interleaves a relink step with unlink-and-destroy step.
We test with the if instruction whether the first (head) node has any children. If so, we make its child a new head and the current node becomes the new head's next node. This way we have one more next link in the first-level list. What was 'next' to the now-head node becomes a child to a previous-head node, which is now the head's first next.
On the other hand if the head node has no children, it may be removed and its next becomes a new head.
These two steps are iterated by the while loop until all children are converted into siblings and removed afterwards.
You may use recursive solution
free(root)
{
if (root->next == null)
{
free(node)
}
free(root->left)
free(right->)
}
Related
How would you iterate this 2D linked list?
typedef struct _NODE
{
char *pszName;
unsigned long ulIntVal;
char *pszString;
struct _NODE *pNext;
struct _NODE *pDown;
} NODE;
I could do something like this..
NODE *pHEad;
while (pHead != NULL) {
printf("%s", pHead->pDown->pszName);
pHead = pHead->pNext;
}
.. but it would only give me the one node under every next node. What if it is another node under that one again? And under that one again? Or if there is a pNext attached to the pDown?
In the simplest case, you could use something like the following recursive function:
void processNode(NODE *current) {
if (current != NULL) {
printf("%s", current->pszName);
processNode(current->pNext);
processNode(current->pDown);
}
}
int main(void) {
NODE *pHead;
/* ... Do something to fill your list ... */
processNode(pHead);
/* ... */
}
Also be aware that this can cause a deep nesting of the function calls depending on your processed list. So if you are on an embedded system with limited stack size or if you are processing huge lists, you might run out of stack. In that case, you should find another approach for the processing.
Note that this will first process the pNext-list and then start with processing the first node of the pDown-list of the last node. So assuming the following structure (to the right is pNext and downwards is pDown):
pHead -> p1 -------> p2
|- p1_1 |- p2_1 -> p2_1_1
\- p1_2 |- p2_2
\- p2_3 -> p2_3_1
it should print the nodes in the following order:
pHead, p1, p2, p2_1, p2_1_1, p2_2, p2_3, p2_3_1, p1_1, p1_2
Look at this answer. Don't be overwhelmed by the amount of the code. I have added enough comments to help you proceed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node{
char data[100]; // Assume that this linked list will contain only 100 chars of data
struct Node* next;
} NODE;
// Global Variables are bad, but oh well.
NODE* head = NULL;
// Function to create a node
NODE* createNode(char* str)
{
// First allocate memory for struct
NODE* newNode = malloc(sizeof(NODE));
if(newNode == NULL)
{
printf("Unable to create a new node.");
}
else
{
// Use strcpy or strncpy or memcpy instead of doing something like newNode -> data = str, which changes the pointer, but doesn't copy the contents
// That is do not do newNode -> data = "hello" or something
strncpy(newNode -> data, str, strlen(str));
newNode -> next = NULL;
}
return newNode;
}
void addNode(char* str)
{
// Returns a node which contains str, but points to NULL
NODE* newNode = createNode(str);
// If the linked list is empty, then we make this node itself as the first node(or head)
if(head == NULL)
{
head = newNode;
}
// Else if the linked list is not empty, then we add this node at the start of the linked list
else
{
newNode -> next = head;
head = newNode;
}
}
int main()
{
// Example Linked List Generated(say you already have it in some form)
addNode("This");
addNode("Is");
addNode("Linked List");
// Now let's print the linked list
// Temporary NODE pointer ptr is used in order to not mess with the original NODE pointer head.
NODE* ptr = head;
// Traverse through the linked list starting from head and at the same time printing the corresponding data, until ptr is null
// This ptr != NULL check is exactly what you are looking for. This is your way of stopping the traversal of Linked List once you
// are at the end of it. You don't have to know the number of nodes to stop the traversal this way.
while(ptr != NULL)
{
printf("%s ", ptr -> data);
ptr = ptr -> next;
}
}
However note that the output will be printed in reverse order, since in this implementation of linked list we are adding things towards the back. Just try running the program and start reading the program starting from main function. I have made the code into separate functions to make it easier for you to understand. Just run the code first to get a grasp of what's happening.
You can use iteration instead of recursion by adding a queue, too, if you want to avoid the possibility of a stack overflow—though this will use slightly more heap memory, and there is still a risk that you can run out of heap memory if you have a large list or if you're running on a memory-constrained system. The important part is the print_list function at the end; the other stuff is just a (mostly) self-managing queue implementation I've provided:
typedef struct node_queue NodeQueue;
struct node_queue {
NODE *n;
NodeQueue *next;
};
/*
* Add an item to the end of the queue.
*
* If the item could not be added, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int enqueue(NodeQueue **headp, NodeQueue **endp, NODE *n)
{
NodeQueue *old_end = *endp;
NodeQueue *new_end;
new_end = malloc(sizeof *new_end);
if (new_end == NULL) {
return 0;
}
new_end->n = n;
new_end->next = NULL;
if (old_end != NULL) {
old_end->next = new_end;
}
if (*headp == NULL) {
*headp = new_end;
}
*endp = new_end;
return 1;
}
/*
* Remove an item from the head of the queue,
* storing it in the object that "nret" points to.
*
* If no item is in the queue, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int dequeue(NodeQueue **headp, NodeQueue **endp, NODE **nret)
{
NodeQueue *old_head = *headp;
NodeQueue *new_head;
if (old_head == NULL) {
return 0;
}
if (nret != NULL) {
*nret = old_head->n;
}
new_head = old_head->next;
free(old_head);
if (new_head == NULL) {
*endp = NULL;
}
*headp = new_head;
return 1;
}
void print_list(NODE *start)
{
NodeQueue *head = NULL;
NodeQueue *end = NULL;
NODE *current;
current = start;
/* Iterate all `pNext` nodes, then pop each `pDown` node and repeat. */
for (;;) {
/* Add the "down" node to the node queue. */
if (current->pDown != NULL) {
if (!enqueue(&head, &end, current->pDown)) {
perror("warning: could not add node to queue");
}
}
printf("%s", current->pszNode);
/*
* Move to the "next" node.
* If there is no next node, get the first "down" node from the queue.
* If there is no "down" node, break the loop to end processing.
*/
current = current->pNext;
if (current == NULL) {
if (!dequeue(&head, &end, ¤t)) {
break;
}
}
}
}
This will iterate through all pNext items before moving to a pDown item. The following 2-D list will be printed as A B C D E F G H I J K L M N O P Q:
A
|
B--C
|
D--E-----------F
| |
G-----H I-----J
| | | |
K--L M--N O P
|
Q
You can reverse the priority of pDown/pNext in the print_list function by swapping pNext and pDown inside it, so pNext items are added to the queue and pDown items are iterated until exhausted, which will change the order in which the items are printed to A B D C E G K F I O H M Q L J P N unless you change the structure of the list.
You can see an example using both the code above and the first sample 2-D linked list above at https://repl.it/NjyV/1, though I changed the definition of NODE to make the code using its fields a bit simpler.
I'm trying to build a max heap in VC++ using Visual Studio 2008 v9.0.30729.1 SP.
In the tree, each node looks like:
typedef struct node{
struct data_t *data;
struct node_t *left;
struct node_t *right;
}node_t;
A single node creation logic goes like this:
node_t* createNode(int id, int pID, float probability)
{
node_t *temp = (node_t *)malloc(sizeof(node_t));
data_t *data = (data_t *)malloc(sizeof(data_t));
data->id = id;
data->pID = pID;
data->probability = probability;
temp->data = data;
temp->left = 0;
temp->right = 0;
return temp;
}
I have managed to create and insert elements in the tree (insertion logic working fine). I'm stuck with the logic of removing a node (a leaf, to be precise) from this tree.
I've tried four different approaches for the same:
node_t* deleteLeaf(node_t* heap)
{
node_t* leaf;
if((heap->left==0) && (heap->right==0))
{
//heap = 0; //APROACH 1
//heap->data = 0; //APROACH 2
return heap;
}
else if((heap->left!=0) && (heap->right==0))
{
leaf = deleteLeaf(heap->left);
}
else
{
leaf = deleteLeaf(heap->right);
}
//leaf = 0; //APROACH 3
//free(leaf); //APROACH 4
return leaf;
}
(Uncomment APPROACH 1/2/3/4 for the desired effect).
None of this seems to work. I need to assign a zero/null value to the left/right pointer of the previous node.
How to make this work? Please help.
To delete a node in a tree you need to
free the memory and do the cleanup for the node
fix the pointer you used to reach the node, making it NULL
the part 2 can be solved in two ways:
A) the parent does the fixing
B) the deletion routine receives the address of the address of the node (extra level of indirection).
For solution A the code is simply
void deleteNodeA(Node *p) {
if (p) {
// Here we don't really need part 2 because
// we're going to destroy the whole node containing
// the pointers anyway.
deleteNodeA(p->left); // add p->left = NULL if you like
deleteNodeA(p->right); // add p->right = NULL if you like
free(p->data);
free(p);
}
}
but the caller needs to fix the pointer used to reach the node. For example like
Node *p = root, *parent = NULL;
while (p && (p->left || p->right)) {
// Not a leaf... go left if possible o right otherwise
parent = p;
p = p->left ? p->left : p->right;
}
// 2: Fix the pointer in parent
if (parent) {
if (p == parent->left) {
parent->left = NULL;
} else {
parent->right = NULL;
}
} else {
// No parent... this was the root of the tree
root = NULL;
}
deleteNodeA(p);
The solution B looks like:
void deleteNodeB(Node **p) { // Note the double pointer
if (*p) {
deleteNode(&((*p)->left)); // Note the &
deleteNode(&((*p)->right)); // Note the &
free((*p)->data);
free(*p);
*p = NULL; // (2): fixing the pointer
}
}
and for example code deleting a leaf of the tree is
Node **p = &root;
while ((*p) && ((*p)->left || (*p)->right)) {
// Not a leaf... go left if possible o right otherwise
p = ((*p)->left) ? &((*p)->left) : &((*p)->right));
}
deleteNodeB(p);
Instead of writing 4 random lines of code and calling them "approaches", try actually specifying a function that does something meaningful. A function that takes a heap as an argument should be called DeleteHeap, not DeleteLeaf. Since it deletes a heap, there's nothing for it to return. So, how do you delete a heap? Well, if the heap is a leaf (it has no left or right subtree), delete that, else delete the subtrees by calling DeleteHeap recursively. Code that and you're done.
Edit:
You left a comment:
deleteLeaf is supposed to delete the last element of the tree at the
last level. The value returned should be the data contained in the
deleted leaf.
Well, that's news. We aren't mind-readers. Your question didn't say this, and the function name and signature are wrong for this, too.
Let's start with the name -- DeleteRightmostLeaf. And the return type ... data_t*. Even the argument type is wrong ... it should be heap_t**, because we have to store a NULL into the pointer.
So, DeleteRightmostLeaf takes a pointer to a pointer to a heap. If that heap is a leaf node, store NULL in the pointer to it, extract its data pointer, free the node (in that order ... otherwise you're accessing deleted memory, which isn't allowed), and return the data pointer.
If the heap isn't a leaf node, then call DeleteRightmostLeaf recursively on the pointer to its rightmost subtree -- the right subtree if that's not NULL, else the left subtree. Voila, you're done.
Note that, in both cases, it's very easy to come up with the answer if one just thinks clearly about what they need to do.
As a bonus, here's an iterative solution. I haven't tested or even compiled this.
data_t* DeleteRightmostLeaf(node_t** pheap)
{
node_t* pnode = *pheap;
if (!pnode)
return NULL; // empty heap
while (pnode->left || pnode->right)
{
pheap = pnode->right ? &pnode->right : &pnode->left;
pnode = *pheap;
}
*pheap = NULL;
data_t* pdata = pnode->data;
free(pnode);
return pdata;
}
Try this modification of your method:
node_t* deleteLeaf(node_t* heap)
{
if (!heap)
return 0;
if (heap->left!=0)
deleteLeaf(heap->left);
if (heap->right!=0)
deleteLeaf(heap->right);
if (heap->data)
free(heap->data); // free data
free(heap); // free leaf
heap = 0;
return heap;
}
One question: which value should be returned by this function? (now it always returns 0).
It is hard to understand what you are trying to do (we haven't description of the function, examples of expected results and so on). So, I suspect, that code above is not solution. But it might be first step in understanding of the problem.
I have been trying hard to resolve this however yet not succeed I have data structs as follow (which actually is very complex I just simplifies for discussion) :
typedef struct node{
struct node* next;
void* arg;
}node_t;
typedef struct queue{
node_t* head;
node_t* tail;
}queue_t;
addQ(queue_t*ptr , int data)
{
queue_t* q = ptr;
node_t * n = malloc(sizeof(*n));
n->arg = data;
n->next = NULL;
if(NULL == q->head){
q->head = q->tail = n;
return ;
}
q->tail->next = n;
q->tail = q->tail->next;
}
Now I want to delete node of same value ( I have tried couple ways however yet not succeed ) , Just consider this sequence for reference:
addQ(q, 12);
addQ(q, 12);
addQ(q, 4);
addQ(q, 12);
addQ(q, 12);
addQ(q, 14);
addQ(q, 12);
addQ(q, 12);
I want to Delete all the nodes with value 12.
This solution got a bit hairy with the double pointers, but I still like it, as it doesn't have to special case what node (first vs the rest) is being checked. I tried to put enough comments in to describe what's going on, but it's still hard for even me to follow at first glance.
PSEUDOCODE..
Queue * q;
VALUE = 12;
// double pointer so we can treat the queue head and subsequent nodes the same.
// because they are both pointers to Node.
// Otherwise you'd have to have code that says if the one you're removing is the
// first element of the queue, adjust q->head, otherwise adjust node->next.
// This lets you not special case the deletion.
Node ** node_ptr = &(q->head)
while (*node_ptr != null) {
if ((**node_ptr).arg == VALUE) {
// store off the matching node to be freed because otherwise we'd orphan
// it when we move the thing pointing to it and we'd never be able to free it
Node * matched_node = *node_ptr;
// when we find a match, don't move where node_ptr points, just change the value it
// points to to skip the matched node and point to the one after it (or null)
*node_ptr = matched_node->next;
free(matched_node);
} else {
// otherwise, nothing was deleted, so skip over that node to the next one.
// remember, **node_ptr is a double dereference, so we're at the node
// now, so then we grab the address of the non-matching node's next value so it can be
// potentially changed in the next iteration
node_ptr = &((**node_ptr).next);
}
}
Assuming that you already have a function that obtains and removes the next item in the queue, let's call it getQ(q), then you could achieve your goal without even having to know the internals of the queue, by just using the operations you already have, e.g. something like (this won't work because arg is a void, but the logic should be clear):
node_t *n;
queue_t *q2 = initialiseQ();
while (n = getQ(q)) {
if (n->arg != 12) {
addQ(q2,n);
}
}
free(q);
q = q2;
Here's an inline solution that doesn't use double pointers. It has to treat the first element and subsequent elements differently since the pointer to adjust changes from the queue structure to the node structure.
Also, for subsequent nodes, you have to track the trailing node, since that's where you have to make the adjustment as you delete the matching node.
Queue * q;
VALUE = 12;
// handle the case where the first node matches.
// you have to adjust the q's head pointer
// delete from the head and set a new head node until a non-matching head is found
while (q->head != NULL && q->head->arg == VALUE) {
Node * matching_node = q->head;
q->head = q->head->next;
free(matching_node);
}
// if there is more than one node left, need to check the subsequent nodes
if (q->head != NULL && q->head->next != NULL) {
Node * node_ptr = q->head->next;
Node * prev_node_ptr = q->head;
while (node_ptr != NULL) {
if (node_ptr->arg == VALUE) {
Node * matched_node = node_ptr; // don't orphan it before it's freed
// You don't move the prev_node pointer since that doesn't change when a match
// is found. Only the node_ptr, which skips to the next one.
node_ptr = node_ptr->next;
free(matched_node);
} else {
prev_node_ptr = node_ptr;
node_ptr = node_ptr->next;
}
}
}
I'm writing a hashtable as an array of linked lists.Currently I'm trying to have a simple hash table where the key is the index of the array and value is a singly linked list for implementing chaining.
This is my code to delete a node:
Basic Struct:
struct Node
{
int value;
int page;
struct Node *next;
};
int searchAndDelete(int frame,int page,int delete)
{
struct Node** iter;
iter=&hashtable[(page-1)%7];
struct Node** prev=iter;
for(;*iter;iter=&(*iter)->next)
{
if(page==((*iter)->page))
{
if(frame==((*iter)->value))
{
if(delete)
{
(*prev)->next=(*iter)->next;
free(*iter);
}
return 1;
}
}
prev=iter;
}
return 0;
}
For insertion please take a look here, AddNode
When I'm deleting a node, the value for that changes to 0. When I search for the node it gives back that node is not preset aka 0 as output from the function.
Are there any mistakes in my code which I haven't thought about?Am I leaving any memory leaks or any other problems?
Edit
Added this piece of code to the delete function:
int searchAndDelete(int frame,int page,int delete)
{
struct Node** iter;
iter=&hashtable[(page-1)%7];
struct Node** prev=iter;
struct Node** curr=iter;
for(;*curr;curr=&(*curr)->next)
{
if(page==((*curr)->page))
{
if(frame==((*curr)->value))
{
if(delete)
{
if(curr==iter)
{
iter=(*curr)->next;
free(*curr);
}
else
{
(*prev)->next=(*curr)->next;
free(*curr);
}
}
return 1;
}
}
prev=curr;
}
return 0;
}
Problem I'm seeing is that when I delete the first time, the element is not freed, it's value is set to 0, but it still says in the linked list. In the second deletion the value of the last elements goes to some garbage and hence that element will never be deleted in my comparison checks. Can someone shed light on what I might be doing here?
If the hash table you're using is seven elements wide (i.e. 0..6 for indexes), and from your AddNode code, it appears it is, then the arithmetic you're using is suspect for the initial iterator find.
iter=&hashtable[page-1%7];
should likely be:
struct Node** iter = hashtable + (page % 7);
This will give you the address of the element in your hash table at the page location modulus 7, i.e. [0..6].
Also, your delete from your hash table head node doesn't account for clearing the table element itself. You may need to (a) set it to null, or (b) chain in the next ptr. Do that as well. You have the ability to since the hash table and the initial node pointer are both available.
EDIT: OP asked for sample. This is just a quick jot of how this can be done. I'm sure there are plenty of better ways, maybe even ones that compile. This assumes both the page AND frame must match EXACTLY for a node to be considered delete'able.
void searchAndDelete(int frame, int page, int del)
{
struct Node** head = hashtable + (page % hashtable_size);
struct Node* curr = *head;
struct Node* prev = NULL;
while (curr)
{
// if they match, setup for delete.
if ((curr->page == page) && (curr->value == frame) && del)
{
// so long as the header pointer is the active node prev
// will be NULL. move head along if this is the case
if (prev == NULL)
*head = curr->next;
// otherwise, the previous pointer needs it next set to
// reference the next of our vicitm node (curr)
else
prev->next = curr->next;
// victim is safe to delete now.
free(curr);
// set to the new head node if we just deleted the
// old one, otherwise the one following prev.
curr = (prev == NULL) ? *head : prev->next;
}
else
{ // no match. remember prev from here on out.
prev = curr;
curr = curr->next;
}
}
}
Eh, close enough =P
I see couple of issues:
mod operator % needs parenthesis. So change iter=&hashtable[page-1%7]; to iter=&hashtable[(page-1)%7];
Handle the case when you will delete 1st element in linked list. In such cases prev will be same as iter so (*prev)->next=(*iter)->next; will not make any different. You need to update the array to store next element aka (*iter)->next.
This is something of a followup to a question I asked earlier. I'm still learning my way around pointers, and I'm finding it difficult to maintain a reference to the physical address of a struct while iterating through a data structure. For example, I have a simple, barebones linked list that I'd like to delete from via a searching pointer:
struct Node{
int value;
struct Node* next;
};
struct Node* createNode(int value){
struct Node* newNode = malloc(sizeof *newNode);
newNode->value = value;
newNode->next = NULL;
return newNode;
}
void nodeDelete(Node **killptr){
free(*killptr);
*killptr = NULL;
}
int main(){
struct Node* head = createNode(16);
head->next = createNode(25);
head->next->next = createNode(51);
head->next->next->next = createNode(5);
// Working code to delete a specific node with direct reference address
struct Node** killptr = &head->next;
nodeDelete(killptr);
return 0;
}
The above shows deleting by passing nodeDelete a pointer to the address of the head pointer. What I want to do is be able to move my pointer ->next until it finds something that satisfies a delete condition, and call nodeDelete on that. I've tried the following:
struct Node* searchAndDestroy = head;
while(searchAndDestroy->value != NULL){ // Search until the end of the structure
if (searchAndDestroy->value == 25){ // If the value == 25
nodeDelete(&searchAndDestroy); // Delete the node (FAILS: Nullifies the
// address of search variable, not the
break; // original node)
}else{
searchAndDestroy = searchAndDestroy->next;
}
}
I've also tried something along the lines of:
if (searchAndDestroy->value == 25){
struct Node** killptr = (Node**)searchAndDestroy);
nodeDelete(killptr); // Still fails
}
I need to be able to move my pointer to the ->next point, but also maintain a reference to the address of the node I want to delete (instead of a reference to the address of the search node itself).
EDIT: Some clarification: I realize that deleting from a linked list in this fashion is naive, leaks memory, and drops half the list improperly. The point is not to actually delete from a linked list. Ultimately the idea is to use it to delete the leaves of a binary search tree recursively. I just figured a linked list would be shorter to portray in the question as an example.
struct Node **searchAndDestroy;
for (searchAndDestroy = &head;*searchAndDestroy; searchAndDestroy = &(*searchAndDestroy)->next ){
if ((*searchAndDestroy)->value == 25){
nodeDelete(searchAndDestroy); // Function should be changed to assign the ->next pointer to the **pointer
break;
}
}
And change nodeDelete like this:
void nodeDelete(Node **killptr){
Node *sav;
if (!*killptr) return;
sav = (*killptr)->next;
free(*killptr);
*killptr = sav;
}
Unless I'm missing something, your nodeDelete function is working as designed, but you want to keep a way of accessing the next node in the chain. The easiest way of doing this is just to add a temporary variable:
struct Node *searchAndDestroy = head, *temp = NULL;
while(searchAndDestroy != NULL){ // Need to check if the node itself is null before
// dereferencing it to find 'value'
temp = searchAndDestroy->next;
if (searchAndDestroy->value == 25){
nodeDelete(&searchAndDestroy);
break;
}else{
searchAndDestroy = temp;
}
}
if you give the Address of the previous Node that is where the link to deleting node present then it is very simple
code snippet for that:-
void delete_direct (struct Node *prevNode)
{/*delete node but restrict this function to modify head .So except first node use this function*/
struct Node *temp;/*used for free the deleted memory*/
temp=prevNode->link;
prevNode->link=temp->link;
free(temp);
}
struct Node * find_prev(struct Node *trv_ptr,int ele)
{
/*if deleting element found at first node spl operation must be done*/
if(trv_ptr->data==ele)
return trv_ptr;
while((trv_ptr->link)&&(trv_ptr->link->data!=ele))
{
trv_ptr=trv_ptr->link;
}
if(trv_ptr->link==NULL)
{
return NULL;
}
else
return trv_ptr;
}
main()
{
/*finding Node by providing data*/
struct Node *d_link;
struct Node *temp;
d_link=find_prev(head,51);
if(d_link==NULL)
{//data ele not present in your list
printf("\nNOT FOUND\n");
}
else if(d_link==head)
{//found at first node so head is going to change
temp=head;
head=head->link;
free(temp)
}
else
{//other wise found in some where else so pass to function
delete_direct (d_link);
}
}