【问题标题】:Single pointer for linked list deletion function // is it possible链表删除函数的单指针 // 可以吗
【发布时间】:2020-01-30 17:37:28
【问题描述】:

目前,我正在研究链表结构

当我搜索时,使用'双指针'的链表删除功能。
在下面的代码中,节点被删除函数中的双指针成功删除。

#include <iostream>
using namespace std;

struct node
{
    int data;
    node* next;
};

class LinkedList
{
private:
    node* head;
    node* tail;
public:
    LinkedList()
    {
        head = nullptr;
        tail = nullptr;
    }
    void add_node(int n)
    {
        node* temp = new node;
        temp->data = n;
        temp->next = nullptr;

        if(head == nullptr)
        {
            head = temp;
            tail = temp;
        }
        else
        {
            tail->next = temp;
            tail = tail->next;
        }
    }
    node* gethead()
    {
        return head;
    }
    void display(node * head)
    {
        if(head == nullptr)
        {
            cout << "nullptr : No data" << endl;
            return;
        }
        else
        {
            node* temp;
            temp = head;
            while(temp != nullptr)
            {               
                cout << temp->data << endl;
                temp = temp->next;
            }
        }        
    }
    void del(node* head, int value)
    {       
        if(!head)
        {
            return;
        }
        else
        {
            node** nd = &head;
            while(*nd && (*nd)->data != value)
                nd = &(*nd)->next;
            if(*nd)
            {
                node* temp = *nd;
                *nd = (*nd)->next;
                delete temp;
            }
            else
            {
                cout << "No matching data in the node" <<endl;
            }           
        }   
    }
};

int main()
{
    LinkedList la;
    la.add_node(10);
    la.add_node(20);
    la.add_node(30);
    la.add_node(40);
    la.add_node(50);

    la.display(la.gethead()); //10 20 30 40 50 

    la.del(la.gethead(), 40);
    la.display(la.gethead()); //10 20 30 50

    return 0;
}

我只是想知道为什么下面的代码不起作用。
我试图通过不使用双指针来简化代码。

#include <iostream>
using namespace std;

struct node
{
    int data;
    node* next;
};

class LinkedList
{
private:
    node* head;
    node* tail;
public:
    LinkedList()
    {
        head = nullptr;
        tail = nullptr;
    }
    void add_node(int n)
    {
        node* temp = new node;
        temp->data = n;
        temp->next = nullptr;

        if(head == nullptr)
        {
            head = temp;
            tail = temp;
        }
        else
        {
            tail->next = temp;
            tail = tail->next;
        }
    }
    node* gethead()
    {
        return head;
    }
    void display(node * head)
    {
        if(head == nullptr)
        {
            cout << "nullptr : No data" << endl;
            return;
        }
        else
        {
            node* temp;
            temp = head;
            while(temp != nullptr)
            {               
                cout << temp->data << endl;
                temp = temp->next;
            }
        }        
    }
     void del(node* head, int value)
    {       
        if(!head)
        {
            return;
        }
        else
        {
            node* pp = head;

            while((pp)->data != value)
                pp = pp->next;
            if(pp)
            {
                node* temp = pp;  
                pp = pp->next;
                delete temp;
            }
            else
            {
                cout << "No matching data in the node" <<endl;
            }    
        }   
    }
};

int main()
{
    LinkedList la;
    la.add_node(10);
    la.add_node(20);
    la.add_node(30);
    la.add_node(40);
    la.add_node(50);

    la.display(la.gethead()); //10 20 30 40 50 

    la.del(la.gethead(), 40);
    la.display(la.gethead()); //10 20 30 50

    return 0;
}

您能否给我一些建议,说明为什么上面的代码没有像第一个代码那样删除节点?
我认为第二个代码必须工作,因为它通过利用指针(保存节点的地址)删除节点。

提前致谢。

【问题讨论】:

  • 通过简化,您的字面意思是“从代码中删除一个 '*'”吗?
  • pp 和 temp 指向您删除的同一节点。您需要修改前一个节点的下一个指针(或头部,如果在开头)。
  • 解释“不工作”。为什么你认为它不起作用?怎么不行。它的行为是否与您的预期不同?你期待什么?
  • @sweenish 是的,我的意图是使用一个“*”作为删除功能。

标签: c++ pointers linked-list


【解决方案1】:

首先,术语是“指向指针的指针”而不是“双指针”。双指针是指向double类型变量的指针。

您应该真正意识到指针只是内存中的地址。 当您复制指针时(即:node* pp = head;),您将 head 指向的地址放入 pp。 这是什么意思? pp 和 head 都指向同一个地址。

但是,同样重要的是要记住 pp 和 head 是变量,因此也写入内存中。话说——pp 和 head 也有地址,但是由于 pp 和 head 是不同的变量,所以它们有不同的地址。

因此,当您尝试修改 head 的内容时,问题就来了。

在第一次出现时:

            node** nd = &head;
            while(*nd && (*nd)->data != value)
                nd = &(*nd)->next;

您根本不会修改 head(或*nd)的内容。因此,您可以使用带有 pp 的版本。

你的问题在于这段代码:

pp = pp->next;

这里,pp 是原始链表项的地址的副本,既然它只是一个副本,那么pp = pp-&gt;next 几乎什么都不做。在这种情况下,您真的应该写 *nd = *nd-&gt;next,因为这样会更改原始值,而不是您创建的副本。

注意:即使您将在第二个示例中将变量 pp 更改为指针到指针,您的代码仍然无法删除列表中的第一个元素,因为它是作为指向 head 的常规指针,因此只有您的第一个版本有效。

【讨论】:

  • 我理解你的解释。非常感谢您提供的详细信息。正如您所提到的,在第二个代码中,pp = pp-&gt;next 实际上什么也没做。谢谢你的观点。此外,delete temp 并没有删除我期望的节点,而是删除了 pp(它只是保存了节点的地址)。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 2015-07-23
  • 2016-03-18
  • 2021-05-07
  • 2012-10-06
  • 2018-07-28
相关资源
最近更新 更多