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

Asked

Viewed 778 times

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 at the ends..

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

I have read the Rase() and remove() documentation, but I still don’t get it.. I created a basic example so you can understand and 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;
}
  • Dudu, good that you opened another question about this specific doubt. But look, try to improve it a little bit. First you don’t make clear what your difficulty is (by what I had understood you want to remove a node from the list from its identification number, right? If yes, put this in the text of the question. ). Another thing, try to make the example be a [mcve]. For this, also put the minimum code of the class No. Finally: why is it even that you make such a point of using the vector as a pointer? You understood that you do not need, right?

  • Your help is being crucial, so I’m making the decisions you suggest. I edited the question by adding my node class and specifying what I want. I am now using list and no longer vector. As for the pointer, the work refers to an implementation in graphs that tends to grow a lot, for some reason the teacher suggested that we use pointer, I believe it is due to some future functionality... I count on your help in this issue more @Luizvieira

1 answer

2


Here is 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 override (reimplement) the comparison operator for equality in class No. Thus, the removal methods can compare and find the Node you want to remove based on the Id (note that the control of how it compares is within this code - you can do as you wish/like).

For removal, you cannot use only the listaNos.erase, because it expects as a parameter the iterator of the item to be removed. Thus, for this reason you need to chain the call to std::remove in the listaNos.erase.

It would also work only with the call from erase using iterator arithmetic if you knew what the node index is (not its id), and if you used vector in place of list (because the vector iterator is random access, the list iterator is not). For example, if listaNos were a vector, you could do so:

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

Remarks:

  1. If you need to do other things like sort using STL algorithms (such as the Std::, for example), you will need override other comparison operators. In this case to documentation (and her examples) are useful.
  2. 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 your teacher said will have many knots, and that by this you understand will need to be pointer. I do not fully agree. In practice, as much as you will use. But for your learning as professional programmer, I would say you talk to your teacher and try to understand the motivation for it. You will learn a lot about. :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.