C++ 为什么它只打印双链表的第一个值,而我的程序却崩溃了

C++ 为什么它只打印双链表的第一个值,而我的程序却崩溃了,c++,doubly-linked-list,C++,Doubly Linked List,我试图创建一个双链接列表,然后打印它的值,但是输出只显示第一个值,然后整个程序就崩溃了 我不明白代码中的问题在哪里 输入 三, 1 2 3 预期产量 1 2 3 电流输出 一, 在上面标记为1和2的行之间,究竟是什么将变量temp设置为指向实际节点,而不是指向某个任意内存地址 没什么,我听见你说了?嗯,这将是一个问题:- 更详细地说,行: node *temp; 将temp设置为指向某个随机位置,除非您的列表当前为空,否则在您尝试执行之前,不会有任何更改: temp->next = ne

我试图创建一个双链接列表,然后打印它的值,但是输出只显示第一个值,然后整个程序就崩溃了

我不明白代码中的问题在哪里

输入

三,

1 2 3

预期产量

1 2 3

电流输出

一,

在上面标记为1和2的行之间,究竟是什么将变量temp设置为指向实际节点,而不是指向某个任意内存地址

没什么,我听见你说了?嗯,这将是一个问题:-

更详细地说,行:

node *temp;
将temp设置为指向某个随机位置,除非您的列表当前为空,否则在您尝试执行之前,不会有任何更改:

temp->next = newnode;
换句话说,如果幸运的话,它很可能会使用无效的指针值并崩溃。如果你运气不好,它不会崩溃,而是会在之后的某个时候表现出一些奇怪的行为

如果您不担心列表中的顺序,可以通过始终在标题处插入以下内容来解决此问题:

node *makenode(node *head, int val) {
    node *newnode = new node;
    newnode->data = val;
    if (head == 0) { // probably should use nullptr rather than 0.
        newnode->next = 0;
        newnode->prev = 0;
    } else {
        newnode->next = head->next;
        newnode->prev = 0;
    }
    head = newnode;
    return head;
}
如果您关心订单,则必须根据该值找出新节点的位置,例如:

