Insert an array in one position within another

4

I'm doing an exercise of POO but with pointers, and I have to insert an array into another in the position that is requested, without overwriting or losing those that are, just move it.

In the function void IntArr::addElement(int pos,int qtty,int *vec) I do exactly that, but as you will see I complicate my life to do so.

Is not there a more efficient way to do it to avoid so many lines of code?

Some references:

  • qtty is the number of elements I want to pass from the vector to be inserted.
  • pos is the position that I want to insert.
  • vec is the vector to insert
  • p dynamic vector where I will insert values
  • used number of used elements of the vector p
  • size vector size p

I leave the code of the functions, but if you need the full class and the main to understand what I need, tell me and I edit it.

This is my code :

void IntArr::addElement(int pos,int qtty,int *vec){
  verificarPos(pos);
  redimensionador(qtty);

  //Iterador de los vectores auxiliares
  int j=0;

  //Vemos la cantidad de elementos a desplazar
  int cantDesp;
  cantDesp = used - pos;

  //Creamos el vector auxiliar con la cantidad de elementos a desplazar
  int vAux[cantDesp];

  //Recorremos el array original para guardar los elementos a desplazar
  for(int i=pos;i<used;i++){
    //cout<<endl<<"vAux["<<j<<"] = "<<vAux[j]<<" --> p["<<i<<"] = "<<p[i]; //DEBUG
    vAux[j] = p[i];
    j++;
  }

  //Vemos hasta donde llegan los nuevos items a agregar
  int espNew;
  espNew = pos + qtty;
  j=0; //Reinicio iterador

  //Agregamos los nuevos items al vector p[]
  for(int i=pos;i<espNew;i++){
    p[i] = vec[j];
    j++;
  }

  //Calculamos la pos hasta donde irán los items desplazados
  int pAux;
  pAux = used + qtty;
  j=0; //Reinicio iterador

  //Utilizamos el vAux para agregar los items salvados
  for(int i=used-1;i<pAux;i++){
    p[i] = vAux[j];
    j++;
  }
  used += qtty;
}

//Verificador
void IntArr::redimensionador(int cant){
  if(cant+used>size){
    if(cant > 5){
      size += cant;
    }
    else{
      size += 5 + cant;
    }
    int *temp = new int [size];
    memcpy (temp,p,used*sizeof(int));
    delete [] p;
    p = temp;
  }
}
void IntArr::verificarPos(int &pos){
  if(pos<=0){   //Si la posición es negativa o igual a cero
    pos = 0;
   }
  else if(pos>=size){ //Si la posición supera el tamaño del array
    pos = used;
  }
}
    
asked by Emiliano Calvacho 18.04.2018 в 20:00
source

2 answers

5
  

Is not there a more efficient way to do it to avoid so many lines of code?

There are several ways to measure the efficiency of an algorithm, from the great O to just the style . An algorithm of the type you describe can not be more efficient than O (n).

You can improve your algorithm not in efficiency but in something that is usually much better and will earn you the respect and admiration of your coworkers: Legibility.

Things to keep in mind.

  • Self-explanatory names : In the 80s and 90s, we had to program on screens of 80 characters wide and 25 lines high, making the code concise, concise and clustered was a necessity. Those times have been (thankfully) behind, so avoid the variables of a single character, acronyms and abbreviations.
  • Small areas : It is recommended that the scope of the variables be as small as possible; this makes it easier to follow the code because you do not have to continually go back to a definition several lines back to know the history of a variable.
  • Initialization : Initialize all the variables, you can do it in the definition itself.
  • Do not reinvent the wheel : C ++ offers many utilities that do routine tasks, it is not worth inventing your own method for it having available utilities tested by hundreds of thousands of users and with the endorsement of a standard. I understand that the exercise of arrays forces you to use pointers instead of utilities like std::array or std::vector , but nothing prevents you from using std::copy or std::copy_n .
  • Use objects : C ++ is a language that (among others) uses the object-oriented paradigm; the objects allow you to give a semantic sense to data sets while grouping data that are closely related.

Those are simple premises, in addition you have an error: you are creating a static size array using a variable size whose value is known at runtime, that is not portable. See the questions that mention VLA for more information.

Proposal.

I understand what you want to do is this:

But you must also take into account these other cases:

In either case the task has three steps:

  • Create a new space (result of adding the space of array e into ).
  • Copy the data to the new space.
  • Delete (if applicable) the old data.
  • As I have already proposed: use objects, an object that groups the pointer and the size associated with it will facilitate your work:

    struct my_array
    {
        int quantity = 0;       // Nada de qtty, queremos un nombre legible.
        int *vector = nullptr;  // Nada de vec, queremos un nombre legible.
    };
    

    This way your insertion function can receive two objects my_array and return another my_array as a new object:

    /* 'array' e 'into' son nombres que en el contexto de una función
    llamada 'insert' nos dan claras pistas de lo que podemos esperar
    de dicha función. La variable 'position' (no 'pos') cobra sentido
    fácilmente en este contexto. */
    my_array insert(const my_array &array, my_array &into, int position)
    {
        // Tamaño resultante de insertar 'array' en 'into'.
        const auto size = array.quantity + into.quantity;
        // Nuevo objeto resultante de la inserción de 'array' en 'into'
        my_array result { size, new int[size]{} };
    
        /* (1) 'position' elementos de 'into' en 'result' desde el inicio de 'into'. */
        auto bookmark = std::copy_n(into.vector, position, result.vector);
    
        /* (2) todos los elementos de 'array' en 'result' desde el punto anterior. */
        bookmark = std::copy_n(array.vector, array.quantity, bookmark);
    
        /* (3) el resto de elementos de 'into' en 'result' desde el punto anterior. */
        std::copy_n(into.vector + position, into.quantity - position, bookmark);
    
        return result;
    }
    

    The function std::copy_n copies elements of the first parameter in the pointer of the third parameter, copies as many elements as indicated in the second parameter and returns where it stopped copying when the operation was finished, therefore the algorithm is very simple. Follow and write. Here is an illustration of what happens when you copy array in the middle of into :

    You can see the code working in Wandbox 三 へ (へ ਊ) へ ハ ッ ハ ッ .

        
    answered by 19.04.2018 / 08:41
    source
    1

    In case you get interested, I have this method that is an alternative to the one you published, it is not more efficient (or if), but good.

    void IntArr::addElement(int pos,int qtty, int *vec){
        if(used+qtty>size){
            espaciar(qtty);
        }
        int *aux=new int[size];
        if(pos<=0){
            for(int i=0;i<qtty;i++){
                aux[i]=vec[i];
            }
        int x=qtty;
        for(int i=0;i<used;i++){
            aux[x]=p[i];
            x++;
            }
        }
    
        if (pos>size || pos>used){
            for (int i=0;i<used;i++){
                aux[i]=p[i];
            }
            for (int i=0;i<qtty;i++){
                aux[used+i]=vec[i];
            }
        }
    
        if (pos>0 && pos<=used){
            for (int i=0;i<pos;i++){
                aux[i]=p[i];
            }
            for (int i=0;i<qtty;i++){
                aux[pos+i]=vec[i];
            }
            for (int i=pos;i<used;i++){
                aux[i+qtty]=p[i];
            }
        }
    
        used+=qtty;
        delete []p;
        p=aux;
    
    }
    

    I hope you help Calvin. And if it did not help you, it does not matter.

        
    answered by 20.04.2018 в 23:38