C ++ How to remove an element outside the ends of a list

1

I use the list library and am having trouble removing an element using remove (), or erase (). With push_back () and push_front () it works, but I need to remove elements that are not on the ends ..

I want to pass the id of the node I want to remove.

I have already read the erase () and remove () documentation, but I still do not understand it. I created a basic example so you can understand and be able to help me.

No.h:

#ifndef NO_H_INCLUDED
#define NO_H_INCLUDED

#include <list>

using namespace std;

class No
{
    int id;

    public:
    No(int id); // construtor
    int getId();
};

#endif // NO_H_INCLUDED

No.cpp:

#include "No.h"
#include <list>

No::No(int id){
    this->id=id;
}

int No::getId(){
    return this->id;
}

Main.cpp:

#include <iostream>
#include "No.h"

using namespace std;

int main()
{
    list<No> *listaNos;
    list<No>::iterator it;

    //adicionando valores a lista;
    listaNos = new list<No>;
    No noAux(10);
    listaNos->push_back(noAux);
    No noAux2(20);
    listaNos->push_back(noAux2);
    No noAux3(30);
    listaNos->push_back(noAux3);
    No noAux4(40);
    listaNos->push_back(noAux4);
    No noAux5(50);
    listaNos->push_back(noAux5);

    //exibindo a lista;
    for(it=listaNos->begin();it != listaNos->end();it++){
        cout << it->getId() << " ";
    }

    //remover o elemento 20; Como fazer?

    return 0;
}
    
asked by anonymous 03.05.2016 / 15:05

1 answer

2

Here's a solution:

#include <vector>
#include <list>
#include <iostream>
#include <algorithm>

using namespace std;

class No {
    private:
        int id;
    public:
        No(int id)
        {
            this->id = id;
        };

        int getId()
        {
            return id;
        };

        // Sobrecarrega o operador de comparação (para igualdade).
        inline bool operator==(const No &outro) const
        {
            return outro.id == this->id;
        }
};

int main()
{
    list<No> listaNos;
    list<No>::iterator it;

    //adicionando valores a lista;
    No noAux(10);
    listaNos.push_back(noAux);
    No noAux2(20);
    listaNos.push_back(noAux2);
    No noAux3(30);
    listaNos.push_back(noAux3);
    No noAux4(40);
    listaNos.push_back(noAux4);
    No noAux5(50);
    listaNos.push_back(noAux5);

    //exibindo a lista ANTES de remover
    cout << "ANTES DE REMOVER, A LISTA TEM:" << endl;
    for (it = listaNos.begin(); it != listaNos.end(); it++) {
        cout << it->getId() << " ";
    }
    cout << endl;

    //remover o no com Id 20
    listaNos.erase(std::remove(listaNos.begin(), listaNos.end(), No(20)));
    //ou:
    //listaNos.erase(std::remove(listaNos.begin(), listaNos.end(), noAux2));

    //exibindo a lista APÓS remover
    cout << "DEPOIS DE REMOVER, A LISTA TEM:" << endl;
    for (it = listaNos.begin(); it != listaNos.end(); it++) {
        cout << it->getId() << " ";
    }
    cout << endl;

    return 0;
}

Result of this code:

ANTES DE REMOVER, A LISTA TEM:
10 20 30 40 50
DEPOIS DE REMOVER, A LISTA TEM:
10 30 40 50

The idea is to overwrite (reimplement) the comparison operator for equality in class No . So the removal methods can compare and find the Node that you want to remove based on the Id (note that the control of how it compares is within that code - you can do as you want / want).

For removal, you can not use only listaNos.erase because it expects the iterator of the item to be removed as a parameter. So, that's why you need to chain the call from std::remove to listaNos.erase .

It would also only work with erase using iterators' arithmetic if you knew what the node index is (and not its Id), and if you used vector instead of list (because the vector iterator is random access, the list is not). For example, if listaNos was a vector , you could do so:

listaNos.erase(listaNos.begin() + 1); // O primeiro nó é índice 0, logo o segundo é índice 1
  

Comments:

     
  • If you need to do other things like sorting using STL algorithms (such as std :: sort , for example), you will need   override other comparison operators. In this case   documentation (and its examples) are useful.
  •   
  • Note that I intentionally did not use the list as a pointer in this code, because it is not really necessary in this example . You   commented that his teacher said that he will have many knots, and that   you understand that you need to be a pointer. I do not totally agree. In practice,   How much do you want to use? But for your learning how to   professional programmer, I would tell you to talk to your   teacher and seek to understand the motivation for it. You'll learn   much about it. :)
  •   
        
    03.05.2016 / 15:42