Реализация связанного списка на Java

#java #list #object #linked-list #model

Вопрос:

Я пытаюсь реализовать связанный список в java, консультируясь с учебником моей школы.

Чтобы просмотреть список, я использую метод getInfo() для каждого узла, который должен возвращать имя и фамилию каждого человека в списке (я создаю список людей).

Я не понимаю, почему мой учебник в методе getInfo() узла класса возвращает a new Invitato(info) , а не тот, который хранится в классе Nodo .

Если я попытаюсь вернуть того , кто хранится в классе Nodo , я получу исключение с нулевым указателем.

 public class Main{
    public static void main(String args[]){
        
        Invitato i1 = new Invitato("Michele","Bianchi");
        Invitato i2 = new Invitato("Paolo","Rossi");
        Invitato i3 = new Invitato("Mario","Verdi");
        Invitato i4 = new Invitato("Giacomo","Neri");

        Lista l = new Lista();

        l.inserisciInCoda(i1);
        l.inserisciInTesta(i2);
        l.inserisciInTesta(i3);
        l.inserisciInPosizione(i4,2);

        l.visitaLista();
    }
}


public class Lista{
    private Nodo head;
    private int elementi;

    public Lista(){
        elementi=0;
        head = null;
    }

    private Nodo creaNodo(Invitato invitato, Nodo link){
        Nodo nuovoNodo = new Nodo(invitato);
        nuovoNodo.setLink(link);
        return nuovoNodo;
    }

    public int getElementi(){
        return elementi;
    }

    private Nodo getLinkPosizione(int n){
        Nodo p = head; 
        int i = 1;

        if(n>elementi || n<1)
            return null;
        else{
            while(p.getLink() != null amp;amp; i<n){
                p = p.getLink();
                i  ;
            }
        }
        return p;
    }

    public void visitaLista(){
        Nodo p = head;
        if(p==null){
            System.out.println("Lista vuota");
        }
        else{
            while(p!=null){
                System.out.println(p.getInfo().toString());
                p = p.getLink();
            }
        }
    }

public void inserisciInTesta(Invitato invitato){
        Nodo p = creaNodo(invitato, head);      //creo un nuovo nodo e lo liko alla testa
        head = p;                             //il nuovo nodo diventa la head
        elementi  ;
    }

    public void inserisciInCoda(Invitato invitato){
        if(head==null){                             //se la lista è vuota
            inserisciInTesta(invitato);          //posso inserire il nuovo nodo in testa
        }

        else{
            Nodo p = getLinkPosizione(elementi);            //prendo l'ultimo nodo
            Nodo nuovoNodo = creaNodo(invitato, null);
            p.setLink(nuovoNodo);
            elementi  ;
        }
    }

    public void inserisciInPosizione(Invitato invitato, int posizione){
        if(posizione <=1){
            inserisciInTesta(invitato);
        }
        else{
            if(posizione > elementi){
                inserisciInCoda(invitato);
            }
            else{
                Nodo p = getLinkPosizione(posizione-1);
                Nodo nuovoNodo = creaNodo(invitato,p.getLink());
                p.setLink(nuovoNodo);
                elementi  ;
            }
        }
    }

    public void eliminaInTesta(){
        if(head == null)    //la lista è vuota?
            return;
        head = head.getLink(); //la nuova head è il nodo a cui linka, quindi ora head riferisce al secondo nodo
        elementi--;
    }

    public void eliminaInCoda(){
        if(head == null){               //lista vuota
            return;
        }
        Nodo p = getLinkPosizione(elementi-1);    //prendo il penultimo nodo
        p.setLink(null);                // e metto il suo link a null
        elementi--;
    }

    public void eliminaInPosizione(int n){
        if(n<=1){
            this.eliminaInTesta();
        }
        else{
            if(n>=elementi){
                this.eliminaInCoda();
            }
            else{
                Nodo pp = getLinkPosizione(n-1);         //nodo prima di quello da cancellare
                Nodo ps = getLinkPosizione(n);          //nodo da cancellare
                
               pp.setLink(ps.getLink());                //assegno al link precedente a quello da cancellare il link di quello che sto cancellando
               elementi--;
            }
        }
    }
}

public class Invitato{
    private String nome;
    private String cognome; 

    public Invitato(String nome, String cognome){
        this.nome = nome;
        this.cognome = cognome;
    }

    public Invitato(Invitato invitato){
        this.nome = invitato.getNome();
        this.cognome = invitato.getCognome();
    }

    public String getNome(){
        return nome;
    }

    public String getCognome(){
        return cognome; 
    }

    public String toString(){
        return nome   " "   cognome ";";
    }
}

public class Nodo{
    private Invitato info; 
    private Nodo link;

    public Nodo(Invitato invitato){
        this.invitato = new Invitato(invitato);
        link = null;
    }

    public Invitato getInfo(){
        return new Invitato(info);
    }

    public void setLink(Nodo link){
        this.link = link;
    }

    public Nodo getLink(){
        return link;
    }    
}
 

Комментарии:

1. getInfo() возвращает копию приглашения в Nodo. Не видя полной трассировки стека вашего NPE, невозможно определить, что не так.

2. Небольшой совет на будущее: пишите код на английском, а не на итальянском. Конечно, код все равно будет работать, но кому-то становится трудно читать и понимать, что вы делаете (даже мне, а я итальянец!)

3. Это вообще компилируется? В Nodo конструкторе вашего класса у вас есть this.invitato = ... , но у этого класса нет никакого поля с именем invitato .

Ответ №1:

Конструктор Nodo неверен:
this.invitato = new Invitato(invitato);
должно быть:
this.info= new Invitato(invitato);

И вам не нужно создавать новый экземпляр Invitato в конструкторе Nodo и в getInfo методе:

     public Nodo(Invitato invitato){
        this.info = invitato;
        link = null;
    }
    public Invitato getInfo(){
        return info;
    }
 

Как только конструктор исправлен, у меня есть список без каких-либо исключений:

 Mario Verdi;
Giacomo Neri;
Paolo Rossi;
Michele Bianchi;
 

Комментарии:

1. Большое спасибо, за исключением несоответствия информации и приглашения, я использовал свой подход из учебника, который для меня не имел смысла.