Dificuldade em fazer uma lista dupla encadeada [RESOLVIDO]

1. Dificuldade em fazer uma lista dupla encadeada [RESOLVIDO]

Lendel dos Santos Rodrigues
lendel

(usa Linux Mint)

Enviado em 22/08/2021 - 11:10h


#include <cstdlib>
#include <iostream>
#include <iomanip>
#include "Funcoes22049.h"

using namespace std;

int main (int argc, char *argv[])
{
ListaDupla list1;
list1.insere(1,0), list1.insere(2,1), list1.insere(5,2), list1.insere(7,3);
cout << "tamanho: " << list1.tamanho() << endl;
int y = 0;
cout << "Quantidade: " << list1.quantidade(y) << endl;
cout << "Lista" << endl;
list1.imprimeLista();
list1.retira(2);
cout << "tamanho: " << list1.tamanho() << endl;
int x = 0;
list1.obtem(x,1);
cout << "Valor: " << 5 << " posição: 3" << endl;
cout << "Lista" << endl;
list1.imprimeLista();
if(list1.tamanho() == 0)
cout << "lista está vazia" << endl;
else{
cout << "tamanho: " << list1.tamanho() << endl;
};
cout << "Quantidade: " << list1.quantidade(y) << endl;
}

#include "Funcoes22049.h"
#include <iomanip>
#include <iostream>

using namespace std;

ListaDupla::ListaDupla()
{
primeiro = NULL;
ultimo = NULL;
}

void ListaDupla::limpa()
{
Elemento *z = primeiro; // z aponta para o início.
// Percorrer toda a lista para desalocar os elementos.
Elemento *y = NULL;
while(z != 0){
y = z->prox;
delete z;
z = y;
}
primeiro = 0; // Indica que a lista está vazia.
}

bool ListaDupla::vazia()
{
return primeiro == 0;
}

ListaDupla::~ListaDupla()
{
limpa();
}

bool ListaDupla::insere(Valor x, int pos)
{
if(pos < 0) return false; // pos inválida.
else{
Elemento *y, *z, *w;
// y é o ponteiro anterior e z o atual.
y = 0; // y não aponta para ninguém.
z = primeiro; // z aponta para o primeiro elemento.
int p = 0; // Indice do primeiro elemento.
while(p < pos && z != 0){ // A posição é válida.
p++; // Próximo indice.
y = z; // O anterior é o atual.
z = z->prox; // O atual é o proximo da lista.
}
if(z == 0 && p == pos || z != 0){ // pos. inválida.
w = new Elemento; // Tenta criar um novo elem.
if(w != 0){ // Elemento criado.
w->val = x;
if(pos == 0) { // Ins. prim. pos.
w->ant = NULL;
w->prox = primeiro;
primeiro->ant = w;
primeiro = w;
}else{ // Inserção demais posições.
w->prox = y->prox; // anterior aponta para o proximo
y->prox = w;
w->ant = y;
if(z != NULL)
z->ant = w;
}
while(z->prox != NULL) // procuramos o ultimo elemento
z = z->prox;
ultimo = z;
quant++;
return true;
}
else return false; // Elemento não criado.
}
else return false; // Inserção em posição inválida.
}
}

bool ListaDupla::retira(int pos)
{
// Verifica se é uma posição válida para remover.
if(pos < 0 || pos >= tamanho())
return false; // Não é válida, não removeu.
else{ // É válida.
Elemento *y = primeiro; // y aponta p/ o primeiro.
if(pos == 0) { // Remoção na primeira posição.
// Removeremos o primeiro elemento da lista.
primeiro = y->prox; // O segundo será o primeiro.
primeiro->ant = NULL; // anterior do primeiro aponta para nulo
delete y; // Remove o primeiro elemento da memoria.
quant--;
}
else{ // A posição para remoção não é a primeira.
// Percorre a lista até a posição da remoção.
for(int i = 1; i < pos; i++){
y = y->prox;}
Elemento *z = y->prox; // z aponta p/ o próximo.
if(z->prox == NULL){ // z aponta para o ultimo
y->prox = NULL; // y passa apontar para ultimo
}
else { // y aponta para o proximo
y->prox=z->prox;
y->prox->ant = z->ant;
}
while(y->prox != NULL) // procuramos o ultimo elemento
y = y->prox;
ultimo = y;
delete z; // Remove o elemento da memória.
quant--;
}
return true; // Indica que removeu o valor.
}
}

