【问题标题】:Remove all occurrences of the given string from doubly linked list从双向链表中删除所有出现的给定字符串
【发布时间】:2017-04-19 21:21:08
【问题描述】:
int StringList::remove(string value)
{
if ((head == NULL) || (value > tail->data) || (value < head->data))
{
    return false;
}

if ((head == tail) && (head->data == value))
{
    delete head;
    head = tail = NULL;
    return true;
}

if ((head->data) == value)
{
    head = head->next;
    delete head->previous;
    head->previous = NULL;
    return true;
}

if ((tail->data) == value)
{
    tail = tail->previous;
    delete tail->next;
    tail->next = NULL;
    return true;
}

Node *nodeToDelete = head;

while ((nodeToDelete->data) < value)
{
    nodeToDelete = nodeToDelete->next;
}

if ((nodeToDelete->data) == value)
{
    nodeToDelete->previous->next = nodeToDelete->next;
    nodeToDelete->next->previous = nodeToDelete->previous;
    delete nodeToDelete;
    return true;
}
else
{
    return false;
}
}

我在这里有一个双向链表,我试图删除给定字符串的所有出现。目前该功能只会删除一个事件,这很好但不太有效。我相信我需要以某种方式实现一个计数器变量,该变量将计算给定字符串被删除的次数,但我不太确定如何去做。

完整代码:https://pastebin.com/3bRfJzJT

【问题讨论】:

  • 为什么需要计数器。只需枚举列表并删除字符串匹配的任何节点。如果您需要以某种方式返回已删除的实例数,那是一个几乎相关的问题。
  • 真的没那么相关吗?
  • 是的,确实不相关。您遍历列表,拉出匹配的节点并根据需要处理它们。除非该函数专门针对特定数量的移除,否则多少无关紧要。
  • 您所拥有的:void removeAll(string value) { while(remove(value)) /*empty*/; }。 (即使它不是性能)

标签: c++ linked-list doubly-linked-list


【解决方案1】:
int StringList::remove(string value)
{
    Node* curr = head;
    while (curr != NULL)
    {
        if ((curr->data) == value)
        {
            if (curr == head)
            {
                head = curr->next;
                if (head->prev != NULL)
                    head->prev = NULL;
                else
                    tail = NULL;
                delete curr;
                curr = head;
            }
            else if (curr == tail)
            {
                tail = curr->prev;
                tail->next = NULL;
                delete curr;
                curr = NULL;
            }
            else
            {
                curr->prev->next = curr->next;
                curr->next->prev = curr->prev;
                Node* next = curr->next;
                delete curr;
                curr = next;
            }
        }
        else
            curr = curr->next;
    }
}

【讨论】:

  • head == tail == curr时好像你没处理。
  • @Jarod42 谢谢,已修复。
  • @DavidSchwartz 哇,这真是太快了,基本上你把函数包装在一个 while 循环中?
  • @LearningCode 是的,完全正确。 (您可以通过添加一个deleteNode 函数来简化此操作,该函数删除一个节点并返回其后的下一个节点。)
【解决方案2】:
int StringList::remove(string value)
{
    int numDeleted = 0;

    Node *node = head;
    while (node)
    {
        Node *nextNode = node->next;

        if (node->data == value)
        {
            if (head == node)
                head = head->next;

            if (tail == node)
                tail = tail->previous;

            if (node->previous)
                node->previous->next = node->next;

            if (node->next)
                node->next->previous = node->previous;

            delete node;
            ++numDeleted;
        }

        node = nextNode;
    }

    return numDeleted;
}

话虽如此,您确实应该使用std::list 而不是手动列表实现。让它为您处理节点,包括删除值,例如:

#include <list>

class StringList
{
private:
    std::list<std::string> data;

public:
    ...
    void remove(string value);
};

void StringList::remove(string value)
{
    data.remove(value);
}

【讨论】:

    猜你喜欢
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 2014-08-07
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多