@Alexandru, el objetivo de SO es ser un lugar para todas las preguntas relacionadas con la programación, de cualquier nivel de habilidad. ¿A dónde crees que debería dirigir Google a las personas cuando utilizan esa consulta tuya? Los poderosos quieren que venga aquí : cuando SO es el enlace principal de Google para esa consulta, nuestro trabajo está hecho.
paxdiablo
1
Mi código original era flojo y probablemente muy diferente de lo que hubiera encontrado con una búsqueda en Google. Sin embargo, después de todos los comentarios de la comunidad, tiene un ejemplo de una buena implementación de cómo usar qsort.
repetición el
@paxdiablo: si ese es el caso, también podrían simplemente alojar la documentación estándar de la biblioteca; dudo que esta pregunta agregue algo por encima de la referencia canónica, aquí. Para algunos casos complejos, quizás, pero ¿solo para encontrar una función básica?
Eamon Nerbonne
4
Incluso preguntas como esta contribuyen a la eventual integridad de SO como una base de datos útil para codificadores atascados.
thomaspaulb
7
Además, en muchos casos la gente no sabe qué buscar. Si sabe que c tiene una función de ordenación llamada qsort (), la documentación es de fácil acceso, sin embargo, si no sabe qué buscar, qué recurso debe usar.
repetición el
Respuestas:
120
qsort()es la función que estás buscando. Lo llama con un puntero a su matriz de datos, el número de elementos en esa matriz, el tamaño de cada elemento y una función de comparación.
Hace su magia y su matriz se ordena en el lugar. A continuación se muestra un ejemplo:
#include<stdio.h>#include<stdlib.h>int comp (constvoid* elem1,constvoid* elem2){int f =*((int*)elem1);int s =*((int*)elem2);if(f > s)return1;if(f < s)return-1;return0;}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]);return0;}
Realmente debería usar sizeof (* x) en caso de que alguna vez cambie el tipo en el futuro, pero +1 para proporcionar una muestra.
paxdiablo
12
En el caso general, un intento de comparar entradas restando una de otra resultará en un desbordamiento. Es mejor alejarse de ese mal hábito desde el principio. Usereturn (f > s) - (f < s);
LAn
4
Bien, cambiado según la mayoría de las sugerencias. Dibujo la línea, @ChrisL, en la necesidad de size_t ya que mis matrices nunca llegan a ser tan grandes :-) Y, @AndreyT, aunque ese truco es inteligente, prefiero que mi código sea legible :-)
paxdiablo
2
@paxdiablo: Ese "truco" es un modismo bien establecido. Cualquier programador que se precie lo reconoce de inmediato. No tiene efectos negativos en la legibilidad.
el AnT
2
@JAamish ISO C99 Norma N1256, en "7.20.5.2 La qsortfunción" Punto 4 "Si dos elementos se comparan como iguales, su orden en la matriz ordenada resultante no se especifica."
12431234123412341234123
60
La biblioteca estándar de C / C ++ <stdlib.h>contiene qsortfunción.
Esta no es la mejor implementación de ordenación rápida del mundo, pero es lo suficientemente rápida y MUY FÁCIL de usar ... la sintaxis formal de qsort es:
Lo único que necesita implementar es la función compare_function, que toma dos argumentos de tipo "const void", que se pueden convertir a la estructura de datos adecuada y luego devolver uno de estos tres valores:
negativo, si a debe ser antes de b
0, si a es igual ab
positivo, si a debería ser después de b
1. Comparando una lista de números enteros :
simplemente echar a y b números enteros si x < y, x-yes negativo, x == y, x-y = 0, x > y, x-yes positivo
x-yes una forma de acceso directo para hacerlo :) revertir *x - *ya *y - *xpara la clasificación en la disminución / orden inverso
int compare_function(constvoid*a,constvoid*b){int*x =(int*) a;int*y =(int*) b;return*x -*y;}
2. Comparación de una lista de cadenas :
Para comparar cadenas, necesita una strcmpfunción dentro de <string.h>lib.
strcmppor defecto devolverá -ve, 0, ve apropiadamente ... para ordenar en orden inverso, simplemente invierta el signo devuelto por strcmp
Una respuesta bastante buena, pero la explicación del valor de retorno de la función de comparación es al revés. Además, en algunos de los ejemplos, está haciendo el truco xy, que puede dar resultados erróneos (y es menos obvio que una simple comparación).
Adrian McCarthy
Bueno, en lo que a mí respecta ahora ... esto funciona para todos los concursos;)
whacko__Cracko
5
El truco xy no funciona si la diferencia entre xey es mayor que el int representable más grande. Por lo tanto, está bien cuando se comparan dos números positivos, pero fallará al comparar, por ejemplo, INT_MAX y -10. Sin embargo, voté a favor porque me gustan todos los ejemplos de clasificación de tipos muy diferentes.
Douglas
2
Además del problema de desbordamiento tanto en el comparador de enteros como en el comparador de teclas, la función de comparación de cadenas es incorrecta. Al ordenar una matriz de int, los valores pasados al comparador se int *disfrazan como void *. char *Por lo tanto, al ordenar una matriz de , los valores pasados al comparador se char **disfrazan como void *. Por lo tanto, el código correcto debe ser: int compare_function(const void *a,const void *b) { return (strcmp(*(char **)a, *(char **)b)); }.
Jonathan Leffler
1
Para las comparaciones de enteros resistentes al desbordamiento, considere if (x > y) return +1; else if (x < y) return -1; else return 0;, o si desea una expresión simple, entonces return (x > y) - (x < y);. Esto siempre evalúa dos comparaciones en el nivel C, pero el optimizador podría evitarlo. La resta no funciona con valores sin firmar. La primera versión funciona bien cuando se trata de una serie de comparaciones: primero se comparan 2 miembros enteros de una estructura, y si son iguales, luego dos dobles, luego dos cadenas, etc. Hay más de una forma de hacerlo, en C y Perl.
Jonathan Leffler
9
Seguro: qsort()es una implementación de cierto tipo (no necesariamente una clasificación rápida como su nombre sugiere).
Si bien no está exactamente en la biblioteca estándar, https://github.com/swenson/sort tiene solo dos archivos de encabezado que puede incluir para obtener acceso a una amplia gama de enrutamientos de clasificación increíblemente rápidos, así:
#define SORT_NAME int64 #define SORT_TYPE int64_t #define SORT_CMP ( x , y ) (( x ) - ( y )) #include "sort.h" / * Ahora tiene acceso a int64_quick_sort, int64_tim_sort, etc., por ejemplo, * /
int64_quick_sort ( arreglo , 128 ); / * Asume que tienes int * arr o int arr [128]; * /
Esto debería ser al menos dos veces más rápido que la biblioteca estándar qsort, ya que no usa punteros de función y tiene muchas otras opciones de algoritmos de clasificación para elegir.
Está en C89, por lo que debería funcionar básicamente en todos los compiladores de C.
Hay varias funciones de clasificación C disponibles en stdlib.h. Puede hacerlo man 3 qsorten una máquina Unix para obtener una lista de ellos, pero incluyen:
Respuestas:
qsort()
es la función que estás buscando. Lo llama con un puntero a su matriz de datos, el número de elementos en esa matriz, el tamaño de cada elemento y una función de comparación.Hace su magia y su matriz se ordena en el lugar. A continuación se muestra un ejemplo:
fuente
return (f > s) - (f < s);
qsort
función" Punto 4 "Si dos elementos se comparan como iguales, su orden en la matriz ordenada resultante no se especifica."La biblioteca estándar de C / C ++
<stdlib.h>
contieneqsort
función.Esta no es la mejor implementación de ordenación rápida del mundo, pero es lo suficientemente rápida y MUY FÁCIL de usar ... la sintaxis formal de qsort es:
Lo único que necesita implementar es la función compare_function, que toma dos argumentos de tipo "const void", que se pueden convertir a la estructura de datos adecuada y luego devolver uno de estos tres valores:
1. Comparando una lista de números enteros :
simplemente echar a y b números enteros si
x < y
,x-y
es negativo,x == y
,x-y = 0
,x > y
,x-y
es positivox-y
es una forma de acceso directo para hacerlo :) revertir*x - *y
a*y - *x
para la clasificación en la disminución / orden inverso2. Comparación de una lista de cadenas :
Para comparar cadenas, necesita una
strcmp
función dentro de<string.h>
lib.strcmp
por defecto devolverá -ve, 0, ve apropiadamente ... para ordenar en orden inverso, simplemente invierta el signo devuelto por strcmp3. Comparación de números de coma flotante :
4. Comparación de registros basados en una clave :
A veces necesita ordenar cosas más complejas, como grabar. Esta es la forma más sencilla de hacerlo utilizando la
qsort
biblioteca.fuente
int
, los valores pasados al comparador seint *
disfrazan comovoid *
.char *
Por lo tanto, al ordenar una matriz de , los valores pasados al comparador sechar **
disfrazan comovoid *
. Por lo tanto, el código correcto debe ser:int compare_function(const void *a,const void *b) { return (strcmp(*(char **)a, *(char **)b)); }
.if (x > y) return +1; else if (x < y) return -1; else return 0;
, o si desea una expresión simple, entoncesreturn (x > y) - (x < y);
. Esto siempre evalúa dos comparaciones en el nivel C, pero el optimizador podría evitarlo. La resta no funciona con valores sin firmar. La primera versión funciona bien cuando se trata de una serie de comparaciones: primero se comparan 2 miembros enteros de una estructura, y si son iguales, luego dos dobles, luego dos cadenas, etc. Hay más de una forma de hacerlo, en C y Perl.Seguro:
qsort()
es una implementación de cierto tipo (no necesariamente una clasificación rápida como su nombre sugiere).Pruebe man 3 qsort o lea en http://linux.die.net/man/3/qsort
fuente
qsort
no tiene que implementarse con Quicksort.Si bien no está exactamente en la biblioteca estándar, https://github.com/swenson/sort tiene solo dos archivos de encabezado que puede incluir para obtener acceso a una amplia gama de enrutamientos de clasificación increíblemente rápidos, así:
Esto debería ser al menos dos veces más rápido que la biblioteca estándar
qsort
, ya que no usa punteros de función y tiene muchas otras opciones de algoritmos de clasificación para elegir.Está en C89, por lo que debería funcionar básicamente en todos los compiladores de C.
fuente
prueba
qsort
en stdlib.h.fuente
Usar
qsort()
en<stdlib.h>
.@paxdiablo La
qsort()
función cumple con ISO / IEC 9899: 1990 (`` ISO C90 '').fuente
Hay varias funciones de clasificación C disponibles en
stdlib.h
. Puede hacerloman 3 qsort
en una máquina Unix para obtener una lista de ellos, pero incluyen:fuente