我试图创建一个双链表,然后打印它的值,但输出只显示第一个值,然后整个程序崩溃。
我无法理解代码中的问题出在哪里。
输入
3
1 2 3
预期产出
1 2 3
电流输出
1
#include<iostream>
#include<stdlib.h>
using namespace std;
class node //declation of node
{
public:
int data;
node *next;
node *prev;
};
node *makenode(node *head,int val) //function to create node
{
node *newnode=new node;
node *temp;
newnode->data=val;
newnode->next=0;
newnode->prev=0;
if(head==0) temp=head=newnode;
else
{
temp->next=newnode;
newnode->prev=temp;
temp=newnode;
}
return head;
}
void display(node *head) //display function
{
system("cls"); //clearing output screen
while(head!=0)
{
cout<<head->data<<" ";
head=head->next;
}
}
int main()
{
node *head;
head=0;
int val;
int s; //size of list
cout<<"ENTER THE SIZE OF LIST";
cin>>s;
system("cls");
for(int i=0;i<s;i++)
{
cout<<"ENTER THE "<<i+1<<" VALUE\n";
cin>>val;
head=makenode(head,val); //calling makenode and putting value
}
display(head); //printing value
return 0;
}
node *makenode(node *head,int val) //function to create node
{
node *newnode=new node;
node *temp; // #1
newnode->data=val;
newnode->next=0;
newnode->prev=0;
if(head==0) temp=head=newnode;
else
{
temp->next=newnode; // #2
在上面标记为#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;
}
如果您关心顺序,则必须根据值找出新节点应该去的地方,例如WITH:
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;
}
你实际上没有把任何东西联系在一起。 这一行:if(head==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
tail = tail->next; // point the tail to the new node
}
}
};
int main() {
LinkedList lList;
lList.add(1);
lList.add(2);
// etc...
return 0;
}