int ListaDupla::tamanho()
{
if(primeiro == 0) return 0; // Está vazia.
else{ // Não está vazia.
int c = 1; // Inicializa o contador c em 1.
Elemento *z = primeiro; // z aponta para o primeiro.
// Percorre a lista até o último elemento.
while(z->prox != 0){
c++;
z = z->prox;
}
return c; // Retorna o tamanho contado por c.
}
}

bool ListaDupla::obtem(Valor &x, int pos)
{
if(pos < 0 || pos >= tamanho())
return false; // Não é válida, não obteve.
else{ // E válida.
Elemento *z = primeiro; // z aponta para o primeiro.
// Percorre a lista até a posição pos do elem. x.
for(int i = 0; i < pos; i++) z = z->prox;
x = z->val; // Volta em x o valor (referência).
return true; // Indica que obteve o valor.
}
}

void ListaDupla::imprimeLista(){
Elemento *z = primeiro;

cout << "L -> ";
while(z != NULL){
cout << z->val << " -> ";
z = z->prox;
}
cout << "NULL" << endl;

Elemento *w = ultimo;

cout << "L -> ";
while(w != NULL){
cout << w->val << " -> ";
w = w->ant;
}
cout << "NULL" << endl;
}

int ListaDupla::quantidade(Valor &q)
{
return quant;
}

#ifndef LISTADUPLA_H
#define LISTADUPLA_H

//#include "Funcoes22047.h"

class ListaDupla //: public Lista
{
private:
typedef int Valor;
struct Elemento
{
Valor val; // Material da seção.
Elemento *prox; // Aponta para proximo.
Elemento *ant; // Aponta para anterior.
};
int quant = 0;
Elemento *primeiro; // Aponte para o primeiro.
Elemento *ultimo; // Aponte para o ultimo.
public:
// Construtor padrão:
ListaDupla();
// Destruidor da lista:
~ListaDupla();
// Insere o valor x na posição pos da lista:
bool insere(Valor x, int pos);
// Retire o elemento da posição pos da lista:
bool retira(int pos);
// Retorna o tamanho da lista:
int tamanho();
// Indica se a lista está vazia:
bool vazia();
// Remove todos os elementos da lista:
void limpa();
// Obtém o valor x da posição pos da lista:
bool obtem(Valor &x, int pos);
// Imprimir os dados da lista em suas posições
void imprimeLista();
// Obtém a quantidade inserida na lista
int quantidade(Valor &q);
};
#endif

resultado ao copilar
Falha de segmentação (imagem do núcleo gravada)

O problema maior se encontra na função inserir e na função retirar



  


2. Re: Dificuldade em fazer uma lista dupla encadeada

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/08/2021 - 12:43h

Bom dia, prezado.

Algumas dicas:

1) Não sei como está no seu editor de texto, mas a versão do código que você colou aqui está com níveis de recuo (indentation) irregulares, dificultando um bocado a compreensão. Se puder ajustar, ajuda.

