hey guys i have this code here but i cannot understand what the cmpfunc function does actually i don't understand the return statement can someone explain it to me ? than
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main()
{
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Start with a qsort description - here it is.
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
So you need to write a function with such inputs and output to use in qsort.
int cmpfunc (const void * a, const void * b)
is ok, but inputs are *void and you need to compare integers in your case. So you will need to convert types. That's why there are
*(int*)a
Finally, return values of cmpfunc must match requirements from qsort description.
In article I mentioned at the begging of this post you can find this implementation:
int compareMyType (const void * a, const void * b)
{
if ( *(MyType*)a < *(MyType*)b ) return -1;
if ( *(MyType*)a == *(MyType*)b ) return 0;
if ( *(MyType*)a > *(MyType*)b ) return 1;
}
Your version is just a proper simplification of it.
cmpfnc is comparing the values of of pointers provided. It uses void* so that any kind of data can be passed to it and compared after being converted. First it converts the void* values to int* and then deferences them via * to subtract the integers they are pointing at
When you want to sort an array of some kind you need a comparison function.
the comparison function is used by qsort in order to compare two objects in the array. In this case the compare function compares two integers.
Related
I have the following code to create a sorted suffix array but there is simply no output. I run the program and it halts for 1-2secs and then exits.
The code is based off the c++ answer on the following website: https://www.geeksforgeeks.org/suffix-array-set-1-introduction/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
struct suffix
{
int index;
char *suff;
};
int cmp(const void *a, const void *b)
{
const struct suffix *a1 = a;
const struct suffix *b1 = b;
return strcmp(a1->suff, b1->suff) < 0? 1 : 0;
}
int *buildSuffixArray(char *txt, int n)
{
struct suffix suffixes[n];
for (int i = 0; i < n; i++)
{
suffixes[i].index = i;
suffixes[i].suff = (txt+i);
}
qsort(suffixes, n, sizeof(int), cmp);
int *suffixArr = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
suffixArr[i] = suffixes[i].index;
}
return suffixArr;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d", arr[i]);
}
printf("\n");
}
int main()
{
char txt[] = "banana";
int n = strlen(txt);
int *suffixArr = buildSuffixArray(txt, n);
printf("following is suffix array for %s\n", txt);
printArr(suffixArr, n);
return 0;
}
Since there is no output, I assume that the problem is within the 'buildSuffixArray' function, specifically with qsort. I have tried fixing it but had no luck. Any help would be appreciated.
Summarizing the comments in the question from Weather Vane and Jonathan Leffler:
OP is passing the wrong element size to qsort(). qsort(suffixes, n, sizeof(int), cmp); should be qsort(suffixes, n, sizeof suffixes[0], cmp);. (Weather Vane).
The cmp function must return a negative value if the first argument sorts before the second argument, zero if they sort equal, or a positive value if the first argument sorts after the second argument. OP's cmp function returns 1 if the first argument is less than the second argument, otherwise 0. This will screw up any sorting by qsort(). (Jonathan Leffler)
It appears that the cmp function written by OP was based on the C++ code from Suffix Array | Set 1 (Introduction). In particular, OP's return strcmp(a1->suff, b1->suff) < 0? 1 : 0; is based on the similar return strcmp(a.suff, b.suff) < 0? 1 : 0; in the C++ code. The problem is that the C++ code uses std::sort(), not qsort() and the rules for the return value of the comparison functions are different.
As Jonathan Leffler points out, it would be sufficient for OP's cmp function to return the value from strcmp() directly:
return strcmp(a->suff, b->suff);
OP's printArr() function prints the integers in the array with no separation between each number. The correction is trivial.
Hello guys i have a situation here am trying to sort out numbers in C language but i seem to struggle to put a sort function can you please help me with this following souce code that prints out number and supose to sort them but i cant...please help:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num1 = 8, num2 = 6, num3 = 2, num4 = 4, num5 = 1;
printf("%d %d %d %d %d", num1, num2, num3, num4, num5);
// qsort(); THIS IS WHAT I STRUGGLE WITH AT THE MOMENT
return 0;
} // THIS CODE PRINTS OUT NUMBERS BUT ARE NOT SORTED...SO I NEED TO SORT THEM PLEASE
// YOUR HELP WILL BE MUCH APPRECIATED
// I NEED TO KNOW HOW TO USE THE SORT(qsort) FUNCTION
qsort() does one thing and it does it exceptionally well, it sorts arrays, and does so very efficiently. As noted in the comments, before you can use qsort() you will need to collect your values in an array rather than separate variables. Once you have an array, using qsort() is trivial, your only responsibility using qsort is to write the compare() function.
New users of qsort() usually have their eyes roll back in their heads when they see the declaration for the function:
int compare (const void *a, const void *b) { ... }
It's actually quite simple. a and b are simply pointers to elements of the array to compare. Since qsort() can handle any type array, the parameter type are void pointers. If you have an array of int, a and b are just pointers int (e.g. int*). You simply need to write your compare function to cast a and b to int* and dereference to compare the int values with each other.
The return of compare() is either less than zero (a sorts before b), zero (a and b are equal) or greater than zero (b sorts before a). So a niave compare() can be as simple as:
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return x - y;
}
However, there is always a potential for x - y to overflow with a large negative x and large y or large x and large negative y. So you generally try and use the differnce between two comparisons to eliminate the potential for overflow, e.g.
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return (x > y) - (x < y);
}
Now if you take any value of a and b the return will either be -1, 0 or 1 providing the sort information for qsort() without chance of overflow.
A short example using your values could be written as:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return (x > y) - (x < y);
}
void prn_arr (int *arr, size_t nmemb)
{
for (size_t i = 0; i < nmemb; i++)
printf (i ? ", %d" : "%d", arr[i]);
putchar ('\n');
}
int main()
{
int num[] = {8, 6, 2, 4, 1};
size_t nmemb = sizeof num / sizeof *num;
puts ("array before sort:\n");
prn_arr (num, nmemb);
qsort (num, nmemb, sizeof *num, compare);
puts ("\narray after sort:\n");
prn_arr (num, nmemb);
}
Example Use/Output
$ ./bin/qsortnum
array before sort:
8, 6, 2, 4, 1
array after sort:
1, 2, 4, 6, 8
Look things over and let me know if you have further questions.
Is there any library function available in C standard library to do sort?
qsort() is the function you're looking for. You call it with a pointer to your array of data, the number of elements in that array, the size of each element and a comparison function.
It does its magic and your array is sorted in-place. An example follows:
#include <stdio.h>
#include <stdlib.h>
int comp (const void * elem1, const void * elem2)
{
int f = *((int*)elem1);
int s = *((int*)elem2);
if (f > s) return 1;
if (f < s) return -1;
return 0;
}
int main(int argc, char* argv[])
{
int x[] = {4,5,2,3,1,0,9,8,6,7};
qsort (x, sizeof(x)/sizeof(*x), sizeof(*x), comp);
for (int i = 0 ; i < 10 ; i++)
printf ("%d ", x[i]);
return 0;
}
C/C++ standard library <stdlib.h> contains qsort function.
This is not the best quick sort implementation in the world but it fast enough and VERY
EASY to be used... the formal syntax of qsort is:
qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);
The only thing that you need to implement is the compare_function, which takes in two
arguments of type "const void", which can be cast to appropriate data structure, and then
return one of these three values:
negative, if a should be before b
0, if a equal to b
positive, if a should be after b
1. Comparing a list of integers:
simply cast a and b to integers
if x < y,x-y is negative, x == y, x-y = 0, x > y, x-y is positive
x-y is a shortcut way to do it :)
reverse *x - *y to *y - *x for sorting in decreasing/reverse order
int compare_function(const void *a,const void *b) {
int *x = (int *) a;
int *y = (int *) b;
return *x - *y;
}
2. Comparing a list of strings:
For comparing string, you need strcmp function inside <string.h> lib.
strcmp will by default return -ve,0,ve appropriately... to sort in reverse order, just reverse the sign returned by strcmp
#include <string.h>
int compare_function(const void *a,const void *b) {
return (strcmp((char *)a,(char *)b));
}
3. Comparing floating point numbers:
int compare_function(const void *a,const void *b) {
double *x = (double *) a;
double *y = (double *) b;
// return *x - *y; // this is WRONG...
if (*x < *y) return -1;
else if (*x > *y) return 1; return 0;
}
4. Comparing records based on a key:
Sometimes you need to sort a more complex stuffs, such as record. Here is the simplest
way to do it using qsort library.
typedef struct {
int key;
double value;
} the_record;
int compare_function(const void *a,const void *b) {
the_record *x = (the_record *) a;
the_record *y = (the_record *) b;
return x->key - y->key;
}
For sure: qsort() is an implementation of a sort (not necessarily quicksort as its name might suggest).
Try man 3 qsort or have a read at http://linux.die.net/man/3/qsort
While not in the standard library exactly, https://github.com/swenson/sort has just two header files you can include to get access to a wide range of incredibly fast sorting routings, like so:
#define SORT_NAME int64
#define SORT_TYPE int64_t
#define SORT_CMP(x, y) ((x) - (y))
#include "sort.h"
/* You now have access to int64_quick_sort, int64_tim_sort, etc., e.g., */
int64_quick_sort(arr, 128); /* Assumes you have some int *arr or int arr[128]; */
This should be at least twice as fast as the standard library qsort, since it doesn't use function pointers, and has many other sorting algorithm options to choose from.
It's in C89, so should work in basically every C compiler.
try qsort in stdlib.h.
I think you are looking for qsort.
qsort function is the implementation of quicksort algorithm found in stdlib.h in C/C++.
Here is the syntax to call qsort function:
void qsort(void *base, size_t nmemb, size_t size,int (*compar)(const void *, const void *));
List of arguments:
base: pointer to the first element or base address of the array
nmemb: number of elements in the array
size: size in bytes of each element
compar: a function that compares two elements
Here is a code example which uses qsort to sort an array:
#include <stdio.h>
#include <stdlib.h>
int arr[] = { 33, 12, 6, 2, 76 };
// compare function, compares two elements
int compare (const void * num1, const void * num2) {
if(*(int*)num1 > *(int*)num2)
return 1;
else
return -1;
}
int main () {
int i;
printf("Before sorting the array: \n");
for( i = 0 ; i < 5; i++ ) {
printf("%d ", arr[i]);
}
// calling qsort
qsort(arr, 5, sizeof(int), compare);
printf("\nAfter sorting the array: \n");
for( i = 0 ; i < 5; i++ ) {
printf("%d ", arr[i]);
}
return 0;
}
You can type man 3 qsort in Linux/Mac terminal to get a detailed info about qsort.
Link to qsort man page
Use qsort() in <stdlib.h>.
#paxdiablo
The qsort() function conforms to ISO/IEC 9899:1990 (``ISO C90'').
There are several C sorting functions available in stdlib.h. You can do man 3 qsort on a unix machine to get a listing of them but they include:
heapsort
quicksort
mergesort
GNU qsort source in stdlib shows that it is quicksort.
Suppose I have the following array:
int A[5]={2,3,5,4,1};
In this array, each of the index represents a player. For example:
A[0]=player 0
A[1]=player 1
.....
I want to sort the array in descending order like this:
A[5]={5,4,3,2,1};
and also I want to trace the previous index of the players so that I can write the sorted array like this:
{player 2, player 4, player 1, player 0,player 4}
In a word, I want to trace the original index. I have written a program in C using qsort to arrange the elements in descending order.
#include <stdio.h>
#include <stdlib.h>
int A[] = {2,3,5,4,1};
int compare (const void * a, const void * b)
{
return ( *(int*)b - *(int*)a );
}
int main ()
{
int n;
qsort (A, 5, sizeof(int), compare);
for (n=0; n<5; n++)
printf ("%d ",A[n]);
return 0;
}
Is is possible to trace the original index also using this qsort?
It is a common requirement. A possible way is to replace the array of ints with and array of 2 element structures:
struct PlayerScore {
int playerId;
int score;
}
Your code could become:
#include <stdio.h>
#include <stdlib.h>
int A[] = {2,3,5,4,1};
#define N sizeof(A)/sizeof(A[0])
struct PlayerScore {
int playerId;
int score;
};
int compare (const void * a, const void * b)
{
return ( (*(struct PlayerScore*)b).score - (*(struct PlayerScore*)a).score );
}
int main ()
{
int n;
struct PlayerScore ps[N];
for(n=0;n<N; n++) {
ps[n].playerId = n;
ps[n].score = A[n];
}
qsort (ps, 5, sizeof(struct PlayerScore), compare);
for (n=0; n<N; n++)
printf ("%d (%d) ",ps[n].score, ps[n].playerId);
return 0;
}
And you finally get:
5 (2) 4 (3) 3 (1) 2 (0) 1 (4)
Your problem has nothing to do with qsort as such, but merely program design.
"In this array, each of the index represents a player" is the problem. You have invented a weird dependency between the array indexes and the contents, even though you want to change the array indexes.
Instead of arrays of int, filled with cryptic "magic numbers", make an array of structs with meaningful data.
It could for example be something like this:
typedef struct
{
// whatever makes sense to store here, names, stats etc
} player_t;
player_t players [] =
{
{0, ...},
{1, ...},
};
Now you can qsort that table based on whatever you like.
Please note that for performance reasons, it might be better to declare an array of pointers-to-struct and then qsort that array. Far less data shuffling for qsort that way.
You need to sort pairs of numbers, for example by storing each piece of information in a struct:
struct player {
int data;
int index;
};
struct player A[] = {{2,0}, {3,1}, {5,2}, {4,3}, {1,4}};
int compare (const void * a, const void * b)
{
return ( ((struct player*)b)->data - ((struct player*)a)->data );
}
int main ()
{
int n;
qsort (A, 5, sizeof(struct player), compare);
for (n=0; n<5; n++)
printf ("data=%d, index=%d\n", A[n].data, A[n].index);
return 0;
}
I am using this compare function to sort an array consisting of long long int nos.
int compare(const void * p1,const void * p2)
{
return (* (long long int * )a-*(long long int * )b);
}
qsort(array,no of elements,sizeof(long long int),compare)
this works fine for small nos but when the array contains nos of the oreder of 10^10 it gives wrong results?
what is the mistake i am making?
The result of compare function must be int. The subtraction of two long long can easily overflow the int type (and it does in your case).
Try comparing the two values explicitly and returning -1, 0 or 1.
explicitly return -1,1 or 0. This is the following code :
int cmpfunc (const void * a, const void * b)
{
if( *(long long int*)a - *(long long int*)b < 0 )
return -1;
if( *(long long int*)a - *(long long int*)b > 0 )
return 1;
return 0;
}
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
qsort (values, 6, sizeof(int), compare);
http://www.cplusplus.com/reference/cstdlib/qsort/