node *makenode(node *head, int val) {
    node *newnode = new node;
    newnode->data = val;

    // Special case for empty list, just make new list.

    if (head == 0) { // probably should use nullptr rather than 0.
        newnode->next = 0;
        newnode->prev = 0;
        head = newnode;
        return head;
    }

    // Special case for insertion before head.

    if (head->data > val) {
        newnode->next = head->next;
        newnode->prev = 0;
        head = newnode;
        return head;
    }

    // Otherwise find node you can insert after, and act on it.

    // Checknode will end up as first node where next is greater than
    // or equal to insertion value, or the last node if it's greater
    // than all current items.

    node *checknode = head;
    while (checknode->next != 0 && (checknode->next->data < val) {
        checknode = checknode->next;
    }

    // Then it's just a matter of adjusting three or four pointers
    // to insert (three if inserting after current last element).

    newnode->next = checknode->next;
    newnode->prev = checknode;
    if (checknode->next != 0) {
        checknode->next->prev = newnode;
    }
    checknode->next = newnode;

    return head;
}
在上面标记为1和2的行之间,究竟是什么将变量temp设置为指向实际节点,而不是指向某个任意内存地址

没什么,我听见你说了?嗯,这将是一个问题:-

更详细地说,行:

node *temp;
将temp设置为指向某个随机位置,除非您的列表当前为空,否则在您尝试执行之前,不会有任何更改:

temp->next = newnode;
换句话说,如果幸运的话,它很可能会使用无效的指针值并崩溃。如果你运气不好,它不会崩溃,而是会在之后的某个时候表现出一些奇怪的行为

如果您不担心列表中的顺序,可以通过始终在标题处插入以下内容来解决此问题:

node *makenode(node *head, int val) {
    node *newnode = new node;
    newnode->data = val;
    if (head == 0) { // probably should use nullptr rather than 0.
        newnode->next = 0;
        newnode->prev = 0;
    } else {
        newnode->next = head->next;
        newnode->prev = 0;
    }
    head = newnode;
    return head;
}
如果您关心订单,则必须根据该值找出新节点的位置,例如:

node *makenode(node *head, int val) {
    node *newnode = new node;
    newnode->data = val;

    // Special case for empty list, just make new list.

    if (head == 0) { // probably should use nullptr rather than 0.
        newnode->next = 0;
        newnode->prev = 0;
        head = newnode;
        return head;
    }

    // Special case for insertion before head.

    if (head->data > val) {
        newnode->next = head->next;
        newnode->prev = 0;
        head = newnode;
        return head;
    }

    // Otherwise find node you can insert after, and act on it.

    // Checknode will end up as first node where next is greater than
    // or equal to insertion value, or the last node if it's greater
    // than all current items.

    node *checknode = head;
    while (checknode->next != 0 && (checknode->next->data < val) {
        checknode = checknode->next;
    }

    // Then it's just a matter of adjusting three or four pointers
    // to insert (three if inserting after current last element).

    newnode->next = checknode->next;
    newnode->prev = checknode;
    if (checknode->next != 0) {
        checknode->next->prev = newnode;
    }
    checknode->next = newnode;

    return head;
}

实际上,您并没有将任何内容链接在一起。此行:ifhead==0 temp=head=newnode;这是链接列表包含值的唯一原因。第一个值将head设置为它的值,当您打印head时,您将获得该值。为了正确地创建链表,您需要一个头和尾指针。头部指向列表中的第一个元素,尾部指向最后一个元素。将元素添加到列表末尾时,使用tail查找最后一个元素并链接到该元素。使链表成为一个可以封装头和尾的类是最容易的:

struct Node {
public:
    int data;
    node *next;
    node *prev;
    Node(int data) : data(data), next(nullptr), prev(nullptr) {} // constructor
};

class LinkedList {
private:
    Node* head;
    Node* tail;

public:
    LinkedList() { head = tail = nullptr; }

    // This function adds a node to the end of the linked list
    void add(int data) {
        Node* newNode = new Node(data);
        if (head == nullptr) { // the list is empty
            head = newNode;
            tail = newNode;
        }
        else { // the list is not empty
            tail->next = newNode; // point the last element to the new node
            newNode->prev = tail;  // point the new element to the prev
            tail = tail->next;  // point the tail to the new node
        }
    }
};

int main() {

  LinkedList lList;
  lList.add(1);
  lList.add(2);
  // etc...

  return 0;
}

实际上,您并没有将任何内容链接在一起。此行:ifhead==0 temp=head=newnode;这是链接列表包含值的唯一原因。第一个值将head设置为它的值,当您打印head时,您将获得该值。为了正确地创建链表,您需要一个头和尾指针。头部指向列表中的第一个元素,尾部指向最后一个元素。将元素添加到列表末尾时,使用tail查找最后一个元素并链接到该元素。使链表成为一个可以封装头和尾的类是最容易的:

struct Node {
public:
    int data;
    node *next;
    node *prev;
    Node(int data) : data(data), next(nullptr), prev(nullptr) {} // constructor
};

class LinkedList {
private:
    Node* head;
    Node* tail;

public:
    LinkedList() { head = tail = nullptr; }

    // This function adds a node to the end of the linked list
    void add(int data) {
        Node* newNode = new Node(data);
        if (head == nullptr) { // the list is empty
            head = newNode;
            tail = newNode;
        }
        else { // the list is not empty
            tail->next = newNode; // point the last element to the new node
            newNode->prev = tail;  // point the new element to the prev
            tail = tail->next;  // point the tail to the new node
        }
    }
};

int main() {

  LinkedList lList;
  lList.add(1);
  lList.add(2);
  // etc...

  return 0;
}

我不明白你想说什么@paxdiablo@BATMAN_X您的else case通过写入temp->来解除temp的引用,但temp只是声明的,从未使用地址初始化过,因此它有一个未定义的值,因此您的程序有未定义的行为,在本例中会崩溃。您需要先将某个节点的有效内存地址分配给temp,然后才能取消引用。@BATMAN_X,我已经调整了该部分,希望能让它更清晰。我不明白您想说什么@paxdiablo@BATMAN_X您的else案例通过写入temp->来解除temp的引用,但temp只是声明的,从未使用地址初始化,所以它有一个未定义的值,所以你的程序有未定义的行为,在这种情况下会崩溃。您需要将某个节点的一些有效内存地址分配给temp,然后才能取消引用它。@BATMAN_X,我已经调整了该部分,希望能让它更清晰。