Ошибка сегментации в insert (), двусвязном списке на c ++ - PullRequest
0 голосов
/ 03 мая 2019

Я пытаюсь реализовать двусвязный список в c ++, но я получаю ошибку, когда пытаюсь реализовать функцию insert(). Это структура узла:

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 голосов
/ 04 мая 2019

Хорошо, так что в первую очередь вы должны проверить, есть ли у вас только один элемент в списке.В этом случае вы не можете сделать:

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

Если вы сделаете такую ​​вещь, temp1->siguiente будет нулевым указателем, и как таковой, temp2 также будет нулевым указателем.Ваша ошибка сегментации произойдет, когда вы позвоните temp2->anterior.Поскольку вы будете выходить на поле, где нет ничего.

Я призываю вас всегда пытаться разделить этот вид процедуры на разные функции.Один для push-back и один для push-front для вызова либо в первом 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++;
}

Теоретически ваша вставка должна работать в любом случае, но я понимаю, что вы только начинаете учиться иувидеть решение лучше таким образом.У Линуса Торвальдса есть хороший TedTalk, где он говорит о написании прекрасного кода, и я думаю, что пример, который он выберет для этого класса, - вставка списка.

...