Merge arrays ordered in C ++

3

I need to combine the elements of two arrays interspersed and sort them during insertion. However, something strange happens when I order the second array ( arreglo2 ), since it modifies the first element of the first array ( arreglo1 ) and I have no idea why.

I'm compiling in Zinjai and I've tried it in CodeBlocks, but the problem remains the same:

#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

#define EXT 5

void ordenar (int *array);
void generar (int *a);

void ordenar(int *array){
    int aux=0;

    for(int j= 0 ; j<EXT ; j++){
        for(int i=0 ; i<EXT-j; i++){
            if(array[i] > array[i+1]){
                aux = array[i];
                array[i] = array[i+1];
                array[i+1] = aux;
            }
        }
    }

    cout << "Arreglo ordenado:";
    for(int k=0 ; k<EXT; k++)
        cout << "\t" << array[k];
    cout<<endl;
}

void generar (int *a) {

    cout << "Arreglo generado:"; 
    for(int i=0 ; i<EXT ; i++){
        a[i] = rand()%10;
        cout << "\t" << a[i];   
    }

    cout << "\n";
}

int main(int argc, char *argv[]) {

    int arreglo1[EXT];
    int arreglo2[EXT];
    int arregloS[EXT*2];
    int a = 0, b = 0, c = 0;

    srand(time(NULL));

    generar(arreglo1);
    ordenar(arreglo1);

    cout << "\n\n";

    generar(arreglo2);
    ordenar(arreglo2);
    cout << "\n\n";

    do{
        if (arreglo2[a] <= arreglo1[b]) {
            arregloS[c] = arreglo2[a];
            a++;
        }
        else if (arreglo2[a] >= arreglo1[b]) { 
            arregloS[c] = arreglo1[b];
            b++;
        }
        c++;
    }while(c < EXT*2);

    cout << "Arreglo final:"; 
    for (int i = 0 ; i<2*EXT ; i++){
        cout << "\t" << arregloS[i];
    }
    cout << endl; 

    return 0;
}
    
asked by Emiliano Rios 27.09.2018 в 03:12
source

3 answers

1

In this loop:

for(int j= 0 ; j<EXT ; j++){
    for(int i=0 ; i<EXT-j; i++){
        if(array[i] > array[i+1]){
            aux = array[i];
            array[i] = array[i+1];
            array[i+1] = aux;
        }
    }
}

If j==0 , i you can reach the value i=EXT-1 , which will have the following sequence:

aux = array[EXT-1];
array[EXT-1] = array[EXT];
array[EXT] = aux;

That is, you will be accessing elements that do not belong to the array. Recall that the indexes start at zero, then the index EXT is not valid.

The sort function should look more like the following example:

for( int i=0; i<EXT-1; i++ )
{
  for( int j=i+1; j<EXT; j++ )
  {
    if( array[i] > array[j] )
    {
      int aux = array[i];
      array[i] = array[j];
      array[j] = aux;
    }
  }
}

Or, using standard library functions:

for( int i=0; i<EXT-1; i++ )
{
  for( int j=i+1; j<EXT; j++ )
  {
    if( array[i] > array[j] )
      std::swap(array[i],array[j]);
  }
}

On the other hand, your function to merge the arrays is not correct and the reason is that does not verify if either of the two arrays has already been copied completely (that is, if a==EXT or b==EXT ). In consequence the fusion will end up accessing elements that do not belong to the arrays and, due to this, show erroneous results.

One possible solution:

for( int a = 0, b = 0, c = 0; c < EXT*2; c++ )
{
  if( a == EXT )
  {
    arregloS[c] = arreglo2[b];
    b++;
  }
  else if( b == EXT || arreglo1[a] <= arreglo2[b] )
  {
    arregloS[c] = arreglo1[a];
    a++;
  }
  else
  {
    arregloS[c] = arreglo2[b];
    b++;
  }
}

The first thing we do is verify that a and b are valid indexes. He thinks that if an index is not valid, it implies that the other must be mandatory. It is easy to verify that if a==EXT and b==EXT then, c = a+b = EXT+EXT = 2 * EXT , which is just the range in which c moves.

    
answered by 27.09.2018 в 10:07
1