2) Procure uniformizar a forma de representar ponteiros nulos. Em alguns lugares você usou NULL (uma convenção do C), em outros usou 0, mas o C++ preconiza a palavra reservada nullptr desde o padrão de 2011, com o intuito de se livrar das ambiguidades que os dois outros têm (veja esta postagem da comunidade: https://www.vivaolinux.com.br/topico/C-C++/C-qual-usar-NULL-ou-0-ou-nullptr).

3) Listas encadeadas normalmente não utilizam índices para operações de inserção ou remoção de elementos. As operações mais comuns são inserção/remoção no início, inserção/remoção no fim, inserção/remoção baseada no valor usado como chave (principalmente no caso de listas ordenadas) e inserção/remoção usando como referência algum ponteiro ou iterador para outro elemento já pertencente à lista um um cursor que mantém uma informação semelhante a “última posição usada” (especialmente se você tiver operações que permitam avançar ou retroceder o cursor). Ao fazer usando índice, temo que você acabe ficando com uma implementação pouco eficiente de vetor, em vez de lista.

4) Para representar quantidades de elementos, use valores inteiros sem sinal. Uma boa prática é usar std::size_t. Essa simples medida ajuda a evitar que você tenha de testar nas suas funções se o usuário tentou usar um índice negativo.

5) As funções-membro tamanho() e quantidade() me parecem meio redundantes, especialmente se você estiver mantendo adequadamente o membro de dados quant (não olhei ainda o código muito a fundo para verificar isso). E não entendi a razão para o parâmetro da função quantidade(), que não é usado para nada.

6) A menos que você tenha opções de compilação que desabilitem exceções por padrão, o comportamento normal de new é disparar uma exceção em caso de erros. Cuidado com isso.

7) Não sei se estou deixando de ver alguma coisa, mas a função limpa() parece não alterar o valor do membro de dados ultimo.

8) Na função de inserção, a linha “if(z == 0 && p == pos || z != 0){ // pos. inválida.” está estranha. Acho que o comentário não reflete exatamente o que está sendo testado, reflete? Apesar de haver uma diferença entre a precedência dos operadores && (mais alta) e || (mais baixa) alguns compiladores recomendam o uso de parênteses para deixar o código mais evidente para quem lê o programa (e possivelmente também porque em algumas outras linguagens, tal como o shell padrão do UNIX, esses operadores têm a mesma precedência). Pode ser interessante reescrever o teste como “if( (z==nullptr && p==pos) || z!=nullptr )” (note os parênteses e a substituição de 0 por nullptr nas comparações com ponteiros). Aliás, a expressão pode ser ainda mais simplificada, se você mudar a ordem, ela pode ficar simplesmente “if(z!=nullptr || p==pos)” (porque já fica implícito que se o teste usando p for necessário, então o teste usando z já determinou que o ponteiro é nulo).

9) Parece-me que, na função de inserção, você está sendo induzido a erro pelos recuos irregulares. Fiquei com a nítida impressão de que o laço de repetição que busca pelo último elemento tenta usar z->prox sem se certificar de que z é válido (não-nulo).


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


3. Problema está na função inserir

Lendel dos Santos Rodrigues
lendel

(usa Linux Mint)

Enviado em 23/08/2021 - 21:55h

Bom dia, caro colega.

Esse código é uma modificação de um exemplo do livro "Aplicações Cientificas em C++ da programação estruturada à programação orientada a objetos", a questão 22.49 na página 389 do mesmo... A questão pede para: "Implemente uma classe ListaDupla , considerando as modificações propostas pela figura 22-6. Observe que a cabeça da lista já possui um campo de nome quant que é utilizado para guardar a quantidade de elementos presentes na lista; se quant for 0, então a lista não possui elementos. A cabeça também deverá possuir os campos primeiro e ultimo que apontam, respectivamente, para o primeiro e para o ultimo elemento da lista. Estes campos facilitarão a implementação de alguns métodos que manipulam a lista. Implemente, no mínimo, as operações insere e retire e teste a classe instanciando objetos e chamando os métodos, junto à função main.

Vou colocar aqui a função original :


Aqui está o cabeçalho com as especificação
#ifndef LISTA_H
#define LISTA_H

