c++vectormergesort

Merge sort by object attribute in vector


I make a c++ project to compare different algorithm complexity. I have a vector of Circle vector<Disque> and i would like to sort this vector by attribute x of circle (x-axis the most in left => x-axis-radius). I've implement merge-sort algorithm but doesn't work and dont know why.

Merge sort implementation :

/**
* Méthode qui permet de fusionner les tableaux qui ont été séparés afin de trier le tableau final
* @param indice_bas
* @param milieu
* @param indice_haut
* @param taille
*/
void fusion(int indice_bas, int milieu, int indice_haut, vector<Disque> tableau) {
    // Déclaration de différents indices pour la fusion
    int h,i,j,k;
    // Déclaration du tableau intérmediaire qui permet de stocké les disques du tableau
    vector<Disque> tab_tmp;
    // Initialisation des indices
    h = indice_bas;
    i = indice_bas;
    j = milieu+1;

    // Tant que nous avons pas trié l'ensemble du tableau
    while((h <= milieu) && (j <= indice_haut)) {
        // Si la valeurs de gauche est plus petite que celle de droite
        if((tableau[h].getPoint().getX() - tableau[h].getRayon()) <= (tableau[j].getPoint().getX() - tableau[j].getRayon())) {
            // On insère la valeur de gauche et on incrémente l'indice h
            tab_tmp.push_back(tableau[h]);
            h++;
        } else {
            // Sinon on interverti les valeurs du tableau afin de les remettrent dans l'ordre et on incrémente l'indice j
            tab_tmp.push_back(tableau[j]);
            j++;
        }
        // Incrémentation de i car tab_tmp[i] possède désormais une valeur
        i++;
    }

    // Si il reste des valeurs à insérer dans le tableau temporaire, on les insère suivant si elles sont dans le tableau de droite ou de gauche
    if(h > milieu) {
        // Boucle qui permet d'insérer les valeurs restantes
        for(k = j; k <= indice_haut; k++)
        {
            tab_tmp.push_back(tableau[k]);
            i++;
        }
    } else {
        // Boucle qui permet d'insérer les valeurs restantes
        for(k = h; k <= milieu; k++) {
            tab_tmp.push_back(tableau[k]);
            i++;
        }
    }

    // On replace les valeurs une à une dans le tableau que nous avons trié
    for(k = indice_bas; k <= indice_haut; k++){
        tableau[k] = tab_tmp[k];
    }
}

/**
 * Méthode tri fusion qui permet de trier les abscisse du point central d'un disque.
 * Choix de cet algorithme car la complexité est en n log n
 * @param indice_bas
 * @param indice_haut
 */
void tri_fusion(int indice_bas, int indice_haut, vector<Disque> tableau, int taille){
    // On déclare un indice qui correspond au milieu du tableau à trier pour effectuer un split
    int milieu;
    if(indice_bas < indice_haut) {
        // Calcul du milieu du tableau
        milieu = indice_bas + (indice_haut - indice_bas) / 2;
        // On appel récursivement la méthode de tri fusion jusqu'à la division de tous les tableaux
        tri_fusion(indice_bas, milieu, tableau, taille);
        tri_fusion(milieu + 1, indice_haut, tableau, taille);
        fusion(indice_bas, milieu, indice_haut, tableau);
    }
}

Main :

// Fonction main qui est le point d'entrée du programme
int main(int argc, const char * argv[]) {
    // Permet de générer plus d'aléa pour la création des disques
    srand((unsigned)time(NULL));
    // On crée quelques disques pour essayer les algos
    vector<Disque> tabDisque;
    for (int i=0; i < 10; ++i) {
        tabDisque.push_back(Disque(rand() % 10 + 1, Point(rand() % 30 + 1, rand() % 30 + 1)));
    }

    // On récupère la taille du vector
    int const taille = (const int)tabDisque.size();

    tri_fusion(0, taille-1, tabDisque, taille);

    for (int z = 0; z < taille ; z++) {
        cout << tabDisque[z].getPoint().getX() - tabDisque[z].getRayon() << " ";
    }
    return 0;
}

Thanks a lot and sorry for the french code :)


Solution

  • If you are aware of the difference between passing things to a function "by reference" and "by value": You passed your vector by value, you should clearly pass it by reference so you can modify it.

    If not: The way you pass you vector to your function right now is called passing "by value". The function will receive a copy of the vector. Now if you modify this copy, say by swapping two entries, the original vector will be unchanged. What you need to do is pass the function a reference to the vector so you can modify it. To do so, change vector<Disque> tableau to vector<Disque> &tableau both in fusion and tri_fusion. You should look up the difference between these two ways to pass values to functions, it's quite important.

    A second mistake is

    for(k = indice_bas; k <= indice_haut; k++){
      tableau[k] = tab_tmp[k];
    }
    

    The indexing in tab_tmp starts at 0, as opposed to indice_bas for tableau. You need to change this to something like

    for(k = 0; k <= indice_haut-indice_bas; k++){
      tableau[k+indice_bas] = tab_tmp[k];
    }
    

    This are the only mistakes I can see right now, but I can't compile your code as I don't know what Disque is, so there might be more I have missed.