insert()中的分段错误,C ++上的双链表

时间:2019-05-03 20:16:42

标签: c++11 pointers segmentation-fault nodes doubly-linked-list

我正在尝试在c ++中实现双向链接列表,但是在尝试实现insert()函数时出现错误。这是Node的结构:

struct NodoLDL
{
   T dato;
   NodoLDL *anterior;
   NodoLDL *siguiente;

   NodoLDL(const T &elem, NodoLDL *ant = nullptr, NodoLDL *sig = nullptr):
      dato(elem),
      anterior(ant),
      siguiente(sig)
   {}
};

这是列表类:

 template <typename T>
class LDL
{
private:
   #include "nodoldl.h"
   size_t listSize;
   NodoLDL *listFront; //head
   NodoLDL *listBack; //tail

public:
   LDL() : listSize(0), listFront(nullptr), listBack(nullptr)
   {}
   void insert(size_t position, const T &elem);
(. . .)
}

这是我正在使用的insert()函数,但是在“ temp2->anterior = temp3”上出现分段错误

template<typename T>
void LDL<T>::insert(size_t position, const T &elem)
{    
    if(empty()){

        listFront = new NodoLDL(elem); 
        listBack = listFront;
        listSize+=1;

    }else if(listSize>0 && position==0){ //push_front()

        //The implementation for push_front() works fine.

    }else if(position==listSize){ //push_back()

        //The implementation for push_back() also works fine.           

    }else if(position > 0 && position<listSize){

        NodoLDL *temp1, *temp2, *temp3;
        temp1 = listFront;

        for(size_t i=0; i<position; i++){
            temp1 = temp1->siguiente;
        }

        temp2 = temp1->siguiente;
        temp3 = new NodoLDL (elem);
        temp1 -> siguiente = temp3;
        temp3 -> anterior = temp1;
        temp3 -> siguiente = temp2;
        temp2 -> anterior = temp3;

        listSize+=1;

    }else if(position > listSize){
        throw invalid_argument("insert() on invalid position");
    }
}

在开头和结尾插入都可以,但是如果插入列表的中间没有,我该如何解决?为什么这种逻辑是错误的? 我不确定这仅仅是行还是else if(position>0 && position<listSize)中的所有逻辑都不正确。

1 个答案:

答案 0 :(得分:0)

好的,因此首先,您必须检查列表中是否只有一个元素。在这种情况下,您不能执行以下操作:

    temp2 = temp1->siguiente;
    temp3 = new NodoLDL (elem);
    temp1 -> siguiente = temp3;
    temp3 -> anterior = temp1;
    temp3 -> siguiente = temp2;
    temp2 -> anterior = temp3;

如果您这样做,temp1->siguiente将为空指针,因此temp2也将为空指针。调用temp2->anterior时会发生分段错误。因为您将访问没有任何内容的字段。

我鼓励您尝试始终将这种过程分为不同的功能。一个用于推后,一个用于推前,如果第一个if则调用。

template<typename T>
void LDL<T>::insert(size_t position, const T &elem) {   

    if (position > listSize) { //I tend to always check this things first
        throw invalid_argument("insert() on invalid position");
    }

    if (empty() || position == 0) {
        push_front(elem);
        return;
    }

    if (position == listSize){ //push_back()           
        push_back(elem)
        return;
    }

    NodoLDL *temp1, *temp2, *temp3;
    temp1 = listFront;

    for(size_t i=0; i<position; i++){
        temp1 = temp1->siguiente;
    }

    temp2 = temp1->siguiente;
    temp3 = new NodoLDL (elem);
    temp1 -> siguiente = temp3;
    temp3 -> anterior = temp1;
    temp3 -> siguiente = temp2;
    temp2 -> anterior = temp3;

    listSize++;
}

理论上,您的插入内容在任何情况下都可以使用,但是我知道您是否只是在开始学习并以这种方式更好地查看解决方案。 Linus Torvalds有一个很好的TedTalk,他在其中谈论编写漂亮的代码,我认为他为该类选择的示例是列表插入。