【问题标题】:C++ get previous node to matching node in singly linked listC ++将前一个节点获取到单链表中的匹配节点
【发布时间】:2017-07-14 20:12:41
【问题描述】:

开始:这是家庭作业的一部分,所以请随意提示答案或指出正确的方向,而不是直接回答。

我在 c++ 中创建一个单链表,其中一个必需的函数是 void remove(const T& key),如果值与传递给函数的键的值匹配,则删除给定节点。

我目前的想法是,我必须首先,找到要删除的节点,找到要删除的节点之前的节点,然后找到要删除的节点之后的节点。从那里我可以删除需要删除的节点,并将前一个节点设置为指向已删除节点之后的节点。

以下是相关功能:

LinkedList.h

//Returns the node with passed in value key
ListNode<T>* find(const T& key) {
    ListNode<T>* currentNode = _head;
    while(currentNode != NULL && currentNode->data() != key){
        currentNode = currentNode->next();  
    }
    return currentNode; 
}

//Returns the node before the key
ListNode<T>* findPreviousNode(const T& key){
    ListNode<T>* previousNode;
    ListNode<T>* currentNode = _head;

    while(currentNode != NULL && currentNode->data() != key){
        previousNode = currentNode;
        currentNode = currentNode->next();  
    }
    return previousNode;
}

// Removes and deletes the first node in the linked list that has data
// equal to the  key
void remove(const T& key) {
    ListNode<T>* nodeToDelete = find(key);
    ListNode<T>* previousNode = findPreviousNode(key);
    ListNode<T>* nextNode = nodeToDelete->next();
    delete nodeToDelete;
    previousNode->setNext(nextNode);

}

我已经对我的find(const T&amp; key) 函数进行了广泛的测试,并且它可以正常工作,所以我相信问题出在我的 findPreviousNode 函数中,但是当我浏览代码时,它似乎工作正常。

在我看来,previousNode 将始终具有最后检查的元素,当找到匹配项时,它会返回尚未更新的 previousNode,因此它仍然包含直接在匹配节点之前的节点,但这显然不是正确,我不知道为什么。当我运行代码时,我得到一个

分段错误(核心转储)

错误信息

这里有一些包含完整代码的粘贴箱:

LinkedList.h http://pastebin.com/b4miZBzA

main.cpp(调用测试函数的方法)http://pastebin.com/0QGtUhjC

【问题讨论】:

标签: c++ data-structures linked-list


【解决方案1】:

你显然错过了很多边缘案例。

您的find() 函数未处理未找到密钥的情况。在这种情况下,它会返回 null,findPreviousNode() 会为此返回 previousNode 的垃圾值。

假设find() 返回指向头部的指针。然后你的findPreviousNode() 再次返回未初始化的前一个节点指针。

尝试处理代码中的边缘情况。

你的 remove() 函数应该可以正常工作,假设这些都得到了处理。

此外,您实际上并不需要调用 find() 函数,那么您可以通过从 findPreviousNode() 返回适当的值来真正改善运行时,因为您正在运行两个不必要的循环,因此您可以节省你的运行时。

【讨论】:

  • find() 的指令是在未找到该值时返回 NULL,但现在我确实看到了在 findPreviousNode() 尝试获取 null 的下一个节点时这会如何导致问题价值。我会尝试解决这个问题,看看是否能解决任何问题。
  • 阅读我回答的最后一行,并尝试使用它来解决您的代码效率低下问题。
  • 为什么我不需要运行 find() 函数?这是必需的,所以我可以删除相应的节点
  • 只是一个提示:你在 findPreviousNode() 函数中做同样的事情。如果您可以从 findPreviousNode() 函数中获取前一个节点,那么您实际上并不需要 find(),因为 find() 的输出可以很容易地从 findPreviousNode()-&gt;next(); 的输出中获得,给它你最好的机会,然后让我知道如果您需要更多帮助。
  • 问题最终成为其中一个测试删除了 LinkedList 的第一个元素,我试图设置之前的空指针。感谢您的回答
【解决方案2】:

从您在问题中发布的代码来看,您的想法似乎是正确的。

两个提示:

  1. 防御性编程。检查 nodeToDelete 和 previousNode 是否不为 NULL。目前,如果未找到密钥,您最终将取消引用一个 NULL 指针,这可能是您的分段错误的原因。

  2. 效率。为什么要遍历列表两次(一次在“find”中,一次在“findPrevious”中),而您只需遍历一次并获得两个值? IE。结合 find() 和 findPrevious() 函数来减少程序必须做的工作量。

【讨论】:

  • for 1 我相信这是我正在解决的问题。为 2 进行编码时,我肯定觉得它效率低下,但是因为有时我需要该节点,而其他时候我需要将前一个节点拆分为两个函数,因为我无法更改方法参数以包含布尔值或其他东西来指示我是否想要返回以前的或当前的
猜你喜欢
  • 1970-01-01
  • 2011-11-04
  • 2021-05-25
  • 1970-01-01
  • 2013-12-02
  • 2018-07-04
  • 2021-08-02
  • 2011-12-23
  • 1970-01-01
相关资源
最近更新 更多