C ++链接列表读取访问冲突

时间:2018-01-08 15:06:11

标签: c++

我是C ++的新手,我正在研究链接列表,我遇到了这个问题,但仍然无法找到解决方案。

这是基本节点的样子。

False

我正在尝试用这个函数交换第一个节点和最后一个节点的位置。

struct node {
    int data;
    node *next;
};

我得到的错误是:抛出异常:读取访问冲突,这个 - >尾部是nullptr。

有谁能解释我做错了什么?

3 个答案:

答案 0 :(得分:0)

  • 你没有删除头部和尾。
  • 假设tail是最后一个,有一个node::next指向它,而您没有将其更改为指向temp
  • 如果列表为空怎么办?您没有检查headtail是否为空。

编辑添加了固定方法

void swap_first_and_last() 
{
    //if there is less than 2 nodes - finished.
    if(!head || !tail || head==tail) return; 
    node *temp = new node;
    node *temp2 = new node;
    node *temp3;

    temp->data = head->data;
    temp->next = NULL;

    temp2->next = head->next;
    temp2->data = tail->data;

    temp3 = head;
    head = temp2;
    delete temp3; //delete old head
    temp3 = tail;
    //find the tail previous
    for(tail=head; tail->next!=temp3;tail=tail->next);
    //make tail previous point to tail
    tail->next = temp;
    tail = temp;//now it will point to new tail...
    delete temp3;//delete old tail
}

更好的解决方案:

void swap_first_and_last() 
{
    node *temp;
    //if there is less than 2 nodes - finished.
    if(!head || !tail || head==tail) return; 
    for(temp=head; temp->next!=tail;temp=temp->next);
    temp->next = head; //set tail precedor's next to point to head, prepere for head = tail
    tail->next = head->next; //set tail's next to point head->next, prepere for head = tail 
    head = tail; //set tail as head
    tail = temp->next; //set old head as tail
    tail->next = NULL; // tail next is always null (was point to the 2nd).
}

答案 1 :(得分:0)

//              V----- where does tail get initialized?
temp2->data = tail->data;

调用swap_first_and_last时,tail尚未初始化,就像运行时所说的那样:你的时间会很糟糕。

你可以 -

  • 确保在调用前使用值初始化tail swap_first_and_last
  • 检查tail之前是否已初始化 试图对它进行任何读取访问。

我认为后者是更好的选择。

if (head) {
    temp->data = head->data;
}

if (tail) {
    temp2->data = tail->data;
}

你应该问自己一个问题 - 为什么我不把这个初始化放在node 的构造函数中?

答案 2 :(得分:0)

你是C ++的新手,所以我理解这并不是特别容易理解,但是一旦掌握了它,你就会理解上面的评论。

头部和尾部是指针node *head;,因此您不需要创建它们指向的对象的副本。

head指向具有内容(data = 42; next = tail)的内存块,tail指向保存的内存块(7和null)。您可以将头部复制到temp并拖至temp2,然后将其复制回tailhead,但为什么?除了内存泄漏之外,通过创建内存块的副本可以获得什么?你不关心内存块,你不想移动它们,你不想改变它们你想要做的就是改变哪个指针指向哪个内存块。

node* pTemp = head;
head = tail;
tail = head;

不幸的是,这会破坏您的列表,因为现在head->next = null所以您只需要修复它:

pTemp = head->next;  // Which should always be null.
head->next = tail->next;
tail->next = pTemp;

现在,如果你把它放在一个以两个指针作为参数的小函数中,那么你就有了一个可以切换列表中任意两个给定节点的代码块,这意味着对列表进行排序变得容易多了。