I have compiled and tested your code and it works correctly, I do not observe the behavior " When I order arreglo2 modify the first element of arreglo1 ", maybe if you share the input data, the output data and the data that you hoped to obtain we can find it.

Meanwhile, you labeled the question as C and C ++ but your code is completely incompatible with C (hence the elimination of that label); Since your code is C, you should consider the following:

  • Headers <stdlib.h> and <time.h> are from not from . These headers have a version adapted to C ++ that has the prefix c and has no extension. If you really need to use the C headers (which will never be the case) you should use the C ++ equivalents <cstdlib> and <ctime> . Read this thread to find out why.
  • There is no obligation to use the using namespace std; clause since it is only an aid to the writing of code; If you decide to use this clause do not do it in the global scope, use it in the smallest possible scope. Read this thread to find out why.
  • The rand() function belongs to the C libraries, it is discouraged to use it in C ++ because it may not be portable and may offer questionable results and performance, therefore it is being studied deprecarla . From the C ++ 11 standard there is a complete library of generation of pseudo-random numbers that you should use instead. Read this thread to find out why.
  • Avoid using macros ( #define ), use constants instead. Macros are a preprocessor utility, not language, so they ignore contexts and namespaces, they can cause compilation problems, they do not belong to the type system and they are prone to be used in problematic ways.
  • Avoid using raw pointers; to store values use formations 1 if the size is known at compile time or containers if the size is dynamic. Avoid abusing std::endl (because it can cause performance problems) and favors the use of the explicit line break ( \n ). Read this thread to find out why.
  • Let your variables breathe, in the 90 we had screens of 80 characters wide and 25 lines high, by then it made sense to squeeze the code to fit on the screen. Today we have huge screens and separating variables and operators makes the code more readable.
  • Do not reinvent the wheel, if you have to do a sorting exercise, it's okay to write the ordering code, but otherwise use the tools that the language already provides, it will make your life easier and your code will be more concise and clear.
  • Encourages pre-increment versus post-increment .

    li>

With all this in mind, your code might look like this:

Proposal:

#include <iostream>
#include <random>
#include <algorithm>

constexpr int EXT = 5;

void ordenar(int (&array)[EXT]){
//               ~~~~~~~ <--- Formación recibida como referencia, no como puntero en crudo.
    int aux = 0;

    for (int j = 0 ; j < EXT; ++j){
        for (int i = 0; i < EXT - j; ++i){
            if(array[i] > array[i + 1]){
                std::swap(array[i], array[i + 1]);
            }
        }
    }

    std::cout << "Arreglo ordenado:";
    for (const auto &k : array) { // bucle for de rango
        std::cout << '\t' << k;
    }

    std::cout << '\n';
}

void generar(int (&a)[EXT]) {
//               ~~~~ <--- Formación recibida como referencia, no como puntero en crudo.

    // Generador de números entre 0 y 9 uniformemente distribuidos
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 9);
    // Generamos números
    std::generate(std::begin(a), std::end(a), [&]() { return dis(gen); });

    std::cout << "Arreglo generado:"; 
    for (const auto &i : a) { // bucle for de rango
        std::cout << '\t' << i;
    }

    std::cout << '\n';
}

int main() {

    using namespace std;

    int arreglo1[EXT];
    int arreglo2[EXT];
    int arregloS[EXT*2];
    int a = 0, b = 0, c = 0;

    generar(arreglo1);
    ordenar(arreglo1);

    cout << "\n\n";

    generar(arreglo2);
    ordenar(arreglo2);
    cout << "\n\n";

    do {
        if (arreglo2[a] <= arreglo1[b]) {
            arregloS[c] = arreglo2[a];
            ++a;
        }
        else if (arreglo2[a] >= arreglo1[b]) { 
            arregloS[c] = arreglo1[b];
            ++b;
        }
        ++c;
    } while (c < EXT * 2);

    cout << "Arreglo final:"; 
    for (int i = 0 ; i<2*EXT ; i++){
        cout << "\t" << arregloS[i];
    }
    cout << endl; 

    return 0;
}
  • Also known as arrays or in English arrays .
  • answered by 27.09.2018 в 10:16
    0

    In the sort function, on the line.

                    array[i+1] = aux;
    

    The value of the variable i reaches 4, which adding to 1 overflows the array.

        
    answered by 27.09.2018 в 09:48