Lista c++ - Usuwanie elementu

0

Witam. Mam problem

Zrobiłem jaką taką listę bo się uczę i właściwie wszystko wydaje się działac, lecz za nic nie mogę dojść
dlaczego program się zawiesza, gdy usuwam element ostatni.
W innych przypadkach element pierwszy i każdy inny oprócz ostatniego działa.

Uprzejmie proszę o wskazówki, co jest nie tak w funkcji do usuwania.

http://pastebin.com/4vAkYzpr

0
Node * tmp2 = tmp->NEXT->PREV;

Jeśli tmp to ostatni element, to tmp->NEXT to NULL, czyli tmp->NEXT->PREV to NULL->PREV. Co to jest NULL->PREV?

if(tmp->value == key-1)

Dlaczego key-1?

0

Nie debugowałem tego, ale na pierwszy rzut oka to to, że w usuwaniu w tym else zamiast

while (tmp->NEXT) 

powinno być while (tmp)


Dodatkowo to co zauważyłem w Twoim usuwaniu to to, że nigdzie na początku nie sprawdzasz czy lista jest pusta. Czy FIRST nie jest nullem. Ma to taki skutek, że wywali Ci program jak będziesz chciał coś usunąć z pustej listy (:  Tu dowód: https://ideone.com/QWjlU7

Możliwe, że jest więcej błędów, ale nie sprawdzałem dogłębnie


EDIT

Jeśli mogę to dodam jeszcze co bym poprawił w programie.

Nie mieszaj polskiego z angielskim w kodzie. Zdecyduj się na któryś na początku i zdecyduj się na angielski ;)

Używaj listy inicjalizacyjnej

Fajnie by było gdyby **Node** miał też konstruktor taki o 
```cpp
Node::Node( Node *prev, int value ) :
    NEXT( NULL ),
    PREV( prev ),
    value( value )
{}

Dzięki temu dodaj mogłoby wyglądać tak

 void Lista_Dodaj(int val)
    {
        Node* tmp = FIRST;

        while ( tmp )
            tmp = tmp->NEXT;
        
        tmp->NEXT = new Node( tmp, val );
    }

ładniej chyba.

Jeszcze jedna wskazówka. Fajnie by było gdyby Lista_znajdz zwracała wskaźnik do znalezionego elementu. Mogła by ona wyglądać tak np.

    Node* Lista_Znajdz( int Poszukiwana )
    {
        Node* tmp = FIRST;
        
        while ( tmp )
        {
            if (tmp->value == Poszukiwana)
                return tmp;

            tmp = tmp->NEXT;
        }
        
        return nullptr;
    } 

Dzięki temu przy usuwaniu mógłbyś ją wykorzystać zamiast powielać kod znajdowania elementu w liście. I przerobić usuwanie na coś takiego

void Lista_Usun( int key )
    {
        Node *node;
        
        node = Lista_Znajdz( key );
        
        if( node == nullptr )
            return;
        
        if( node->PREV != nullptr )
            node->PREV->NEXT = node->NEXT;
        
        if( node->NEXT != nullptr )
            node->NEXT->PREV = node->PREV;    
    } 
0

Bardzo dziękuje za porady i sugestie. Na pewno się do nich zastosuje i je przemyślę.

Zmiana tmp->next na tmp w "else" niestety nie przyniosła rezultatu jeszcze :)

0

No i jeszcze dorób destruktor listy bo masz wycieki pamięci

0

Bardzo proszę jeszcze o wytłumaczenie mi jednej kwestii.

Czym dokładnie w działaniu różni się zapis :

while(tmp) tmp = tmp->NEXT;

while(tmp->NEXT) tmp = tmp->NEXT;

Rozumiem że drugi zapis, będzie wykonywał pętle "WHILE" dopóki w pewnym TMP->NEXT znajdzie wartość NULL.

W takim razie czym różni się w działaniu zapis pierwszy?

0

tym, że jeżeli przed pętlą tmp jest równe NULL to nic się nie stanie a w drugim zapisie wywali Ci program bo będziesz chciał zrobić NULL->NEXT

0

Generalnie chodzi że w funkcji która dodaje węzeł do Listy :

http://pastebin.com/Tp23A0sw

nie działa zapis while(tmp) tylko while(tmp->next) i staram się zrozumieć dlaczego

0

Gdy wychodzisz z takiej pętli

while (tmp)

tmp jest już nullem, więc wszelkie próby wywołania tmp->... skończą się błędem.

Natomiast gdy wychodzisz z tej pętli

while (tmp->next)

tmp jest nadal poprawnym węzłem, na którym można robić różne rzeczy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1