[comp.lang.c] qsorting & managing struct arrays, pointer arrays

burleigh@cica.cica.indiana.edu (Frank Burleigh) (10/21/89)

Suppose you have:

   typedef struct struct_name {...} struct_name;
   struct_name list[MAXSIZE], *s_start, *s_one, *s_two;

   main()
   {
      /*load the array of struct here*/
      s_start = list;
      /*other business*/
      qsort( s_start, s_members, sizeof( struct_name ), ncmp );
   }

   int ncmp( struct_name * s_one, struct_name * s_two )
   {
      return strcmp( s_one->elem, s_two->elem );
   }

This arrangement works well (less than 1000 members), but it may
be a poor design.  If we display the structure members, have to
move forward and backward among them interactively, *and may re-
move members*, then there are two nagging problems.

   1) qsort won't know that you'd like to discard members tagged
   as deleted (ncmp could always make such members greater than
   the comparison member).

   2) Going forward (backward) by, say, 20 members isn't as easy
   some pointer arithmetic, as you could land on (a) deleted
   member(s).  You'd have to walk forward (backward) until 20
   valid members had been counted.  That seems like a lot of over-
   head in an interactive environment.

Adding a field to the structure pointing to the next valid member
doesn't seem to obviate the need to deal with these two problems.

Another approach is to instead maintain an array of pointers to
struct_name.  Assuming the members are sorted, then with each
deletion you could move forward all the following elements of the
array of pointers, filling in the gap created by the deletion;
you'd also decrement a variable counting the number of valid
members.  To move forward (backware) by 20 members only requires
bumping the index into the array of pointers by that much.

First, the concrete question:

   Can the standard qsort accept not the array of structures, but
   the array of pointers to structure members?  If yes, how then
   can the declaration of ncmp (the compare function) be changed
   to accept two elements ([i], [j]) from the array of pointers,
   since the call (and i, j) is buried in the library?  If no,
   then I'll have to make my own qsort -- less desirable, since it
   makes more sense to take advantage of the library authors'
   presumed expertise at writing fast sort routines.

Second, a more global question:

   If there are fewer than 1000 members in the struct, am I mis-
   taken to believe there would be less overhead in closing the
   gap in the array of pointers with each deletion, then there
   would be in counting off valid members with *each movement* in
   the array of struct, especially considering the need to
   occasionally resort?  Alternatively, are there approaches to
   managing a list on screen than I've not thought of and that
   have greater merit than either of the ones above?

Unless this seems of general interest, please e-mail.  Thank you
much.

-- 
Frank Burleigh  burleigh@cica.cica.indiana.edu
USENET: ...rutgers!iuvax!cica!burleigh BITNET: BURLEIGH@IUBACS.BITNET
Department of Sociology, Indiana University, Bloomington, Indiana 47405

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/21/89)

In article <169@cica.cica.indiana.edu> burleigh@cica.cica.indiana.edu (Frank Burleigh) writes:
>   Can the standard qsort accept not the array of structures, but
>   the array of pointers to structure members?

qsort() doesn't know what the array it is sorting consists of;
it leaves that up to the comparison function.  Thus, a standard
trick is to have qsort() sort an array of pointers to records
rather than an array of records.  The rest is merely a matter
of getting the type declarations right; this amounts to adding
an extra * to the parameters in the comparison function.  Note
that the comparison function is fed "generic" pointers (void* or
char*), and you ought to cast them into record_type**s before
using them in the comparison function.

cpcahil@virtech.UUCP (Conor P. Cahill) (10/21/89)

In article <169@cica.cica.indiana.edu>, burleigh@cica.cica.indiana.edu (Frank Burleigh) writes:

>    Can the standard qsort accept not the array of structures, but
>    the array of pointers to structure members?  If yes, how then
>    can the declaration of ncmp (the compare function) be changed
>    to accept two elements ([i], [j]) from the array of pointers,

Your example would be changed to something like:

    typedef struct struct_name {...} struct_name;
    struct_name *list[MAXSIZE], **s_start, *s_one, *s_two;
                ^               ^
 
    main()
    {
       /*allocate and load the array of struct here*/
         ^^^^^^^^^^^^
       s_start = list;
       /*other business*/
       qsort( s_start, s_members, sizeof( struct_name *), ncmp );
	                                              ^
    }
 
    int ncmp( struct_name ** s_one, struct_name ** s_two )
                           ^                     ^
    {
       return strcmp( (*s_one)->elem, (*s_two)->elem );
                      ^^^^^^^^        ^^^^^^^^
    }


NOTE: I have not compiled the above, but you should get the idea.




-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+