How to delete a repeated number in an array? C ++

1

Greetings, I'm studying programming in c ++ and it's complicated in one part of the problem. The problem is following:

  

Perform a class that contains a one-dimensional array of 30   integers (possibly repeated) and get that output   same arrangement but without repeated numbers. A method has to record data   in the arrangement, another method has to exclude the repeated ones and a third   method has to show the array without repeated numbers. Include a   constructor method to initialize the array with a value of zeros.

I have already done the part of making a class that contains data recording and I think I print the data, what fails me is how to eliminate the repeated numbers, that for example the user can give, example
the user defines a range up to 5, and the values that enter are 1, 2, 2, 4,67, now it is not clear to me how to print the results but without repeating the data in theory the result would be like this 1,2 , 4.67.

I already thank you in advance for your time and help.

#include<iostream>
#include<cstdlib>
#include<ctime>
#define MAX 30
using namespace std;
//se esta definiendo la clase
class Grabar {
private:
    int n,i, array[30];
    int valor;
    void datos();
public:
    void tirar();
    void imprimir();
    void eliminar();
};

void Grabar::datos()
{
    cout << "**************************************************";
    cout << "\n";
    do{
        cout<<"\n\nCantidad de elementos a ingresar: ";
        cin>>n;
            if(n<=0)
                cout<<"...No seas payaso(a), ingresa una cantidad correcta: "<<endl;
            if(n>MAX)
                cout<<"...La cantidad maxima permitida es "<<MAX<<" : "<<endl;
    }
    while(n<=0 || n>MAX);
    cout << "**************************************************";
    cout << "\n";
}

void Grabar::tirar()
{
    for(i=0; i<n; i++){
        cout<<"\n Elemento ["<<i<<"] ";
        cin>> array [i];
    }
    cout << "**************************************************";
    cout << "\n";
    cout<<"\n Elementos en el array: ";
    for(i=0; i<n; i++){
        cout<<"\n Elemneto ["<<i<<"]: "<<array[i];

    }


void Grabar::eliminar(){
    //Aca seria el codigo
}

void Grabar::imprimir()
{
    datos();
    cout << valor;
    cout << "\n";
}

int main()
{
    Grabar d;
    d.imprimir();
    d.tirar();
    d.eliminar();
    cin.get();
}
    
asked by Soter Ramirez 02.11.2016 в 22:24
source

3 answers

1

I think what you want to do is something like this that I show you next. The algorithm to do it is a bit rustic, but it works and you can improve it to be more efficient.

#include<iostream>
#define MAX 30

using namespace std;

class Grabar {

public:
    int len, arr[30];

    void leer();
    void eliminar_dup();
    void mostrar();

};

void Grabar::leer() {
    len = 0;
    int n;

    do {

        cout << "Introduzca la cantidad de valores (entre 1 y 30)" << endl;

        cin >> n;

        if(n < 1 || n > MAX)
            cout << "Error" << endl;
        else
            len = n;
    } while(n < 1 || n > MAX);

    cout << "Escriba los valores" << endl;

    for(int i=0; i<len; i++)
        cin >> arr[i];
}

void Grabar::eliminar_dup() {

    for(int i=0; i<len-1; i++)
        for(int j=i+1; j<len; j++) {
            ///Si encontramos un duplicado
            if(arr[i] == arr[j]) {

                ///Lo vamos intercambiando hasta que quede al final
                for(int k=j;k<len-1;k++)
                   swap(arr[k], arr[k+1]);

                ///Disminuimos la longitud en 1, lo que significa
                ///que se elimina un elemento
                len--;

                ///Disminuimos a j para que se quede en el mismo
                ///lugar (vease que el elemento que estaba en esa
                ///posicion fue eliminado, si no disminuimos j en 1
                ///nos saltamos un valor por analizar).
                j--;
            }
      }
}

void Grabar::mostrar() {

    for(int i=0;i<len;i++)
        cout << arr[i] << " \n"[i==len-1];
}

int main() {

    Grabar x;

    x.leer();
    x.eliminar_dup();
    x.mostrar();

    return 0;
}
    
answered by 02.11.2016 / 22:53
source
1

You have several ways to delete repeated numbers:

Container std :: set

std::set is an STL container that stores a list of ordered elements without duplicates. Its use is quite simple:

std::set<int> numeros;
for( int i=0; i<10; i++ )
{
  int n;
  std::cout << "Introduce un número: ";
  std::cin >> n;
  numeros.insert(n);
}

std::cout << "Lista de números sin repeticiones:\n";
for( int numero : numeros )
  std::cout << numero << '\n';

std :: vector + std :: sort + std :: unique

std::vector is the container par excellence of the STL. It stores a list of elements without ordering, it admits duplicates and, its great advantage, all the elements are in contiguous positions of memory, reason why its access is very fast when taking advantage of the benefits of the cache.

std::sort is an STL utility that allows you to sort a range of values.

std::unique is a utility of the STL that given a range of elements (start and end of range iterators), eliminates all contiguous occurrences of repeated elements. Well, it does not really eliminate them ... it moves them at the end of the range. Finally, it returns an iterator to the first duplicate element.

std::vector<int> numeros;
for( int i=0; i<10; i++ )
{
  int n;
  std::cout << "Introduce un número: ";
  std::cin >> n;
  numeros.push_back(n);
}

// Primero ordenamos la secuencia
std::sort(numeros.begin(),numeros.end());

// Despues eliminamos los duplicados
numeros.erase(std::unique(numeros.begin(),numeros.end()),numeros.end());

std::cout << "Lista de números sin repeticiones:\n";
for( int numero : numeros )
  std::cout << numero << '\n';

Although it may seem a more cumbersome method, this mechanism is much faster than the previous one before quite long sequences ... the longer the greater the difference in speed.

Container std :: set + std :: tie

The two previous methods have one drawback and that is that they order the initial sequence. This method is designed to keep the original sequence unaltered but without duplicates.

If you check the std::set help you can see that the insert() method returns a std::pair , which is just an object that allows you to store a pair of values. The first value is an iterator to the inserted element and the second value is a Boolean that indicates whether the inserted element is new in the container or if it already existed.

std::tie is a function that allows to exploit that object std::pair to recover its individual elements. The great advantage of this method is that it allows us to discard values that do not interest us. For your particular case you are only interested in the second value, the Boolean: if it is true it means that the element did not exist in the container.

The idea is to combine std::set and std::tie to identify the duplicate elements and eliminate them without needing to reorganize the original container:

std::vector<int> entrada{ 1,2,1,6,4,2,2,2,3 };
std::vector<int> salida;
std::set<int> detector;
for( numero : entrada)
{
  bool nuevo;
  std::tie(std::ignore,nuevo) = detector.insert(numero);
  if( nuevo )
    salida.push_back(numero); // solo se añaden los numeros no duplicados
}

for( int numero : salida)
  std::cout << numero << '\n';

std::ignore is not more than a kind of wastebasket, it is used to discard values we do not need.

Programming everything from scratch

If you have a sequence and you want to eliminate the duplicates you can choose to go through the sequence from beginning to end and in each iteration compare the current element with all the previous ones ... if there is a match the element is duplicated and you must eliminate it:

std::vector<int> entrada{ 1,2,1,6,4,2,2,2,3 };
std::vector<int> salida;

for( auto it = entrada.begin(); it != entrada.end(); ++it )
{
  bool duplicado = false;
  for( auto it2 = entrada.begin(); it2 != it; ++it2 )
  {
    if( *it == *it2 )
    {
      duplicado = true;
      break;
    }
  }

  if( !duplicado )
    salida.push_back(*it);
}

for( int numero : salida)
  std::cout << numero << '\n';

Simplifying the previous example

We can also give a brief review of the previous example to take advantage of the STL:

std::vector<int> entrada{ 1,2,1,6,4,2,2,2,3 };
std::vector<int> salida;

for( auto it = entrada.begin(); it != entrada.end(); ++it )
{
  if( std::count(entrada.begin(),it,*it) == 0 )
    salida.push_back(*it);
}

for( int numero : salida)
  std::cout << numero << '\n';

std::count tells you the number of times a certain value repeats in a range. In this case we iterate from the beginning of the list to the number immediately before the one we are checking and the number to look for is the current number:

//            (1)          (2)  (3)
std::count(entrada.begin(), it, *it)

// (1): inicio del rango = inicio de la lista
// (2): fin del rango = posición actual (no se incluye en la búsqueda)
// (3): valor a buscar = número actual

Greetings.

    
answered by 02.11.2016 в 23:07
0

there are structures that can help you, for example SET, which means that your collection will not store repeated elements

reads: link

now in c ++ it would be like this:

int a[] = {1,2,3,4};
std::set<int> s{1,2,3,4};
    
answered by 02.11.2016 в 22:32