@Alexandru, celem SO ma być miejsce na wszystkie pytania związane z programowaniem, na dowolnym poziomie umiejętności. Jak myślisz, dokąd Google powinien kierować ludzi, gdy używają tego zapytania? Potęgi, które chcą, żeby tu dotarły - kiedy SO jest górnym linkiem Google dla tego zapytania, nasza praca jest skończona.
paxdiablo
1
Mój oryginalny kod był leniwy i prawdopodobnie znacznie różnił się od tego, co można znaleźć w wyszukiwarce Google. Jednak po wszystkich opiniach społeczności masz przykład dobrej implementacji sposobu korzystania z qsort.
powtórz
@paxdiablo: jeśli tak jest, równie dobrze mogą po prostu hostować standardową dokumentację lib - wątpię, aby to pytanie dodało cokolwiek powyżej tego odniesienia kanonicznego. Może w niektórych skomplikowanych przypadkach - ale tylko po to, aby znaleźć podstawową funkcję?
Eamon Nerbonne,
4
Nawet takie pytania przyczyniają się do ostatecznej kompletności SO jako pomocnej bazy danych dla zablokowanych programistów.
mały zielony
7
Również w wielu przypadkach ludzie nie wiedzą, czego szukać. Jeśli wiesz, że c ma funkcję sortowania o nazwie qsort (), dokumentacja jest łatwo dostępna, jednak jeśli nie wiesz, czego szukać, jakiego zasobu należy użyć.
powtórz
Odpowiedzi:
120
qsort()to funkcja, której szukasz. Wołasz to za pomocą wskaźnika do swojej tablicy danych, liczby elementów w tej tablicy, rozmiaru każdego elementu i funkcji porównania.
Robi swoje, a twoja tablica jest sortowana w miejscu. Oto przykład:
#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;}
Naprawdę powinieneś użyć sizeof (* x) na wypadek, gdybyś kiedykolwiek zmienił typ w przyszłości, ale +1 za dostarczenie próbki.
paxdiablo
12
W ogólnym przypadku próba porównania wartości typu int przez odjęcie jednej od drugiej spowoduje przepełnienie. Lepiej od samego początku trzymać się z daleka od tego złego nawyku. Do wykorzystaniareturn (f > s) - (f < s);
AnT,
4
OK, zmienione zgodnie z większością sugestii. Rysuję linię, @ChrisL, potrzebując size_t, ponieważ moje tablice nigdy nie są tak duże :-) I @AndreyT, chociaż ten hack jest sprytny, wolę, aby mój kod był czytelny :-)
paxdiablo
2
@paxdiablo: Ten „hack” to dobrze znany idiom. Każdy programista warty swojej soli rozpoznaje to natychmiast. Nie ma to negatywnego wpływu na czytelność.
AnT
2
@JAamish ISO C99 Standard N1256, w "7.20.5.2 qsortFunkcja" Punkt 4 "Jeśli dwa elementy są porównywane jako równe, ich kolejność w wynikowej posortowanej tablicy jest nieokreślona."
12431234123412341234123
61
Biblioteka standardowa C / C ++ <stdlib.h>zawiera qsortfunkcję.
To nie jest najlepsza implementacja szybkiego sortowania na świecie, ale jest wystarczająco szybka i BARDZO ŁATWA w użyciu ... formalna składnia qsort to:
Jedyne, co musisz zaimplementować, to funkcja compare_function, która przyjmuje dwa argumenty typu „const void”, które można rzutować na odpowiednią strukturę danych, a następnie zwrócić jedną z tych trzech wartości:
ujemna, jeśli a powinno być przed b
0, jeśli a równa się b
pozytywny, jeśli a powinno być po b
1. Porównanie listy liczb całkowitych :
po prostu rzucić A i B do liczb całkowitych razie x < y, x-yjest negatywna, x == y, x-y = 0, x > y, x-yjest dodatnia
x-yto sposób skrót zrobić :) to odwrócić *x - *ysię *y - *xna sortowanie malejące / odwrotnej kolejności
int compare_function(constvoid*a,constvoid*b){int*x =(int*) a;int*y =(int*) b;return*x -*y;}
2. Porównanie listy ciągów :
Aby porównać łańcuch, potrzebujesz strcmpfunkcji w <string.h>bibliotece.
strcmpdomyślnie zwróci odpowiednio -ve, 0, ve ... aby posortować w odwrotnej kolejności, po prostu odwróć znak zwracany przez strcmp
Całkiem dobra odpowiedź, ale wyjaśnienie wartości zwracanej przez funkcję porównującą jest wstecz. Ponadto w niektórych przykładach wykonujesz sztuczkę xy, która może dać błędne wyniki (i jest mniej oczywista niż proste porównanie).
Adrian McCarthy
Cóż, o ile mi
wiadomo
5
Sztuczka xy nie działa, jeśli różnica między x i y jest większa niż największa reprezentowalna liczba int. Więc jest w porządku podczas porównywania dwóch liczb dodatnich, ale nie powiedzie się porównanie, np. INT_MAX i -10. Głosowałem za to, ponieważ lubię wszystkie przykłady sortowania bardzo różnych typów.
Douglas
2
Oprócz problemu przepełnienia zarówno w funkcji komparatora liczb całkowitych, jak i funkcji komparatora kluczy, funkcja porównywania ciągów jest niepoprawna. Podczas sortowania tablicy intwartości przekazywane do komparatora są int *zamaskowane jako void *. char *Dlatego podczas sortowania tablicy wartości przekazywane do komparatora są char **zamaskowane jako void *. Dlatego prawidłowy kod musi być: int compare_function(const void *a,const void *b) { return (strcmp(*(char **)a, *(char **)b)); }.
Jonathan Leffler
1
W przypadku porównań liczb całkowitych, które są odporne na przepełnienia, rozważ if (x > y) return +1; else if (x < y) return -1; else return 0;, lub jeśli potrzebujesz prostego wyrażenia, wtedy return (x > y) - (x < y);. To zawsze ocenia dwa porównania na poziomie C, ale optymalizator może być w stanie tego uniknąć. Odejmowanie nie działa na wartościach bez znaku. Pierwsza wersja działa dobrze, gdy masz do czynienia z serią porównań - najpierw porównując 2 całkowite elementy struktury, a jeśli są równe, to dwa podwójne, potem dwa ciągi itd. Jest więcej niż jeden sposób, aby to zrobić, w języku C oraz Perl.
Jonathan Leffler
9
Na pewno: qsort()to swego rodzaju implementacja (niekoniecznie quicksort, jak sugeruje nazwa).
qsortnie musi być implementowane za pomocą Quicksort.
James McNellis
6
Chociaż nie jest to dokładnie w standardowej bibliotece, https://github.com/swenson/sort ma tylko dwa pliki nagłówkowe, które możesz dołączyć, aby uzyskać dostęp do szerokiej gamy niesamowicie szybkich tras sortowania, takich jak:
#define SORT_NAME int64 #define SORT_TYPE int64_t #define SORT_CMP ( x , y ) (( x ) - ( y )) #include "sort.h" / * Masz teraz dostęp do int64_quick_sort, int64_tim_sort itp., np. * /
int64_quick_sort ( arr , 128 ); / * Zakłada, że masz jakieś int * arr lub int arr [128]; * /
Powinna być co najmniej dwa razy szybsza niż standardowa biblioteka qsort, ponieważ nie używa wskaźników funkcji i ma wiele innych opcji algorytmu sortowania do wyboru.
Jest w C89, więc powinien działać w zasadzie w każdym kompilatorze C.
Istnieje kilka sortowania C Funkcje dostępne w stdlib.h. Możesz zrobić man 3 qsortna komputerze z systemem UNIX, aby uzyskać ich listę, ale obejmują one:
Odpowiedzi:
qsort()
to funkcja, której szukasz. Wołasz to za pomocą wskaźnika do swojej tablicy danych, liczby elementów w tej tablicy, rozmiaru każdego elementu i funkcji porównania.Robi swoje, a twoja tablica jest sortowana w miejscu. Oto przykład:
źródło
return (f > s) - (f < s);
qsort
Funkcja" Punkt 4 "Jeśli dwa elementy są porównywane jako równe, ich kolejność w wynikowej posortowanej tablicy jest nieokreślona."Biblioteka standardowa C / C ++
<stdlib.h>
zawieraqsort
funkcję.To nie jest najlepsza implementacja szybkiego sortowania na świecie, ale jest wystarczająco szybka i BARDZO ŁATWA w użyciu ... formalna składnia qsort to:
Jedyne, co musisz zaimplementować, to funkcja compare_function, która przyjmuje dwa argumenty typu „const void”, które można rzutować na odpowiednią strukturę danych, a następnie zwrócić jedną z tych trzech wartości:
1. Porównanie listy liczb całkowitych :
po prostu rzucić A i B do liczb całkowitych razie
x < y
,x-y
jest negatywna,x == y
,x-y = 0
,x > y
,x-y
jest dodatniax-y
to sposób skrót zrobić :) to odwrócić*x - *y
się*y - *x
na sortowanie malejące / odwrotnej kolejności2. Porównanie listy ciągów :
Aby porównać łańcuch, potrzebujesz
strcmp
funkcji w<string.h>
bibliotece.strcmp
domyślnie zwróci odpowiednio -ve, 0, ve ... aby posortować w odwrotnej kolejności, po prostu odwróć znak zwracany przez strcmp3. Porównanie liczb zmiennoprzecinkowych :
4. Porównanie rekordów na podstawie klucza :
Czasami musisz posortować bardziej złożone rzeczy, takie jak nagranie. Oto najprostszy sposób na zrobienie tego za pomocą
qsort
biblioteki.źródło
int
wartości przekazywane do komparatora sąint *
zamaskowane jakovoid *
.char *
Dlatego podczas sortowania tablicy wartości przekazywane do komparatora sąchar **
zamaskowane jakovoid *
. Dlatego prawidłowy kod musi być: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;
, lub jeśli potrzebujesz prostego wyrażenia, wtedyreturn (x > y) - (x < y);
. To zawsze ocenia dwa porównania na poziomie C, ale optymalizator może być w stanie tego uniknąć. Odejmowanie nie działa na wartościach bez znaku. Pierwsza wersja działa dobrze, gdy masz do czynienia z serią porównań - najpierw porównując 2 całkowite elementy struktury, a jeśli są równe, to dwa podwójne, potem dwa ciągi itd. Jest więcej niż jeden sposób, aby to zrobić, w języku C oraz Perl.Na pewno:
qsort()
to swego rodzaju implementacja (niekoniecznie quicksort, jak sugeruje nazwa).Spróbuj man 3 qsort lub przeczytaj go pod adresem http://linux.die.net/man/3/qsort
źródło
qsort
nie musi być implementowane za pomocą Quicksort.Chociaż nie jest to dokładnie w standardowej bibliotece, https://github.com/swenson/sort ma tylko dwa pliki nagłówkowe, które możesz dołączyć, aby uzyskać dostęp do szerokiej gamy niesamowicie szybkich tras sortowania, takich jak:
Powinna być co najmniej dwa razy szybsza niż standardowa biblioteka
qsort
, ponieważ nie używa wskaźników funkcji i ma wiele innych opcji algorytmu sortowania do wyboru.Jest w C89, więc powinien działać w zasadzie w każdym kompilatorze C.
źródło
spróbuj
qsort
w stdlib.h.źródło
Użyj
qsort()
w<stdlib.h>
.@paxdiablo
qsort()
Funkcja jest zgodna z normą ISO / IEC 9899: 1990 (`` ISO C90 '').źródło
Istnieje kilka sortowania C Funkcje dostępne w
stdlib.h
. Możesz zrobićman 3 qsort
na komputerze z systemem UNIX, aby uzyskać ich listę, ale obejmują one:źródło