Deleting a middle node from a single linked list when pointer to the previous node is not available

前端 未结 24 1166
陌清茗
陌清茗 2020-11-29 20:42

Is it possible to delete a middle node in the single linked list when the only information available we have is the pointer to the node to be deleted and not the pointer to

相关标签:
24条回答
  • 2020-11-29 21:11

    One approach would be to insert a null for the data. Whenever you traverse the list, you keep track of the previous node. If you find null data, you fix up the list, and go to the next node.

    0 讨论(0)
  • 2020-11-29 21:12

    Let's assume a list with the structure

    A -> B -> C -> D

    If you only had a pointer to B and wanted to delete it, you could do something like

    tempList = B->next;
    *B = *tempList;
    free(tempList);
    

    The list would then look like

    A -> B -> D

    but B would hold the old contents of C, effectively deleting what was in B. This won't work if some other piece of code is holding a pointer to C. It also won't work if you were trying to delete node D. If you want to do this kind of operation, you'll need to build the list with a dummy tail node that's not really used so you guarantee that no useful node will have a NULL next pointer. This also works better for lists where the amount of data stored in a node is small. A structure like

    struct List { struct List *next; MyData *data; };
    

    would be OK, but one where it's

    struct HeavyList { struct HeavyList *next; char data[8192]; };
    

    would be a bit burdensome.

    0 讨论(0)
  • 2020-11-29 21:12

    I appreciate the ingenuity of this solution (deleting the next node), but it does not answer the problem's question. If this is the actual solution, the correct question should be "delete from the linked list the VALUE contained in a node on which the pointer is given". But of course, the correct question gives you a hint on solution. The problem as it is formulated, is intended to confuse the person (which in fact has happened to me, especially because the interviewer did not even mention that the node is in the middle).

    0 讨论(0)
  • 2020-11-29 21:12

    You'll have to march down the list to find the previous node. That will make deleting in general O(n**2). If you are the only code doing deletes, you may do better in practice by caching the previous node, and starting your search there, but whether this helps depends on the pattern of deletes.

    0 讨论(0)
  • 2020-11-29 21:12

    This is a piece of code I put together that does what the OP was asking for, and can even delete the last element in the list (not in the most elegant way, but it gets it done). Wrote it while learning how to use linked lists. Hope it helps.

    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    
    struct node
    {
        int nodeID;
        node *next;
    };
    
    void printList(node* p_nodeList, int removeID);
    void removeNode(node* p_nodeList, int nodeID);
    void removeLastNode(node* p_nodeList, int nodeID ,node* p_lastNode);
    
    node* addNewNode(node* p_nodeList, int id)
    {
        node* p_node = new node;
        p_node->nodeID = id;
        p_node->next = p_nodeList;
        return p_node;
    }
    
    int main()
    {
        node* p_nodeList = NULL;
        int nodeID = 1;
        int removeID;
        int listLength;
        cout << "Pick a list length: ";
        cin >> listLength;
        for (int i = 0; i < listLength; i++)
        {
            p_nodeList = addNewNode(p_nodeList, nodeID);
            nodeID++;
        }
        cout << "Pick a node from 1 to " << listLength << " to remove: ";
        cin >> removeID;
        while (removeID <= 0 || removeID > listLength)
        {
            if (removeID == 0)
            {
                return 0;
            }
            cout << "Please pick a number from 1 to " << listLength << ": ";
            cin >> removeID;
        }
        removeNode(p_nodeList, removeID);
        printList(p_nodeList, removeID);
    }
    
    void printList(node* p_nodeList, int removeID)
    {
        node* p_currentNode = p_nodeList;
        if (p_currentNode != NULL)
        {
            p_currentNode = p_currentNode->next;
            printList(p_currentNode, removeID);
            if (removeID != 1)
            {
                if (p_nodeList->nodeID != 1)
                {
                    cout << ", ";
                }
    
                cout << p_nodeList->nodeID;
            }
            else
            {
                if (p_nodeList->nodeID !=2)
                {
                    cout << ", ";
                }
                cout << p_nodeList->nodeID;
            }
        }
    }
    
    void removeNode(node* p_nodeList, int nodeID)
    {
        node* p_currentNode = p_nodeList;
        if (p_currentNode->nodeID == nodeID)
        {
            if(p_currentNode->next != NULL)
            {
                p_currentNode->nodeID = p_currentNode->next->nodeID;
                node* p_temp = p_currentNode->next->next;
                delete(p_currentNode->next);
                p_currentNode->next = p_temp;
            }
            else
            {
                delete(p_currentNode);
            }
        }
        else if(p_currentNode->next->next == NULL)
        {
            removeLastNode(p_currentNode->next, nodeID, p_currentNode);
        }
        else
        {
            removeNode(p_currentNode->next, nodeID);
        }
    }
    
    void removeLastNode(node* p_nodeList, int nodeID ,node* p_lastNode)
    {
        node* p_currentNode = p_nodeList;
        p_lastNode->next = NULL;
        delete (p_currentNode);
    }
    
    0 讨论(0)
  • 2020-11-29 21:13

    Not if you want to maintain the traversability of the list. You need to update the previous node to link to the next one.

    How'd you end up in this situation, anyway? What are you trying to do that makes you ask this question?

    0 讨论(0)
提交回复
热议问题