基本链表使用Constructor v/s静态方法

Using Constructor v/s static method for basic linked list

我在第一次尝试中尝试实现一个基本的链表我实现了一个静态方法(插入)来插入数据和指向下一个元素的指针,如下所示:

#include <iostream>


using namespace std;

class Node{
    public:
        int data = NULL;
        Node* next = nullptr;
        Node(){}
        
        static void insert(int data, Node* next,Node* obj){
            obj->data = data;
            obj->next = next;
        }
        static void printList(Node* n){
            while(n != nullptr){
                cout << n->data << " ";
                n = n->next;
            }
        }
};




int main()
{
    Node* head = nullptr;
    Node* second = nullptr;
    Node* third = nullptr;
    head = new Node();
    second = new Node();
    third = new Node();
    
    

    //via static method
    Node::insert(1,second,head);
    Node::insert(2,third,second);
    Node::insert(3,nullptr,third);
    
    Node::printList(head);
    
    delete head;
    delete second;
    delete third;
    return 0;
}

如我所料,它工作正常(输出为 1 2 3),但是当我使用 构造函数如下所示:

#include <iostream>


using namespace std;

class Node{
    public:
        int data = NULL;
        Node* next = nullptr;
        Node(){}
        Node(int data, Node* next){
             this->data = data;
             this->next = next;
        }
        
        static void printList(Node* n){
            while(n != nullptr){
                cout << n->data << " ";
                n = n->next;
            }
        }
};




int main()
{
    Node* head = nullptr;
    Node* second = nullptr;
    Node* third = nullptr;
    

    //via constructors.
    head = new Node(1,second);
    second = new Node(2,third);
    third = new Node(3,nullptr);
    
    Node::printList(head);
    
    delete head;
    delete second;
    delete third;
    return 0;
}

我得到的输出为 1 0。当我从第三个到头调用构造函数时,它工作正常(我的意思是)

third = new Node(3,nullptr);
second = new Node(2,third);
head = new Node(1,second);

请解释为什么会这样。 注:我是编程初学者

让我们内联 insert:

Node::insert(x, a, b) 等同于

b->data = x;
b->next = a;

因此,

Node::insert(1,second,head);
Node::insert(2,third,second);
Node::insert(3,nullptr,third);

等同于

head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = nullptr;

现在 head->next 指向与 second 相同的节点,second->nextthird 指向相同的节点 - 你也可以写

head->next = second;
head->data = 1;
head->next->next = third;
head->next->data = 2;
head->next->next->next = nullptr;
head->next->next->data = 3;

在失败的情况下,second 不会一直指向您链接到 first 的节点;它指向一个新节点。
由于您为 secondthird 分配了新值,因此它等同于

head = new Node(1,second);
Node* fourth = new Node(2,third);
Node* fifth = new Node(3,nullptr);

现在您很快就会明白为什么它不起作用。

您也可以绘制“框和指针”图。
(初学者很不愿意做,别这样,比调试快多了。)

让我们看看失败的原因:

head = new Node(1, second);

 head     second
  |          |
  v          v
+---+      +---+
| -------->| X |
+---+      +---+

然后

second = new Node(2,third);

 head                 second     third
  |                     |          |
  v                     v          v
+---+      +---+      +---+      +---+
| -------->| X |      | -------->| X |
+---+      +---+      +---+      +---+

现在 head->next 指向的节点不同于 second 指向的节点 - 它仍然指向您首先创建的 default-initialized Node

虽然部分工作看起来像:

second = new Node(2, third);

second    third
  |          |
  v          v
+---+      +---+
| -------->| X |
+---+      +---+
first = new Node(1,second);

 head      second     third
  |          |          |
  v          v          v
+---+      +---+      +---+
| -------->| -------->| X |
+---+      +---+      +---+     

现在,如果您不以“尽可能小的步骤”方式执行此操作,则可以编写您的工作构造函数代码

Node* third = new Node(3,nullptr);
Node* second = new Node(2,third);
Node* head = new Node(1,second);

但是坏掉的你这样写是编译不通过的,不编译也能发现有依赖问题:

Node* head = new Node(1,second); // second is undeclared
Node* second = new Node(2,third);  // third is undeclared
Node* third = new Node(3,nullptr);

这是适应迈出更大步伐的另一个原因。