class Lista
{
private:
typedef int Valor;
struct Elemento
{
Valor val; // Material da seção.
Elemento *prox; // Aponta para o próximo.
};
Elemento *primeiro; // Aponte para o primeiro.
// Copia profundamente os elementos de uma lista e é
// usado no construtor de cópia e na atribuição:
void copiaProfunda(Lista &lista);
public:
// Construtor padrão:
Lista();
// Destruidor da lista:
virtual ~Lista();
// Construtor de cópia da lista:
Lista(Lista &lista);
// Operação de Atribuição da lista:
Lista & operator = (Lista &lista);
// Insere o valor x na posição pos da lista:
virtual bool insere(Valor x, int pos);
// Retire o elemento da posição pos da lista:
virtual bool retira(int pos);
// Retorna o tamanho da lista:
virtual int tamanho();
// Indica se a lista está vazia:
virtual bool vazia();
// Remove todos os elementos da lista:
virtual void limpa();
// Obtém o valor x da posição pos da lista:
virtual bool obtem(Valor &x, int pos);
};
#endif


Agora as funções do cabeçalho:
#include "Funcoes22047.h"
#include <iomanip>

Lista::Lista()
{
primeiro = 0;
}

void Lista::limpa()
{
Elemento *z = primeiro; // z aponta para o início.
// Percorrer toda a lista para desalocar os elementos.
Elemento *y;
while(z != 0){
y = z->prox;
delete z;
z = y;
}
primeiro = 0; // Indica que a lista está vazia.
}

bool Lista::vazia()
{
return primeiro == 0;
}

Lista::~Lista()
{
limpa();
}

int Lista::tamanho()
{
if(primeiro == 0) return 0; // Está vazia.
else{ // Não está vazia.
int c = 1; // Inicializa o contador c em 1.
Elemento *z = primeiro; // z aponta para o primeiro.
// Percorre a lista até o último elemento.
while(z->prox != 0){
c++;
z = z->prox;
}
return c; // Retorna o tamanho contado por c.
}
}

bool Lista::obtem(Valor &x, int pos)
{
if(pos < 0 || pos >= tamanho())
return false; // Não é válida, não obteve.
else{ // E válida.
Elemento *z = primeiro; // z aponta para o primeiro.
// Percorre a lista até a posição pos do elem. x.
for(int i = 0; i < pos; i++) z = z->prox;
x = z->val; // Volta em x o valor (referência).
return true; // Indica que obteve o valor.
}
}

bool Lista::insere(Valor x, int pos)
{
if(pos < 0) return false; // pos inválida.
else{
Elemento *y, *z, *w;
// y é o ponteiro anterior e z o atual.
y = 0; // y não aponta para ninguém.
z = primeiro; // z aponta para o primeiro elemento.
int p = 0; // Indice do primeiro elemento.
while(p < pos && z != 0){ // A posição é válida.
p++; // Próximo indice.
y = z; // O anterior é o atual.
z = z->prox; // O atual é o proximo da lista.
}
if(z == 0 && p == pos || z != 0){ // pos. inválida.
w = new Elemento; // Tenta criar um novo elem.
if(w != 0){ // Elemento criado.
w->val = x;
w->prox = z;
if(pos == 0) primeiro = w; // Ins. prim. pos.
else y->prox = w; // Inserção demais posições.
return true;
}
else return false; // Elemento não criado.
}
else return false; // Inserção em posição inválida.
}
}

bool Lista::retira(int pos)
{
// Verifica se é uma posição válida para remover.
if(pos < 0 || pos >= tamanho())
return false; // Não é válida, não removeu.
else{ // É válida.
Elemento *y = primeiro; // y aponta p/ o primeiro.
if(pos == 0) { // Remoção na primeira posição.
// Removeremos o primeiro elemento da lista.
primeiro = y->prox; // O segundo será o primeiro.
delete y; // Remove o primeiro elemento da memoria.
}
else{ // A posição para remoção não é a primeira.
// Percorre a lista até a posição da remoção.
for(int i = 1; i < pos; i++) y = y->prox;
Elemento *z = y->prox; // z aponta p/ o próximo.
y->prox = z->prox;
delete z; // Remove o elemento da memória.
}
return true; // Indica que removeu o valor.
}
}

