当前位置: 首页 > 知识库问答 >
问题:

插入到双链接列表

张敏达
2023-03-14

我正在尝试为一个项目创建一个双链接列表容器。我不能使用任何std容器。必须对双链接列表进行排序。以下是我目前的代码:

#include <iostream>
using namespace std;

template <typename T>
class dll {
private:
    struct Node {
        Node* prev;
        Node* next;
        T data;
    };

    Node* head;
    Node* tail;

public:
    dll();
    ~dll();

    void insert(T value);

    bool empty() const { return head == tail; };
};

template <typename T> dll<T>::dll() {
    head = nullptr;
    tail = head;
}

template <typename T> dll<T>::~dll() {
    delete[] head;
}

template <typename T> void dll<T>::insert(T value) {
    Node *node = new Node;
    node->data = value;
    // Case 1: There are no nodes yet
    if (head == nullptr) {
        node->prev = nullptr;
        node->next = nullptr;
        head = node;
        tail = head;
    }
    else {
        // Case 2: There is more than one node
        Node *curr = head;
        if (curr->next != nullptr)
        {
            while (curr->next) {
                // If the value is less than the current value
                if (value < curr->data) {
                    Node *temp = new Node;
                    temp->data = curr->data;
                    temp->next = curr->next;
                    temp->prev = curr->prev;
                    node->next = temp;
                    node->prev = temp->prev;
                    curr->prev = node;
                }
                curr = curr->next;
            }
        }
        // Case 3: There is only one node
        else {
            node->prev = head;
            node->next = nullptr;
            tail = node;
        }
    }
}

int main() {
    dll<int> list;
    list.insert(10);
    list.insert(20);
    list.insert(15);
}

我遇到的问题是在我的插入函数中。我正在使用调试器,并在以下行插入代码:list.insert(10);。

它正确地进入第一种情况,即head==nullptr并创建节点。当我进入下一行代码(list.insert(20))时,它会用这一行创建一个节点:node*node=newnode;但它正在创建具有head指向的内存地址的节点。

我在头变量上放了一个手表,节点变量和内存地址是相同的。基本上,它正在创建与上次插入相同的节点。

我不知道如何获取该行:Node*code=newnode;创造新事物。我在这里使用的新关键字是错误的吗?

共有2个答案

郭思淼
2023-03-14

首先,析构函数无效。此声明

delete[] head;

表示头部是一个数组。然而,head不是数组。它是指向Node类型的单个对象的指针。必须删除析构函数中列表的所有节点。析构函数可以如下所示

template <typename T> 
dll<T>::~dll() 
{
    while ( head )
    {
        Node *tmp = head;
        head = head->next;
        delete tmp;
    }
}

至于insert方法,它看起来非常简单。例如

template <typename T> 
void dll<T>::insert( const T &value ) 
{
    Node *current  = head;
    Node *previous = nullptr;

    while ( current && !( value < current->data ) )
    {
        previous = current;
        current  = current->next;
    }

    Node *node = new Node { previous, current, value };

    if ( previous == nullptr ) head = node;
    else previous->next = node;

    if ( current  == nullptr ) tail = node;
    else current->prev = node;
}

并且没有任何需要和理由向结构节点添加构造函数。当它是一个集合体时更好。

这里有一个测试程序

#include <iostream>

template <typename T>
class dll 
{
private:
    struct Node 
    {
        Node *prev;
        Node *next;
        T data;
    };

    Node *head;
    Node *tail;

public:
    dll();
    ~dll();

    void insert( const T &value);

    bool empty() const { return head == tail; };

    void print() const;
};

template <typename T> 
dll<T>::dll() 
{
    head = tail = nullptr;
}

template <typename T> 
dll<T>::~dll() 
{
    while ( head )
    {
        Node *tmp = head;
        head = head->next;
        delete tmp;
    }
}

template <typename T> 
void dll<T>::insert( const T &value ) 
{
    Node *current  = head;
    Node *previous = nullptr;

    while ( current && !( value < current->data ) )
    {
        previous = current;
        current  = current->next;
    }

    Node *node = new Node { previous, current, value };

    if ( previous == nullptr ) head = node;
    else previous->next = node;

    if ( current  == nullptr ) tail = node;
    else current->prev = node;
}

