Tri d'un enregistrement dans tableau (C)

Fermé
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 - Modifié par cap'tain sheeps le 21/06/2011 à 13:57
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 - 22 juin 2011 à 13:27
Bonjour,
J'aimerais procéder à un tri dans mon tablau selon un champ d'un enregistrement qu'il contient de façon croissante. (ce champs étant un int).
Le problème est que je ne sais pas comment procéder.

Voici la définition de mes types :
//enregistrement d'une connection 
    typedef struct 
    { 
        char nomConnecteur[TAILLE_MAX_PETIT]; 
        char contact[TAILLE_MAX_PETIT]; 
        int equipotentielle; 
        int type; 
    } connection; 

//création du type qui savegardera les connections 
    typedef connection typeTableauConnection [TAILLE_MAX] 


et ma déclaration:
typeTableauConnection tableauConnections;


Voilà, j'aimerais donc que le tableau tableauConnections soit trié selon les valeurs de "type".

Je demande donc à une âme charitable de bien vouloir me donner une piste ou une théories sur un tri particulier, car je suis un peu perdu avec la tri à bulle (qui d'après ce que j'ai vu n'est pas l'idéal non plus).
En vous remerciant à l'avance,
Sheeps.

A voir également:

3 réponses

KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
Modifié par KX le 21/06/2011 à 14:26
Il faudrait vérifier sur un exemple, mais si tu fais ceci avec qsort tu n'as plus besoin de réfléchir à comment faire ta fonction de tri...

int compare(const void* a, const void* b)
{
	return ((connection*) a)->type - ((connection*) b)->type;
}

void trier(typeTableauConnection &tab, const int n)
{
	qsort(tab,n,sizeof(connection),compare);
}

int main ()
{
	typeTableauConnection tableauConnections;
	int taille = 5; // ?
	// ...
	trier(tableauConnections,taille);
	// ...
	return 0;
}
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
21 juin 2011 à 14:29
Salut et merci pour ta réponse.

Justement je me demandais si ça allait marcher avec qsort, j'ai testé et ça ne marchais pas. (sûrement dû au fait qu'il trie un tableau de type nombre et pas enregistrement).

Bref, tout ça pour dire que j'immagine que ton compare est là pour régler le problème, mais j'ai du mal à en comprendre la syntaxe. Pourrais-tu m'expliquer ce que ce sous-programme fais exactement? (Si ce n'est pas trop demander). En attendant je teste ce code.

Encore merci.
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
Modifié par KX le 21/06/2011 à 14:39
qsort tri n'importe quels types d'éléments, la fonction compare qu'on lui passe en argument renvoit un entier positif, nul ou négatif lorsque l'élement a est respectivement supérieur, égal, ou inférieur à b.
En fait la fonction compare permet d'expliquer à qsort comment comparer les deux éléments, dans ton cas en regardant le signe de a.type-b.type, car si qsort sait comparer deux éléments du même type, alors il peut trier un tableau d'éléments de ce type.
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
21 juin 2011 à 14:40
D'accord merci beaucoup.

(Je teste avant de mettre résolu mais j'y arrive, ne t'inquiètes pas ^^)
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
21 juin 2011 à 14:46
Remarque : il serait surement plus agréable de manipuler ce genre de type tableau :

typedef struct
{
	connection tab[TAILLE_MAX];
	int taille;
}
typeTableauConnection;

Dans ce cas trier devient plus facile à manipuler :