void Lista::copiaProfunda(Lista &lista)
{
Elemento *z = lista.primeiro;
if(z == 0) primeiro = 0;
else{
primeiro = new Elemento;
Elemento *y = primeiro;
y->val = z->val;
z = z->prox;
while(z != 0){
y->prox = new Elemento;
y = y->prox;
y->val = z->val;
z = z->prox;
}
y->prox = 0;
}
}

Lista & Lista::operator = (Lista &lista)
{
if(this != &lista) copiaProfunda(lista);
return *this;
}


Bom amigo fiz algumas alterações na minha lista de funções porém não resolveu o problema. Poderia tentar compilar e olhar essa falha?

#include "Funcoes22049.h"
#include <iomanip>
#include <iostream>

using namespace std;

ListaDupla::ListaDupla()
{
primeiro = nullptr;
ultimo = nullptr;
}

void ListaDupla::limpa()
{
Elemento *z = primeiro; // z aponta para o início.
// Percorrer toda a lista para desalocar os elementos.
Elemento *y;
while(z != 0){
y = z->prox;
delete z;
z = y;
}
primeiro = nullptr; // Indica que a lista está vazia.
}

bool ListaDupla::vazia()
{
return primeiro == nullptr;
}

ListaDupla::~ListaDupla()
{
limpa();
}

bool ListaDupla::insere(Valor x, int pos)
{
if(pos < 0) return false; // pos inválida.
else{
Elemento *y, *z, *w;
// y é o ponteiro anterior e z o atual.
y = nullptr; // y não aponta para ninguém.
z = primeiro; // z aponta para o primeiro elemento.
int p = 0; // Indice do primeiro elemento.
while(p < pos && z != nullptr){ // A posição é válida.
p++; // Próximo indice.
y = z; // O anterior é o atual.
z = z->prox; // O atual é o proximo da lista.
}
if(z == 0 && p == pos || z != nullptr){ // pos. inválida.
w = new Elemento; // Tenta criar um novo elem.
if(w != 0){ // Elemento criado.
w->val = x;
w->prox = z;// se em caso for o ultimo aponta para NULL
if(pos == 0){ w->ant = nullptr; // Ins. prim. pos.
primeiro->ant = w;
//w->prox = primeiro;
primeiro = w;
}
else{ y->prox = w; // Inserção demais posições.
w->ant = y;
if(z != nullptr)
z->ant = w;
}
while(z->prox != nullptr) // procuramos o ultimo elemento
z = z->prox;
ultimo = z;
quant++;
return true;
}
else return false; // Elemento não criado.
}
else return false; // Inserção em posição inválida.
}
}

bool ListaDupla::retira(int pos)
{
// Verifica se é uma posição válida para remover.
if(pos < 0 || pos >= tamanho())
return false; // Não é válida, não removeu.
else{ // É válida.
Elemento *y = primeiro; // y aponta p/ o primeiro.
if(pos == 0) { // Remoção na primeira posição.
// Removeremos o primeiro elemento da lista.
primeiro = y->prox; // O segundo será o primeiro.
primeiro->ant = 0; // anterior do primeiro aponta para nulo
delete y; // Remove o primeiro elemento da memoria.
quant--;
}
else{ // A posição para remoção não é a primeira.
// Percorre a lista até a posição da remoção.
for(int i = 1; i < pos; i++){
y = y->prox;}
Elemento *z = y->prox; // z aponta p/ o próximo.
if(z->prox == 0){ // z aponta para o ultimo
y->prox = 0; // y passa apontar para ultimo
}
else { // y aponta para o proximo
y->prox=z->prox;
y->prox->ant = z->ant;
}
while(y->prox != 0) // procuramos o ultimo elemento
y = y->prox;
ultimo = y;
delete z; // Remove o elemento da memória.
quant--;
}
return true; // Indica que removeu o valor.
}
}

