3

I feel as if I am not actually deleting the node and freeing up memory. I think I am just moving pointers around so when I print the linked list the list doesn't print the element I deleted. So my question is am I actually deleting the node or am I just simply rearranging the pointers so it looks like I am deleting the nodes(Essentially just breaking the links but not deleting the node)? Thank you for any help.

void SLL::deleteNode(int target){
Node *current = new Node;
Node *previous = new Node;

for (current = front->next, previous = front; current != NULL; current = current->next, previous=previous->next){
    if (previous->data == target && previous == front){
        front = previous->next;
        delete[] previous;
        return;
    //This if statement deletes the element if its the front
    }

    else {

        if (previous->data == target && previous->next == NULL){
            previous = NULL;
            delete[] current;
            return;
        //This if statement deletes the node if it is the back
        }


        else if (current->data==target)
        {
            previous->next = current->next;
            delete[] current;
            return;
        //This if statement deletes a node if it is in the middle
        }
    }
    }

    delete[] current;
    delete[] previous;
}
WombatCombat
  • 51
  • 1
  • 2
  • 9
  • Why are you using the array delete (`delete []`) version when you declare `current` and `previous` as a single instance? – mathematician1975 Mar 01 '14 at 22:35
  • Starting your enumeration algorithm with `front->next` is concerning. *Please* tell us you're not using a pre-allocated "head" node that doesn't actually contain data. It isn't needed. And unless you allocated your node with `new Node[n]`, you're using the wrong `delete` operator. – WhozCraig Mar 01 '14 at 22:36
  • I dont know. I tried this it worked. Please answer the question. – WombatCombat Mar 01 '14 at 22:56
  • 1
    Don't know *what* ? Whether your front pointer is a sentinel node? Whether your nodes are allocated with vector-`new` ? You wrote the code, right? And btw,the two nodes you're allocating at the head of this function are immediately being leaked, so I can assure you in the end there is zero memory being recouped, whether you deleted a target node or not. – WhozCraig Mar 01 '14 at 23:09
  • You `delete[]` a null vector in your second block, but I don't think that control can ever enter that block, so I guess it's moot. – Beta Mar 01 '14 at 23:14
  • I used new to create new nodes then I used previous and current to allow me to do the delete in the middle. It properly traverses my linked list and then displays the data as if they were removed. I dont know anything about memory leaks really and thats why I asked the question I asked isnt it? So I could learn how to properly delete nodes not just break the links. – WombatCombat Mar 01 '14 at 23:22
  • It would help if you answered the two open questions in these comments: do you use a sentinel node, and is this a linked list of `Node`, or a linked list of `Node[]`? – Beta Mar 01 '14 at 23:49

1 Answers1

10
Node *current  = new Node;
Node *previous = new Node;

This code causes memory leaks - you are never deleting this memory. You can declare pointers without memory allocation:

Node *current  = nullptr;
Node *previous = nullptr;

delete will delete the memory of the pointer so you will actually delete Nodes. But using delete[] for the Node* is incorrect, it should be used only for arrays - the memory allocated with new[]. Improper use leads to undefined behaviour. So, to properly delete nodes delete them with operator delete.

Use memory leaks detection tools to know are there memory leaks in you program.

The code to delete a list element: say, we have pHead which points to the head of the list (but it would give you much more if you write such things yourself):

Node* pCur  = pHead;
Node* pPrev = pCur;

while (pCur && pCur->data != target) {
    pPrev = pCur;
    pCur  = pCur->next;
}

if (pCur==nullptr)  // not found
   return NOT_FOUND;

if (pCur == pHead) {   // first element matches
    pHead = pCur->next;
} else {
    pPrev->next = pCur->next;
}

// pCur now is excluded from the list

delete pCur;     // deallocate its memory

Alternative Using Pointer To Pointer (Community Addition)

The above can take on new light when you use the actual pointers in the list to perform the enumeration. The following starts with pp being assigned the address of the head pointer (not the node it points to; the actual pointer itself). We walk the list until pp hold the address of a pointer that is pointing to a node with the target to delete (could be the head pointer, could be a next pointer in some node, makes no difference). The pointer being addressed is set to its own node's next value, then the target node is removed.

This really should be watched in a debugger to see how it works, but the algorithm is remarkably simple given what is really going on:

Node **pp = &pHead;
while (*pp && (*pp)->data != target)
    pp = &(*pp)->next;

if (*pp)
{
    Node *victim = *pp;
    *pp = victim->next;
    delete victim;
}

Thats all of it. And you get head-node removal without having to special case it for free. Hope this helps as well.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
Spock77
  • 3,256
  • 2
  • 30
  • 39
  • Thank you. I will no longer use new for them from this point on. Although my question still remains, how do I delete my target node? I know you touched on it but can you explain a little more perhaps. – WombatCombat Mar 02 '14 at 00:17
  • @user3291106 - I provide a sample code. But it would be much more useful for you to write it yourself. Try now double-linked list and, say, search from end. – Spock77 Mar 02 '14 at 01:06
  • @Alex How does this finish when `pHead` points to the node that will be deleted? Follow: The while-loop will be skipped and do nothing. `pHead->next` will effectively be assigned to itself because `pPrev`, `pCur`, and `pHead` all point to the same node. The head node will then be destroyed with `delete pCur;`, thereby orphaning the entire remainder of the list and leaving all three pointers holding an invalid, indeterminate address. In a word, *ouch*. – WhozCraig Mar 02 '14 at 03:55
  • @WhozCraig Thank you for the correction! Fixed it. Although I would prefer that _user3291106_ tell me about it :) I need not to hurry with code posts, agree. – Spock77 Mar 02 '14 at 04:35
  • @Alex no problem. have a gander at the addendum. Not sure if you've ever seen it before, but it deserves a look. And +1 for sticking with the answer. – WhozCraig Mar 02 '14 at 04:49