【问题标题】:assignment operator for linked list链表的赋值运算符
【发布时间】:2017-03-16 07:15:30
【问题描述】:
#include <iostream>

using namespace std;

class LinkedList
{
private: 

    struct ListNode
    {
    int value;
    struct ListNode *next;
    };

ListNode *head;

public:
    LinkedList()
    {
        head = NULL;
    }
    ~LinkedList();

    const LinkedList& operator=(const LinkedList &rhs);

    void appendNode(int);
    void insertNode(int);
    void deleteNode(int);

    ListNode *removeLast();
};

void LinkedList::appendNode(int num)
{
    ListNode *newNode;
    ListNode *nodePtr;

    newNode = new ListNode;
    newNode->value = num;
    newNode->next = NULL;

    if (!head)
    {
        head = newNode;
    }
    else
    {
        nodePtr = head;

        while (nodePtr->next)
        {
            nodePtr = nodePtr->next;
        }

        nodePtr->next = newNode;
    }
}

void LinkedList::insertNode(int num)
{
    ListNode *newNode;
    ListNode *nodePtr;
    ListNode *preNode;

    newNode = new ListNode;
    newNode->value = num;

    if (!head)
    {
        head = newNode;
        newNode->next = NULL;
    }
    else
    {
        nodePtr = head;
        preNode = NULL;

        while (nodePtr->next)
        {
            preNode = nodePtr;
            nodePtr = nodePtr->next;
        }

        if (!preNode) // if new node is to be the 1st in the list
        {
            head = newNode;
            newNode->next = nodePtr;
        }

        else
        {
            preNode->next = newNode;
            newNode->next = nodePtr;
        }

    }
}

void LinkedList::deleteNode(int num)
{
    ListNode *nodePtr;
    ListNode *preNode;

    if (!head)
        return;

    if (head->value == num)
    {
        nodePtr = head->next;
        delete head;
        head = nodePtr;
    }

    else
    {
        nodePtr = head;

        while (nodePtr != NULL && nodePtr->value != num)
        {
            preNode = nodePtr;
            nodePtr = nodePtr->next;
        }

        if (nodePtr)
        {
            preNode->next = nodePtr->next;
            delete nodePtr;
        }
    }
}

const LinkedList& LinkedList::operator=(const LinkedList &rhs)
{
    if (this != &rhs)
    {
        ListNode *curr, *nextNode;

        curr = head;
        nextNode = NULL;

        while (curr)
        {
            nextNode = curr->next;
            delete curr;
            curr = nextNode;
        }

        ListNode *cptr = new ListNode;
        cptr = rhs.head;
        cptr->next = NULL;

        temp = rhs.head->next;
        while (temp)
            {
                cptr->next = new ListNode;
                cptr->next = temp;
                cptr = cptr->next;
                cptr->next = NULL;

                temp = rhs.head->next;
            }
        }

    return *this;
}

LinkedList::ListNode* LinkedList::removeLast()
{
    ListNode *nodePtr, *preNode;

    if (!head)
    {
        return;
    }

    nodePtr = head;
    preNode = NULL;

    while (nodePtr->next)
    {
        preNode = nodePtr;
        nodePtr = nodePtr->next;
    }

    preNode->next = NULL;

    return nodePtr;
}

LinkedList::~LinkedList()
{
    ListNode *nodePtr;
    ListNode *nextNode;

    nodePtr = head;

    while (nodePtr)
    {
        nextNode = nodePtr->next;
        delete nodePtr;
        nodePtr = nextNode;
    }
}

感谢那些帮助我的人!

我修复了赋值运算符和 removeLast 函数。

对于removeLast,倒数第二个节点指向null,然后返回最后一个节点

我不确定我的赋值运算符是否正常。

还有 removeLast 函数..

如果你们发现错误,请告诉我!

再次感谢您!

【问题讨论】:

  • 也存储“tail”节点,那么您不必搜索整个列表来找到最后一个节点。 (对于 appendNode)
  • 是的,我知道 tail 对运行时间有很大帮助,但是,我只想先完全了解 SLL。谢谢你的提示!
  • 在 insertMode 中,您忘记为 newNode 分配内存,执行 newNode = new ListNode;并且您可以为 ListNode 创建一个默认构造函数,在其中您可以将 next 设置为 NULL,这样每当新节点创建时,它的 next 就是 NULL。
  • 另一个技巧是在创建列表时为 head 创建一个“虚拟”节点。你不把它算作一个真正的节点。然后你永远不需要做“is head null”检查。 if 语句在性能方面的成本很高,并且由于不检查而减少的代码弥补了头节点的额外空间。
  • 在析构函数中,您将删除所有节点,为该 like(deleteAll) 创建单独的私有函数,并从析构函数和赋值重载中调用它。

标签: c++ linked-list copy-constructor assignment-operator


【解决方案1】:

另外,你们能教我如何声明“ListNode *removeLast();”吗?

LinkedList::ListNode* LinkedList::removeLast()

您刚刚将返回类型和类交叉,但 ListNode 也在 LinkedList 中声明,因此您必须在使用时将其指定为“LinkedList::ListNode”。

据我所知,您的析构函数看起来已经找到了。您只是将一个指针设置为等于另一个指针,这不会触发复制构造函数。

至于创建深拷贝,指针只是保存内存地址,它们本身不是东西。

ListNode *node = head;

只创建一个指向头节点的指针。要制作副本,您必须执行以下操作:

ListNode node = *head; // sometimes brackets such as (*head) avoids errors

或者这个

ListNode *node = new ListNode;
*node = *head;

.

* 

在指针名称之前是“取消引用”。它是对指向的对象的引用,而不是指针变量。然后,您可以使用正常的复制语义。对于非常简单的类(即所有简单对象),默认的复制行为就足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 2019-04-02
    • 2016-02-24
    • 2011-08-02
    相关资源
    最近更新 更多