int ListaDupla::tamanho()
{
if(primeiro == 0) return 0; // Está vazia.
else{ // Não está vazia.
int c = 1; // Inicializa o contador c em 1.
Elemento *z = primeiro; // z aponta para o primeiro.
// Percorre a lista até o último elemento.
while(z->prox != 0){
c++;
z = z->prox;
}
return c; // Retorna o tamanho contado por c.
}
}

bool ListaDupla::obtem(Valor &x, int pos)
{
if(pos < 0 || pos >= tamanho())
return false; // Não é válida, não obteve.
else{ // E válida.
Elemento *z = primeiro; // z aponta para o primeiro.
// Percorre a lista até a posição pos do elem. x.
for(int i = 0; i < pos; i++) z = z->prox;
x = z->val; // Volta em x o valor (referência).
return true; // Indica que obteve o valor.
}
}

void ListaDupla::imprimeLista(){
Elemento *z = primeiro;

cout << "L -> ";
while(z != 0){
cout << z->val << " -> ";
z = z->prox;
}
cout << "NULL" << endl;

Elemento *w = ultimo;

cout << "L -> ";
while(w != 0){
cout << w->val << " -> ";
w = w->ant;
}
cout << "NULL" << endl;
}

int ListaDupla::quantidade(Valor &q)
{
return quant;
}



4. Re: Dificuldade em fazer uma lista dupla encadeada

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/08/2021 - 02:50h

Na postagem anterior, eu não compilei nada do código que você postou. Apenas examinei o que estava escrito.

Eu continuo não gostando muito da ideia de inserção com posição, como se fosse um vetor, em vez de lista. Mas, para fazer desse jeito, eis como eu faria (programa “completo”, sem usar o que você fez, com uma implementação reduzida da lista que só tem a função de inserção, a de limpeza, e uma função de impressão).

#include <iostream>
#include <limits>


using namespace std;


class list_t {
public:
using value_t=int;

private:
struct element_t {
value_t value;
element_t *prev, *next;

// O construtor pode popular os campos da estrutura.
element_t(const value_t &v, element_t *before, element_t *after): value(v), prev(before), next(after) { }
};

element_t *first, *last;
size_t quant;

public:
list_t(): first(), last(), quant() { }
~list_t(){ clear(); }

// Função de inserção genérica com especificador de posição. Qualquer posição maior que ou igual ao tamanho atual da lista
// provoca inserção no final da lista, sem provocar erro. Por isso mesmo, o parâmetro ‘pos’ tem um valor default arbitra-
// riamente grande, que provoca inserção no fim da lista caso a função seja invocada sem o segundo argumento. A função faz
// uso do membro de dados ‘quant’ para tentar reduzir a distância da varredura, a depender de se a lista está vazia ou de se
// a posição de inserção vem antes ou depois da metade da lista.
//
// A função retorna uma referência para a própria lista, o que é útil para encadear operações (ver exemplo de uso abaixo).
// Note também que a função não tenta pegar erro de alocação dentro da função. Como tais erros disparam a exceção padronizada
// std::bad_alloc, a função permite que essa exceção “vaze”, para que o chamador decida o que fazer, caso a receba.
list_t &insert(const value_t &v, size_t pos=std::numeric_limits<size_t>::max()){
// Ponteiros para ponteiros, a fim de guardar referências para quais ponteiros devem ser modificados.
element_t **p_before, **p_after;

if(quant==0){
// Inserção na lista vazia.
p_before=&first;
p_after=&last;
}
else if(pos<=quant/2){
// Até a metade da lista, varre do início para o fim até achar a posição de inserção.
p_after=&first;
while(pos--)
p_after=&(*p_after)->next;
p_before=&(*p_after)->prev;
}
else{
// Após a metade da lista, varre do fim para o início até achar a posição de inserção.
p_before=&last;
while(pos++<quant)
p_before=&(*p_before)->prev;
p_after=&(*p_before)->next;
}
// Note que eu uso o construtor dos elementos para definir valor e ponteiros para os nós vizinhos.
auto new_elem=new element_t(v, *p_before, *p_after);
*p_before=*p_after=new_elem;

++quant;

return *this;
}

// Faz a limpeza da lista. Retorna uma referência para a própria lista.
list_t &clear(){
while(first){
auto n=first->next;
delete first;
first=n;
}
last=nullptr;
quant=0;

return *this;
}

friend ostream &operator<<(ostream &os, const list_t &t);
};


