0

我在以递归方式从循环单链表中删除单个节点/值时遇到了一些问题(当然,如果可能的话)。我的代码仅从中间删除,而不是从第一个或最后一个位置删除。

在以递归方式删除其中一个后,我无法弄清楚如何建立连接。我的意思是,如果我要删除第一个元素,那么我需要将最后一个节点连接到下一个节点。

这是我的代码:

Node *ListDelete(Node *list, Node *tail, int val, Node **deleted) {
    if (!list || (list == tail && list->value != val)) {
        *deleted = NULL;
        return list;
    }

    if (list->value == val) {
        *deleted = list;
        return list->next;
    }

    list->next = ListDelete(list->next, tail, val, deleted);
    return list;
}

参数和返回:

        case MENU_DELETE:
            val = GetValue("Enter value");
            if (list) tail = FindTail(list);
            list = ListDelete(list, tail, val, &node);
            ListPrintNode(node, "Deleted");
            free(node);

查找尾函数:

Node* FindTail(Node* list)
{
    Node* temp = list;
    while(temp->next != list)
        temp = temp->next;
    return temp;
}
4

1 回答 1

1

is的 APIListDelete有一个tail不需要的参数。

这是一个没有这种论点的实现。它返回一个指向循环列表的指针,第一个节点从该循环列表value == val开始,list->next并将指向该节点的指针存储到*deleted

Node *ListDelete(Node *list, int val, Node **deleted) {
    // special case empty and singleton lists
    if (!list || (list == list->next && list->value != val)) {
        *deleted = NULL;
        return list;
    }
    if (list == list->next) {
        *deleted = list;
        return NULL;
    }
    for (Node *node = list;; node = node->next) {
        if (node->next->value == val) {
            *deleted = node->next;
            node->next = node->next->next;
            if (list == *deleted)
                list = node->next;
            return list;
        } else
        if (node->next == list)
            *deleted = NULL;
            return list;
        }
    }
}

使用您的 API,以下是您的代码的更正版本:

Node *ListDelete(Node *list, Node *tail, int val, Node **deleted) {
    if (!list || (list == list->next && list->value != val)) {
        *deleted = NULL;
        return list;
    }
    if (list == list->next) {
        *deleted = list;
        return NULL;
    ]
    if (list->next->value == val) {
        *deleted = list->next;
        list->next = list->next->next;
        return list;
    }
    if (list == tail) {
        *deleted = NULL;
        return list;
    }
    ListDelete(list->next, tail, val, deleted);
    if (list == *deleted)
        list = list->next;
    return list;
}

这种递归实现的缺点是递归的深度是列表的长度。这种递归不是尾递归,因此足够长的列表会导致堆栈溢出

为避免这种情况,您可以将函数转换为非递归函数:

Node *ListDelete(Node *list, Node *tail, int val, Node **deleted) {
    // special case empty and singleton lists
    if (!list || (list == list->next && list->value != val)) {
        *deleted = NULL;
        return list;
    }
    if (list == list->next) {
        *deleted = list;
        return NULL;
    }
    for (Node *node = list;; node = node->next) {
        if (node->next->value == val) {
            *deleted = node->next;
            node->next = node->next->next;
            if (list == *deleted)
                list = node->next;
            return list;
        } else
        if (node == tail) { // equivalent to if (node->next == list)
            *deleted = NULL;
            return list;
        }
    }
}
于 2020-04-12T18:09:56.920 回答