0

Hello everyone i am writing a program for sorting general element in C. it can sort any type of object(int,float,complex number, objects)

What i have thought of is using void pointers,

void qsort(void *ptr,int sz,int i,int j,int (*fptr) (const void *,const void *) )
{

if(i<j)
{
    int p=(i+j)/2;
    p=partition(ptr,sz,i,j,p,fptr);
    qsort(ptr,size,i,p-1,fptr); 
    qsort(ptr,size,p+1,j,fptr); 
}
} 

FOR Comparison

By the value of sz we will know that whether its a pointer to string,int,char,float,etc

int compare(const void* a,const void* b,int sz)
{
if(sz==0)             //means pointer to a string
return strcmp( (char*)a, (char*)b );
else if(sz==1)  //means int
return  *(int*)a -  *(int*)b;
else if(sz==2)  //means float
return *(float*)a-  *(float*)b;
else if(sz==3)
return *(char*)a-  *(char*)b;
}

FOR SWAPPING TWO ELEMENTS

void swap(void *a,void *b,int sz)//for swapping
{
     if(sz==0)
     { 
      void *c;
      c=a;
      a=b;
      b=c;
      }
     else if(sz==1)
      {
      a=(int*)a;
      b=(int*)b;
      int c;
      c= *a;
      *a=*b;
      *b=c;
       }

     else if(sz==2)
     {
       a=(float*)a;
       b=(float*)b;
       float c;
       c= *a;
       *a=*b;
       *b=c;
     }

EDITED

qsort(arr,4,0,9,&compare);

The full code is under construction, please tell me if there could be some optimizations in my approach, or some better alternatives for this problem. As it seems to me that it is really going to be big in size

Many many thanx in advance

Luv
  • 5,381
  • 9
  • 48
  • 61
  • 5
    Do you have a reason for not just using the usual qsort function? http://linux.die.net/man/3/qsort – Michael Anderson Jul 07 '12 at 04:54
  • 1
    I wouldn't worry about the size, but enums would make your code more readable. BTW, your approach in swap() won't work: specifically, when you first say "a=(int*)a" and then "*a=*b", for the second statement, a and b are no longer int*. – Yusuf X Jul 07 '12 at 05:04
  • @MichaelAnderson I am using similar kind of thing – Luv Jul 07 '12 at 05:10
  • 1
    Stylistically, you could use switch statements, rather than long chains of ifs. – huon Jul 07 '12 at 05:11
  • @Yusuf I have used *a=*b and it will work – Luv Jul 07 '12 at 05:16
  • @user315052 I need to ask one thing that you have taken structures, but if i need to compare any two strings, chars, ints, floats, how would it be possible in your implementation? – Luv Jul 07 '12 at 17:51
  • 1
    I have updated my answer with an example for `int` array. The idea is the same, the caller would pass in a different comparison function, one that is specific for their array. – jxh Jul 07 '12 at 17:58
  • @user315052 ok it means we need to have different compare functions as per the type of array – Luv Jul 07 '12 at 18:00
  • 1
    Yes, it is better that way, since you don't know what crazy array type they will want to sort. – jxh Jul 07 '12 at 18:10
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13560/discussion-between-luv-and-user315052) – Luv Jul 07 '12 at 18:14

3 Answers3

2

Since your swap routine will likely be used by the partition function, it should work with arbitrary sized objects, not just the ones you plan to pass in to the code.

void swap (void *a, void *b, int sz) {
    char buf[512];
    void *p = buf;
    if (sz > sizeof(buf)) p = malloc(sz);
    memcpy(p, a, sz);
    memcpy(a, b, sz);
    memcpy(b, p, sz);
    if (p != buf) free(p);
}

From the way you have written your comparison routine, it seems you only plan to send in certain types of arrays. But, sz is usually used to tell how big the individual elements in the array are, not as a type identifier, as you seem to be trying to use it.

struct x { int key; /*...*/ };

int cmp_x (const void *a, const void *b) {
    const struct x *xa = a;
    const struct x *xb = b;
    return (xa->key > xb->key) - (xa->key < xb->key);
}

struct x array_x[100];
/* populate array */
qsort(array_x, sizeof(struct x), 0, 100, cmp_x);

This is how I imagine your qsort should be called. (Thanks to Ambroz Bizjak for the nifty comparison implementation.)

For an array of int:

int cmp_int (const void *a, const void *b) {
    int ia = *(const int *)a;
    int ib = *(const int *)b;
    return (ia > ib) - (ia < ib);
}

int array_i[100];
/* populate array */
qsort(array_i, sizeof(int), 0, 100, cmp_int);
Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193
1

The problem is that this does not allow sorting of custom types, like structs. The usual approach is to accept a function pointer which you call to do the comparisons.

Antimony
  • 37,781
  • 10
  • 100
  • 107
1

What you should be doing is passing in the comparison as a function pointer. You are passing in a function pointer but you don't seem to be using it to compare the values. You don't have to predefine all of the comparisons because you can define them when you use them, for the type of values you're using.

Michael Dorst
  • 8,210
  • 11
  • 44
  • 71
  • Then how we will compare different types – Luv Jul 07 '12 at 05:18
  • Why would you be comparing different types? If you're sorting, your sorting the same type. You're not going to pass in a `FILE *` and a `char *` and sort them. Which one is bigger? That just doesn't make sense. You're going to pass in a bunch of `int`s or a bunch of `double`s or a bunch of `char`s. – Michael Dorst Jul 07 '12 at 06:05
  • By different types i mean to say that sorting chars,ints,etc – Luv Jul 07 '12 at 06:26
  • Yes, but you (probably) don't want to sort an assortment of `char`s and `int`s at one time. If you do you should cast one to the other before you pass them in, otherwise you won't be able to iterate over them inside of your `qsort` function. – Michael Dorst Jul 07 '12 at 06:30