ostream &operator<<(ostream &os, const list_t &t){
switch(t.quant){
case 0:
os << "A lista está vazia.\n";
break;
case 1:
os << "A lista possui apenas um elemento: " << t.first->value << ".\n";
break;
default:
os << "A lista possui " << t.quant << " elementos:\n";
for(auto p=t.first; p!=t.last; p=p->next)
os << " • ‘" << p->value << "’;\n";
os << " • ‘" << t.last->value << "’.\n";
}
return os;
}


int main(){
list_t l;

cout << l
.insert(0) // Insere na lista vazia.
.insert(3) // Insere no fim da lista (argumento default).
.insert(1, 1) // Insere no meio da lista (varre do início para o fim).
.insert(2, 2) // Insere no meio da lista (varre do fim para o início).
;

cout << l.clear();
}



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


5. Re: Dificuldade em fazer uma lista dupla encadeada [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/08/2021 - 02:55h

Por favor, não apague o tópico, mesmo que considere a dúvida respondida.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


6. Consegui achar o problema no código

Lendel dos Santos Rodrigues
lendel

(usa Linux Mint)

Enviado em 24/08/2021 - 21:52h


Na linha 107, acessa um atributo de z sem antes testar se z é NULL ou não (que nem o teste da linha 104)
ultimo = NULL;
while(z != NULL) // procuramos o ultimo elemento
{
ultimo = z;
z = z->prox;
}



a outra parte foi acrescentada um if(primeiro != nullptr) na linha 56

if(pos == 0){ w->ant = nullptr; // Ins. prim. pos.
if(primeiro != nullptr)
primeiro->ant = w;
w->prox = primeiro;
primeiro = w;}


então a função inserir completa funcionando ficou assim...

bool ListaDupla::insere(Valor x, int pos)
{
if(pos < 0) return false; // pos inválida.
else{
Elemento *y, *z, *w;
// y é o ponteiro anterior e z o atual.
y = nullptr; // y não aponta para ninguém.
z = primeiro; // z aponta para o primeiro elemento.
int p = 0; // Indice do primeiro elemento.
while(p < pos && z != nullptr){ // A posição é válida.
p++; // Próximo indice.
y = z; // O anterior é o atual.
z = z->prox; // O atual é o proximo da lista.
}
if(z == 0 && p == pos || z != nullptr){ // pos. inválida.
w = new Elemento; // Tenta criar um novo elem.
if(w != 0){ // Elemento criado.
w->val = x;
w->prox = z;// se em caso for o ultimo aponta para NULL
if(pos == 0){ w->ant = nullptr; // Ins. prim. pos.
if(primeiro != nullptr)
primeiro->ant = w;
w->prox = primeiro;
primeiro = w;}
else{ y->prox = w; // Inserção demais posições.
w->ant = y;
if(z != nullptr)
z->ant = w;
}
ultimo = nullptr;
while(z != nullptr){ // procuramos o ultimo elemento
ultimo = z;
z = z->prox;
}
quant++;
return true;
}
else return false; // Elemento não criado.
}
else return false; // Inserção em posição inválida.
}
}




  



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts