添加元素的双链表

Doubly Linked List adding elements

本文关键字:链表 元素 添加      更新时间:2023-10-16

我有一个uni赋值,不幸的是,遇到了一个问题。
我仍然在为指针和引用而挣扎,所以我很难找到解决方案,尽管我已经搜索了一整天。

以下是我的代码的重要部分:

struct BuenoList
{
    int value;
    BuenoList* prev;
    BuenoList* next;
};

声明:

void insertNode(BuenoList*, int);

定义:

void insertNode(BuenoList* tail, int _id)
{
    BuenoList* temp = new BuenoList;
    temp->value = _id;
    temp->prev = tail;
    tail->next = temp;
    tail = temp;
    tail->next = NULL;
}

现在,在main()中,我这样做:

int main(int argc, char **argv)
{
    BuenoList* BuenoListing = new BuenoList;
    BuenoListing->value = 1;
    BuenoListing->prev = NULL;
    BuenoListing->next = NULL;
    BuenoList* BuenoHead = BuenoListing;
    BuenoList* BuenoTail = BuenoListing;
    insertNode(BuenoTail, 2); // Add value 2 to the list
    insertNode(BuenoTail, 3); // Add value 3 to the list
    return 0;
}

好吧,问题来了:当我从第一个元素打印列表时,它的打印方式如下:
1
1 2
1 3
所以很明显这条线

insertNode(BuenoTail,3);

覆盖值2。

我的猜测是BuenoTail不会改变,所以引用一定有问题。

我该如何解决这个问题?打印应为:1 2 3

@编辑

void deleteNode(BuenoList*& tail, int _id) // Search list for specified value and delete it
{
    BuenoList* temp = tail;
    while (temp->prev != NULL)
    {
        if (temp->value == _id) break; 
        else temp = temp->prev;
    }
    if (temp->value == _id)
    {
        temp->prev = temp->next;
        free(temp);
    }
    else std::cout << "ERROR KEY DOES NOT EXISTn";
}

考虑到您希望保持代码结构不变,我将向您展示两种可能的解决方案。在C模式中,您可以使用指向指针的指针来更新头部和尾部指针。或者,在C++中,您可以通过引用传递头指针和尾指针。就我个人而言,在C++中,我会创建一个LinkedList类来跟踪头部和尾部节点。

通过引用传递指针(C++)

为了通过引用传递指针,首先更改insertNode声明

void insertNode(BuenoList *&tail, int _id);

接下来,使用相同的函数参数更改insertNode定义。就是这样,您的代码现在应该可以工作了。这种微小的更改是有效的,因为insertNode函数中的tail节点与main函数中的tail节点具有别名。

逐指针传递指针(C)

我知道您放置了一个C++标记,但您也可以使用更类似C的方法更新headtail节点。首先,在主函数中,您需要将BuenoHeadBuenoTail声明为指向指针的指针。

int main(int argc, char **argv)
{
    BuenoList* BuenoListing = new BuenoList;
    BuenoListing->value = 1;
    BuenoListing->prev = NULL;
    BuenoListing->next = NULL;
    BuenoList** BuenoHead = new BuenoList*;
    BuenoList** BuenoTail = new BuenoList*;
    *BuenoHead = BuenoListing;
    *BuenoTail = BuenoListing;
    insertNode(BuenoTail, 2); // Add value 2 to the list
    insertNode(BuenoTail, 3); // Add value 3 to the list
    return 0;
}

然后,您需要更新insertNode函数声明,以获取指向指针的指针。

void insertNode(BuenoList** tail, int _id);

然后,你需要更新函数定义,以使你的指针正确地指向一个指针,

void insertNode(BuenoList** tail, int _id) 
{
    BuenoList* temp = new BuenoList;
    temp->value = _id;
    temp->prev = *tail;
    temp->next = NULL;
    (*tail)->next = temp;
    *tail = temp;
}

编辑

删除节点

您修改了问题,请求有关删除节点的帮助。您的deleteNode函数有几个问题。

  1. newfree混合。无论何时使用new进行分配,都应相应地使用delete
  2. 调用temp->prev时不检查temp是否可以是NULL
  3. 您需要更改函数参数以包含head指针。结果可能是你想要删除的节点是你的链表的头。如果是这样,则需要相应地更新头节点
  4. 您需要检查要删除的节点是否位于列表的中间、列表的头、列表的尾,或者是否是列表的唯一节点。每种情况都需要不同的操作来更新您的链接列表

考虑到这是一项大学作业,我不想给你全面的解决方案。这是一个经过部分修改的deleteNode函数。不过,我留下了一些部分让你填写。希望这能有所帮助。也许下次再把问题集中一点,这样我就不必给出部分答案了。

void deleteNode(BuenoList*& tail, BuenoList*& head, int _id) {
    BuenoList* toDelete;
    toDelete = tail;
    // Traverse list and find node to delete
    while( ( toDelete != NULL ) && ( toDelete->value != _id ) ) {
        toDelete = toDelete->prev;
    }
    // If node not found, return
    if( toDelete == NULL ) {
        std::cout << "ERROR KEY DOES NOT EXISTn";
        return;
    }
    // Check to see if node to delete is tail
    if( toDelete == tail ) {
        if( toDelete->prev != NULL ) {
            tail = toDelete->prev;
            tail->next = NULL;              
        } else { //Deleting only node in list
            tail = NULL;
            head = NULL;
        }
        delete toDelete;
        return;
    }
    // Check to see if node to delete is head
    if( toDelete == head ) {
        // FILL OUT WHAT TO DO HERE
        return;
    }
    // Node to delete is neither head nor tail.
    // FILL OUT WHAT TO DO HERE
    return;
}

您正在insertNode()中更新tail,但更新后的值不会以任何方式返回给调用者。所以BuenoTail并没有像您所怀疑的那样发生变化。

解决这个问题的一个简单方法是将您的功能更改为:

BuenoList *insertNode(BuenoList* tail, int _id)

并从该函数返回新的CCD_ 25。同时将呼叫更改为

BuenoTail = insertNode(BuenoTail, 2); // Add value 2 to the list

您可能需要考虑使用节点结构和列表结构:

struct BuenoNode
{
    int value;
    BuenoNode* prev;
    BuenoNode* next;
};
struct BuenoList
{
    BuenoNode* head;
    BuenoNode* tail;
    size_t count; // having a count would be optional
}

列表函数将使用一个指向列表结构的指针,例如InsertNode(BuenoList*blptr,int data);列表结构将被初始化,使得头指针和尾指针都==NULL,并且您需要检查是否将节点添加到空列表中,或者删除列表中唯一的节点以得到空列表。