void trier(typeTableauConnection &tableau)
{
	qsort(tableau.tab,tableau.taille,sizeof(connection),compare);
}
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
21 juin 2011 à 15:25
Ouch ça va me ralonger encore plus tous mes noms de variables ça ^^. Chanque chose en son temps, si il m'en reste un peu je m'y pencherais, promis. ;-)
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
Modifié par cap'tain sheeps le 21/06/2011 à 15:08
Mhh.. quelques erreurs. (sûrement au niveau du passage des paraètres:

In function 'int NouvelleEqui(char*, connection*, char*, defConnection*)':| 
243|error: invalid initialization of reference of type 'connection (&)[10000]' from expression of type 'connection*'| 
19|error: in passing argument 1 of 'void trier(connection (&)[10000], int)'| 


J'ai pourtant mes prototypes en haut:
int compare(const void* a, const void* b); 

void trier(typeTableauConnection &tab, const int n);


Ma fonction qui utilisera tes fonctions:
int NouvelleEqui(char * cheminFichierFil, typeTableauConnection tableauConnections, char * cheminFichierPro, typeTableauDefinitionConnecteur tableauDefinitionConnecteur) 
{ 
//[...] 
int taille = 20;//par exemple 
trier(tableauConnections,taille); 

return nbnbnb; 
}


et le corps que tu m'a mis en bas... là j'ai du mal désolé ...

Edit : sachant que la définition des types est dans le header.
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
Modifié par KX le 21/06/2011 à 15:59
Chez moi ça marche, je pense que ton erreur doit venir d'ailleurs dans ton code...

Voici un exemple, j'en ai profité pour mettre en place ce dont je parlais sur le tableau, c'est quand même plus propre que la taille du tableau soit référencée à l'intérieur du type tableau plutôt que de balader une variable "taille" dans tout le programme !

#include <stdlib.h>
#include <stdio.h>

#define TAILLE_MAX_PETIT 5
#define TAILLE_MAX 10

typedef struct 
{
	char nomConnecteur[TAILLE_MAX_PETIT]; 
	char contact[TAILLE_MAX_PETIT]; 
	int equipotentielle; 
	int type; 
}
connection; 

typedef struct
{
	unsigned int taille; // entre 0 et TAILLE_MAX-1
	connection tab[TAILLE_MAX];
}
tableauConnections; 

int compare(const void* a, const void* b)
{
	return ((connection*)a)->type - ((connection*)b)->type;
}

void trier(tableauConnections &tableau)
{
	qsort(tableau.tab,tableau.taille,sizeof(connection),compare);
}

int main ()
{
	tableauConnections t={3,{{"c0","",0,2},{"c1","",0,3},{"c2","",0,1}}};

	trier(t); // c2 c0 c1

	for (unsigned int i=0; i<t.taille; i++)
		printf("%s(%d) ",t.tab[i].nomConnecteur,t.tab[i].type);

	system("PAUSE");
	return 0;
}
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
21 juin 2011 à 15:41
Merci,
Mouais c'est bisarre ces erreurs si ça marche dans ton code. Le truc c'est que mon programme fais plus ou moins 2500 lignes et qu'il y a beaucoup d'utilisation de ce tableau, donc ça me prendrais un petit moment de tout changer...

Bon je vais chercher par moi même et je te tiens au courant.
Merci encore.
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
Modifié par KX le 21/06/2011 à 15:53
Pour le tableau c'est juste un plus ;-)
Si tu remets ton typeTableauConnection comme avant ça marchera aussi...

#include <stdlib.h>
#include <stdio.h>

#define TAILLE_MAX_PETIT 5
#define TAILLE_MAX 10

typedef struct 
{
	char nomConnecteur[TAILLE_MAX_PETIT]; 
	char contact[TAILLE_MAX_PETIT]; 
	int equipotentielle; 
	int type; 
}
connection; 

typedef connection typeTableauConnection[TAILLE_MAX] ;

int compare(const void* a, const void* b)
{
	return ((connection*)a)->type - ((connection*)b)->type;
}

void trier(typeTableauConnection &tableau, const unsigned int taille)
{
	qsort(tableau,taille,sizeof(connection),compare);
}

int main ()
{
	unsigned int n = 3;
	typeTableauConnection t = {{"c0","",0,2}, {"c1","",0,3}, {"c2","",0,1}};

	trier(t,n); // c2 c0 c1

	for (unsigned int i=0; i<n; i++)
		printf("%s(%d) ",t[i].nomConnecteur,t[i].type);

	system("PAUSE");
	return 0;
}
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
21 juin 2011 à 16:20
Bon ça marche si je vire le & avant tableau. Vu que je passe le paramètre comme ça aussi dans ma fonction.
Après quelques autres erreurs, mais pas relative à ce problème. Donc merci (encore ^^) et => résolu.
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
Modifié par cap'tain sheeps le 22/06/2011 à 09:27
Désolé, mais je me vois dans l'obligation de relancer le sujet.

En effet, cette fonction fonctionne (euh...). Mais elle me trie mon tableau de façon bisarre. En fait pour des données :
@0 : ["CR","CD",0,2]
@1 : ["CD","CD",0,2]
@2 : ["CA","CD",0,3]
@3 : ["CP","CD",0,2]
@4 : ["CC","CD",0,4]

Il me le triera par exemple:
@0 : ["CP","CD",0,2]
@1 : ["CD","CD",0,2]
@2 : ["CR","CD",0,2]
@3 : ["CA","CD",0,3]
@4 : ["CC","CD",0,4]

Or, je ne veux pas que mon ordre des connections soit modifié lorsqu'il s'agit du même type. C'est à dire que je voudrais avoir:
@0 : ["CR","CD",0,2]
@1 : ["CD","CD",0,2]
@2 : ["CP","CD",0,2]
@3 : ["CA","CD",0,3]
@4 : ["CC","CD",0,4]

Je sais pas si c'est très clair, mais en gros, la fonction qsort ne me trie pas mon tableau comme il faut car elle inverse l'ordre de mes connecions au sein du même type.J'ai déjà la petite partie qui calculera la taille de chaque équipotentielle, mais je suis bloqué au niveau du tri:
    int it, itit, ititit; 
    int taille,auxEqui; 
    i=0; 

    for(ititit = 0; ititit < NB_LIGNES; ititit++) 
    { 
        itit  = i; 
        taille = 1; 
        auxEqui = tableauConnections[i].equipotentielle; 
        while (tableauConnections[i+1].equipotentielle == auxEqui) 
        { 
            auxEqui = tableauConnections[i].equipotentielle; 
            i++; 
            taille++; 
        } 
        //tri d'une équi 
        it = 0; 
        while (it < i - itit) 
        { 
            /*ici, je ne sais pas comment procéder, il faudrais répéter cette boucle pour tous les éléments à priori pour faire un tri à bulle, mais ce genre de tri est, parrait-il, très long pour l'ordinateur, et mon tableau a à peu près 600 éléments.*/ 
        } 
    }


Donc encore une fois, je suis dans le même cas de figure: Si quelqu'un connaitrait une technique de trie adaptée, je le verrais comme mon sauveur.

Merci d'avance!
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
Modifié par KX le 22/06/2011 à 10:03
C'est parce que tu voulais que le tableau tableauConnections soit trié selon les valeurs de "type". Mais tu n'as pas précisé quoi faire en cas d'égalité de ces types !
Ici on a bien l'ordre des enregistrement qui est modifié par ordre croissant des types, mais qsort fait "ce qu'il veut" pour les égalités, puisqu'on ne lui impose rien...

Pour que ça marche parfaitement, il faudrait définir un ordre total, c'est à dire : trier par ordre croissant des types, et si il y a égalité alors trier les égaux avec un autre ordre...
Dans tous les cas il faudra modifier la fonction compare pour être plus exigeant sur le critère de tri.

Il faudrait par exemple que tu rajouter une information int ordreInitial; et que tu imposes à qsort de trier dans l'ordre croissant de cette information en cas d'égalité sur les types :

int compare(const void* a, const void* b)
{
	connection *c1 = (connection*) a, *c2 = (connection*) b;

	if (c1->type==c2->type)
		return c1->ordreInitial - c2->ordreInitial;
	else
		return c1->type - c2->type;
}

[0,"CR","CD",0,2] 		[0,"CR","CD",0,2] 
[1,"CD","CD",0,2] 		[1,"CD","CD",0,2] 
[2,"CA","CD",0,3]	-->	[3,"CP","CD",0,2] 
[3,"CP","CD",0,2] 		[2,"CA","CD",0,3]
[4,"CC","CD",0,4]		[4,"CC","CD",0,4]

Remarque : c'est peut-être un peu "dangereux" mais au lieu d'indiquer une nouvelle information "ordre initial" tu pourrais essayer d'utiliser la valeur du pointeur comme critère de tri, si tes connecteurs sont dans un tableau ça pourrait marcher, mais faudrait tester pour voir, je suis pas sûr du tout :

int compare(const void* a, const void* b)
{
	int n = ((connection*) a)->type - ((connection*) b)->type;
	
	if (n==0)
 		return (int) a - (int) b;
	else
		return n;
}
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
22 juin 2011 à 11:00
Bah en fait, le truc avec cette fonction, c'est qu'elle est automatisée alors que j'ai besoin de faire quelque chose de particulier:

Premièrement ne pas changer l'ordre quand il y a le même type, qui pourrait se résoudre grâce à ton code, mais aussi, faire un tri de cette façon:
Quand la valeur équipotentielle = 0, on trie toutes les connections de l'équipotentielle 0 selon leur type.
Quand la valeur équipotentielle = 1, on trie toutes les connections de l'équipotentielle 1 selon leur type.
etc.

Or il faudra alors spécifier à cette fonction quelle partie du tableau trier, et changer donc aussi son premier paramètre, ce qui compliquerais encore plus le code. (Et encore si ceci est possible, je ne connais pas du tout cette fonction, mais à priori, elle plante quand j'augmente mes tests au delà de l'équipotentielle 0).

Bref, je te suis très reconnaissant, mais un tri sans utilisation de cette fonction ne serait-il pas plus judicieux et simple d'utilisation?

PS: Je m'excuse, c'est vrai que je n'ai pas donné toutes les informations dès l'ennoncé du sujet... A vrai dire je ne m'attendais pas à ce qu'une fonction de tri existe.
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
22 juin 2011 à 11:12
Cette fonction existe et l'intérêt de l'utiliser c'est qu'elle est optimisée... donc il serait peu judicieux de s'en passer... surtout pour faire un tri à bulle qui est le pire des tri !

Par contre, tu peux utiliser plusieurs fonctions de comparaisons et utiliser qsort différemment selon les cas que tu as à gérer.
Quand la valeur équipotentielle=0, trier avec qsort et compare_0
Quand la valeur équipotentielle=1, trier avec qsort et compare_1
etc...
0
cap'tain sheeps Messages postés 447 Date d'inscription jeudi 19 mai 2011 Statut Membre Dernière intervention 1 octobre 2014 10
22 juin 2011 à 11:29
Non, ma question initiale était justement une variante du tri à bulle pour avoir une optimisationdu tri. Après, j'aimerais bien pouvoir utiliser qsort, mais je pense que c'est impossible ou du moins, compliqué car à la question:

Est-ce qu'il est possible de procéder à un tri de l'équipotentielle n°1 sans toucher à l'équipotentielle n°0?

Si la seule solution est de créer des fonctions compare différentes, il faudra alors générer ces fonctions automatiquement, car le nombre d'équipotentielle varie selon une donnée d'entrée du programme. Sans compter sur le fait que le nombre de ces fonctions pourront être d'une centaine dans certains cas. Ce qui est (je pense) beaucoup plus compliqué que d'essayer de recréer algorithmiquement ma propre fonction de tri.

L'idéal pour moi serrait en fait de connaître le corps de cette fonction afin de pouvoir l'adapter "à ma sauce".

Après, je me doute bien que vous n'avez pas que ça à faire, c'est pourquoi je ne vous demande pas de m'écrire cette fonction, mais simplement de me donner une logique de tri afin de pouvoir me donner une piste qui me permettra d'en coder une.
Ne connaissant (vaguement) que le tri à bulle, je préfère justement l'éviter de par la lenteur de celui-ci, mais je n'ai pas trouvé dans mes recherches personnelles des variantes.

Ma question est donc : existes-il d'autres méthodes de tri, si oui : lesquelles?

PS: ne t'inquiètes pas, je te suis reconnaissant de ta proposition de solution, c'est juste que j'ai du mal avec les automatismes dont je ne connais rien...
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 018
22 juin 2011 à 12:04
En l'occurence qsort utilise le tri rapide (quick sort), tu peux toujours t'amuser à le recoder et l'adapter à tes besoins, mais je ne pense pas que ce soit plus simple...

Je ne suis pas sûr d'avoir forcément tout compris à ce que tu veux faire avec tes connecteurs, mais tu pourrais faire des "cellules" de tri, avec par exemple quatres valeurs : l'ordre initial, l'équipotentielle ou plus exactement un booléen qui indique si on doit trier cette équipotentielle, le type et le connecteur, comme ça ce ne sont pas les connecteurs que tu trieras mais les cellules, soit par rapport à l'ordre initial si le booléen est faux, ou par rapport au type si le booléen est vrai.
Ton tri consisterait donc à créer ces cellules à partir d'un tableau, en particulier choisir correctement les booléens selon les valeurs des connecteurs, faire le tri (avec une seule fonction compare) et récupérer les cellules dans l'ordre pour reconstituer ton tableau.

Exemple : tri des connecteurs 0

["CR","CD",0,5] 	(1,true,5,["CR","CD",0,5])
["CD","CD",0,4] 	(2,true,4,["CD","CD",0,4] )
["CA","CD",1,3]	-->	(3,false,3,["CA","CD",1,3])
["CP","CD",1,2] 	(4,false,2,["CP","CD",1,2])
["CC","CD",0,1]		(5,true,1,["CC","CD",0,1])
		
(5,true,1,["CC","CD",0,1])		["CC","CD",0,1]
(2,true,4,["CD","CD",0,4])		["CD","CD",0,4] 
(1,true,5,["CR","CD",0,5])	-->	["CR","CD",0,5]
(3,false,3,["CA","CD",1,3])		["CA","CD",1,3]
(4,false,2,["CP","CD",1,2])		["CP","CD",1,2]
0