template <typename T> 
void dll<T>::print() const
{
    for ( Node *current = head; current; current = current->next )
    {
        std::cout << current->data << ' ';
    }
}

int main() 
{
    dll<int> list;

    list.insert( 10 );
    list.insert( 20 );
    list.insert( 15 );

    list.print();
    std::cout << std::endl;

    return 0;
}

输出是

10 15 20 
樊桐
2023-03-14

为了使Node的初始化更容易,让我们添加一个合理的构造函数,将prev和Next成员初始化为null。这使得以后的代码更容易。

struct Node {
    Node* prev;
    Node* next;
    T data;
    Node() : prev(nullptr), next(nullptr)
    {

    }
};

链表问题中总有四种情况需要注意。你得到了一些。插入到空列表中。在列表的前面插入,在列表的末尾插入,在列表的中间插入。

template <typename T> void dll<T>::insert(T value) {
    Node *node = new Node;
    node->data = value;

    // Case 1: There are no nodes yet
    if (head == nullptr) {
        head = node;
        tail = head;
        return;
    }


    // case 2 - inserting at the head of the list
    if (node->data < head->data)
    {
        node->next = head;
        head = node;
        return;
    }

    // case 3 - inserting at the end of the list
    if (node->data >= tail->data)
    {
        node->prev = tail;
        tail->next = node;
        tail = node;
        return;
    }

    // general case - inserting into the middle
    Node* probe = head;
    while (probe && (node->data >= probe->data))
    {
        probe = probe->next;
    }
    if (probe)
    {
        node->next = probe;
        node->prev = probe->prev;
        probe->prev->next = node;
        probe->prev = node;
        return;
    }

    // error - we shouldnt' reach this point. If we did, it meant the list was out of order to begin with.
    return;
}
 类似资料:
  • 我正在尝试创建一个函数,用于在双链接列表的末尾添加。我无法精确指出为什么它没有打印出任何内容。 当我构建程序时,没有出现错误。 我正在确定。新建节点首先检查头部是否有任何值 在上一个当前指针之后创建 我将前一个节点连接到新节点,新节点指向前一个节点,而新节点指向nullptr作为下一个节点。

  • 我有以下代码,它是双链表实现的一部分。然后,我必须使用我的ADT实现来创建一个表,其格式为(它是一个字符串)、(它是uint32_t类型)(因此是一个2列的表)。 我需要首先创建这个表,然后添加到这个记录。 我的困难在于实现一个函数,该函数将要添加的值插入到这个特定的表中。我需要另一个插入功能,还是必须编辑我拥有的功能? 如果需要一个新的函数作为参数:一个指向结构类型的新表>代码> ListSt目

  • 因此,我对数据结构很陌生,我在对数组进行排序时,在尝试了几天之后,我偶然发现了双链表的插入排序。我仍然无法理解排序有什么问题,是的,我已经在线检查过,我不能只插入排序,我需要对函数参数中传递的列表进行排序,它的名称是internationSort(Dlinkedlist-arr)。 ` ` 我尝试实现它,但我被困住了,因为处理数组的逻辑有点不同,因为我们正在使用 next 和 prev 指针,这使

  • 我试图在C中的双向链表上做插入排序。在这种状态下,我的代码让我陷入了一个没有结束的循环,吐出了8和9。 有人能好心解释一下“插入排序”方法是如何设计的吗? 我的链表是设计包含头,上一个,下一个和一些数据。 到目前为止这是我的代码 我的希望破灭了。请帮忙。

  • 我正在尝试使用时循环将元素添加到双向链表中。节点正在制作中,但它们都存储相同的单词,这是我正在阅读的文件的最后一个单词。这是我的时循环: 在while循环开始之前,光标被初始化为列表的开头。 这是我的节点结构: 我的时循环出了什么问题?为什么它总是覆盖以前的节点?请并谢谢你!

  • insertUrl(int $row, int $column, string $url[, string $text, string $toolTip, resource $formatHandler]) int $row $excel = new \Vtiful\Kernel\Excel($config); ​ $urlFile = $excel->fileName("free.xlsx")