IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

utiliser qsort avec void**


Sujet :

C

  1. #21
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par dj.motte
    Bonjour,

    D' accord pas de changement pour cmp.
    Maintenant dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void tri (TR ** q,  size_t n)
    {
       qsort (q, n, sizeof *q, cmp);
    }
    j' ai l' impression que sizeof * q sera toujours égal à 4, avec un processeur 32 bits.
    Peut être, c'est grave ? Ceci est destiné à trier un tableau de pointeurs (c'est toi qui a lancé l'idée du void **, alors moi, bête et discipliné, je respecte la consigne).

    Si tu veux trier un tableau de structures, tu fais ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void tri (TR * q,  size_t n)
    {
       qsort (q, n, sizeof *q, cmp);
    }
    et voilà. C'était pas trop dur comme maintenance...

    Remarque, plus l'objet est petit, plus le tri est rapide... Un tableau de pointeurs sur des structures est donc plus rapide à trier qu'un tableau de grosse structure.

  2. #22
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut
    Bonjour,

    Cela pourait être plus complexe avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
     
    //#include <stdlib.h>
    #include <stdio.h>
     
    int Array[] = { 100, -4, 11 ,99,-9,5,78,90,37,71,1,54,31,-2, -1 ,123,-9,7,36,198,11,98,67,38,12,7,23,78,89,32,2 };
    unsigned  max = sizeof( Array ) / sizeof( Array[0] ) ;
     
     int intcomp( int *c1, int *c2 )
        { return( *c1 - *c2 ) ; }
     
    typedef int comparF (const void *, const void *);
     
    static  comparF    *Fcmp;
    static  unsigned    qWidth;
    #define _LT_(x,y)       (x < y)
     
    /*-----------------------------------------------------------------------*
    Name            Exchange - exchanges two objects
    Usage           static  void  Exchange (void  *leftP, void *rightP);
    Description     exchanges the qWidth byte wide objects pointed to
    		by leftP and rightP.
    Return value    Nothing
    *------------------------------------------------------------------------*/
     
     void  Exchange (void  *leftP, void *rightP)
      { unsigned  i;
        char  c;
        char *lp = (char *)leftP;
        char *rp = (char *)rightP;
     
        for (i = 0; i < qWidth; i++ )
         { c = *rp;
           *rp++ = *lp;
           *lp++ = c;
         }
      }
     
    /*-----------------------------------------------------------------------*
    Background
     
    The Quicker Sort algorithm was first described by C.A.R.Hoare in the
    Computer Journal, No. 5 (1962), pp.10..15, and in addition is frequently
    described in computing literature, notably in D. Knuth's Sorting and
    Searching.  The method used here includes a number of refinements:
     
    - The median-of-three technique described by Singleton (Communications
      of the A.C.M., No 12 (1969) pp 185..187) is used, where the median
      operation is also the special case sort for 3 elements.  This slightly
      improves the average speed, especially when comparisons are slower
      than exchanges, but more importantly it prevents worst-case behavior
      on partly sorted files.  If a simplistic quicker-sort is run on a file
      which is only slightly disordered (a common need in some applications)
      then it is as slow as a bubble-sort.  The median technique prevents
      this.
     
      Another serious problem with the plain algorithm is that worst-case
      behavior causes very deep recursion (almost one level per table
      element !), so again it is best to use the median technique.
     
    - The values of width and compar are copied to static storage and a help
      function with a minimum of parameters is used to reduce the recursion
      overheads.  Recursion is used both for simplicity and because there
      is no practical gain from conversion to loops: the extra housekeeping
      needed for loops needs registers for speed, but the 8086 family has not
      enough registers.  Juggling registers takes just as much time as calling
      subroutines.
     
    /************************************************************************/
    Name            qSortHelp - performs the quicker sort
    Usage           static void  near pascal  qSortHelp (char *pivotP,
    						     size_t nElem);
    Description     performs the quicker sort on the nElem element array
    		pointed to by pivotP.
    Return value    Nothing
    *------------------------------------------------------------------------*/
     
    void  qSortHelp (char *pivotP, size_t nElem)
    {   char     *leftP, *rightP, *pivotEnd, *pivotTemp, *leftTemp;
        unsigned  lNum;
        int       retval;
     
    tailRecursion:
        if (nElem <= 2)
         { if (nElem == 2)
    	{ if (Fcmp (pivotP, rightP = qWidth + pivotP) > 0)
    	  Exchange (pivotP, rightP);
    	}
          return;
         }
     
        rightP = (nElem - 1) * qWidth + pivotP;
        leftP  = (nElem >> 1) * qWidth + pivotP;
        //leftP  = (nElem / 2 ) * qWidth + pivotP;
     
    /*  sort the pivot, left, and right elements for "median of 3" */
     
        if (Fcmp (leftP, rightP) > 0)
    	Exchange (leftP, rightP);
        if (Fcmp (leftP, pivotP) > 0)
    	Exchange (leftP, pivotP);
        else if (Fcmp (pivotP, rightP) > 0)
    	Exchange (pivotP, rightP);
     
        if (nElem == 3)
           { Exchange (pivotP, leftP);
    	 return;
           }
     
    /*  now for the classic Hoare algorithm */
     
        leftP = pivotEnd = pivotP + qWidth;
     
        do {
    	while( (retval = Fcmp(leftP, pivotP)) <= 0)
    	 { if (retval == 0)
    	   { Exchange(leftP, pivotEnd);
    	     pivotEnd += qWidth;
    	   }
    	   if (_LT_ (leftP, rightP)) leftP += qWidth;
    	   else goto qBreak;
    	 }
    	while (_LT_(leftP, rightP))
    	 {  if ((retval = Fcmp(pivotP, rightP)) < 0)
    	    rightP -= qWidth;
    	    else
    	    { Exchange (leftP, rightP);
    	      if (retval != 0)
    	       { leftP += qWidth;
    		 rightP -= qWidth;
    	       }
    	     break;
    	    }
    	 }
           } while (_LT_(leftP, rightP));
     
     qBreak:
     
        if (Fcmp(leftP, pivotP) <= 0)
    	leftP = leftP + qWidth;
     
        leftTemp = leftP - qWidth;
        pivotTemp = pivotP;
        while ((pivotTemp < pivotEnd) && (leftTemp >= pivotEnd))
         { Exchange(pivotTemp, leftTemp);
           pivotTemp += qWidth;
           leftTemp -= qWidth;
         }
     
        lNum = (leftP - pivotEnd) / qWidth;
        nElem = ((nElem * qWidth + pivotP) - leftP)/qWidth;
     
        /* Sort smaller partition first to reduce stack usage */
        if (nElem < lNum)
    	{ qSortHelp (leftP, nElem);
    	  nElem = lNum;
    	}
        else
    	{ qSortHelp (pivotP, lNum);
    	  pivotP = leftP;
    	}
        goto tailRecursion;
    }
     
    /*-----------------------------------------------------------------------*
    Name            qsort - sorts using the quick sort routine
    Usage           void qsort(void *base, int nelem, int width, int (*fcmp)());
    Prototype in    stdlib.h
    Description     qsort is an implementation of the "median of three"
    		variant of the quicksort algorithm. qsort sorts the entries
    		in a table into order by repeatedly calling the user-defined
    		comparison function pointed to by fcmp.
     
    		base points to the base (0th element) of the table to be sorted.
     
    		nelem is the number of entries in the table.
     
    		width is the size of each entry in the table, in bytes.
     
    		*fcmp, the comparison function, accepts two arguments, elem1
    		and elem2, each a pointer to an entry in the table. The
    		comparison function compares each of the pointed-to items
    		(*elem1 and *elem2), and returns an integer based on the result
    		of the comparison.
     
    			If the items            fcmp returns
     
    			*elem1 <  *elem2         an integer < 0
    			*elem1 == *elem2         0
    			*elem1 >  *elem2         an integer > 0
     
    		In the comparison, the less than symbol (<) means that the left
    		element should appear before the right element in the final,
    		sorted sequence. Similarly, the greater than (>) symbol
    		means that the left element should appear after the right
    		element in the final, sorted sequence.
     
    Return value    qsort does not return a value.
     
    *------------------------------------------------------------------------*/
     
    void  Qsort(void *baseP, size_t nElem, size_t width, comparF *compar)
    /*
      The table *baseP containing a count of nElem records each of fixed width
      is to be converted from unknown order into ascending order, using the
      ordering provided by the comparison function compar.
     
      The comparison function compar (leftP, rightP) must return less than, equal,
      or greater than zero, according to whether it decides that (record) *leftP
      is less than, equal, or greater than (record) *rightP.
     
      The internal contents of the records are never inspected by qsort.  It
      depends entirely upon compar to decide the format and value of the records.
      This allows the content of the records to be of any fixed length type -
      formatted text, floating point, pointer to variable length record, etc. -
      so long as each record is understood by compar.
     
      The quicker sort algorithm will in general change the relative ordering
      of records which may compare as equal.  For example, if it is attempted
      to use two passes of quick sort on a order file, first by date and then
      by customer name, the result will be that the second sort pass randomly
      jumbles the dates.  It is necessary to design the compar() function to
      consider all the keys and sort in one pass.
    */
     
     {
        if ((qWidth = width) == 0)	return;
        Fcmp = compar;
        qSortHelp (baseP, nElem);
     }
     
      void say( int * A , size_t nb )
       { size_t i ;
         for( i = 0 ; i < nb; i++ )
         printf("%d ", A[i] ) ;
         printf("\n");
       }
     
      void main()
       { puts("Begin");
         say( Array, max ) ;
         Qsort( Array, max, sizeof(int), (comparF*) intcomp ) ;
         say( Array, max ) ;
         puts("End");
         getchar();
       }
    La médiane de trois...avec des "goto"... bref qsort fait le ménage.
    Ma question vient du fait que l' arithmétique des pointeurs tient sur le ( char * ) et non pas sur le ( void * ).

    Il me semble que la dernière mouture du C , permet l' arithmétique du pointeur sur ( void * ) .

    Vous confirmez ou je me trompe ?

    salut.

  3. #23
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par dj.motte
    Ma question vient du fait que l' arithmétique des pointeurs tient sur le ( char * ) et non pas sur le ( void * ).

    Il me semble que la dernière mouture du C , permet l' arithmétique du pointeur sur ( void * ) .
    Non. C'est une extension (bien malheureuse) de gcc...

  4. #24
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut
    Bonjour,

    Emmanuel Delahaye écrit :
    Non. C'est une extension (ben malheureuse) de gcc...
    Pourquoi malheureuse ?

    Il me paraît normal que le type (void *) soit soummis à l' arithmétique des pointeurs.

    Le problème est dans la reécriture des codes source.
    Vous confirmez ?

    salut.

  5. #25
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par dj.motte
    Pourquoi malheureuse ?

    Il me paraît normal que le type (void *) soit soummis à l' arithmétique des pointeurs.
    C'est contre la définition du langage C qui dit clairement que le type void n'a pas de taille connue et que donc l'arithmétique des pointeurs ne s'applique pas. Pour qu'elle s'applique, il faut un type explicite (typecast ou pointeur relais) différent de void.

Discussions similaires

  1. [Kylix 3] Je n'arrive pas à utiliser MySQL
    Par usebob dans le forum EDI
    Réponses: 4
    Dernier message: 15/04/2005, 11h18
  2. Réponses: 6
    Dernier message: 24/02/2005, 10h44
  3. PB de vue utilisant UNION avec ENTERPRISE MANAGER
    Par punglas dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 22/12/2004, 16h18
  4. Réponses: 12
    Dernier message: 02/02/2004, 14h41
  5. qsort avec un struct* ?
    Par hpfx dans le forum MFC
    Réponses: 11
    Dernier message: 06/10/2003, 19h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo