C library berfungsi untuk melakukan sort


97

Apakah ada fungsi perpustakaan yang tersedia di perpustakaan standar C untuk melakukan penyortiran?


21
@Alexandru, inti dari SO adalah menjadi tempat untuk semua pertanyaan yang berhubungan dengan pemrograman, dari tingkat keahlian apa pun . Menurut Anda, ke mana Google harus mengarahkan orang ketika mereka menggunakan kueri Anda itu? Kekuatan yang diinginkan datang ke sini - ketika SO adalah tautan Google teratas untuk kueri itu, tugas kita selesai.
paxdiablo

1
Kode asli saya malas dan mungkin jauh berbeda dari apa yang Anda temukan dengan pencarian Google. Namun setelah semua masukan dari komunitas Anda memiliki contoh implementasi yang baik tentang bagaimana menggunakan qsort.
Tayangkan ulang

@paxdiablo: jika itu masalahnya, mereka mungkin juga hanya menghosting dokumentasi lib standar - Saya ragu pertanyaan ini akan menambahkan apa pun di atas referensi kanonik itu, di sini. Untuk beberapa kasus yang kompleks, mungkin - tetapi hanya untuk menemukan fungsi dasar?
Eamon Nerbonne

4
Bahkan pertanyaan seperti ini berkontribusi pada kelengkapan SO sebagai database yang berguna untuk pembuat kode yang macet.
thomaspaulb

7
Juga dalam banyak kasus orang tidak tahu apa yang harus dicari. Jika Anda tahu bahwa c memiliki fungsi sortir bernama qsort () dokumentasi mudah diakses, namun jika Anda tidak tahu apa yang harus dicari sumber daya apa yang harus digunakan.
Tayangkan ulang

Jawaban:


120

qsort()adalah fungsi yang Anda cari. Anda menyebutnya dengan penunjuk ke larik data Anda, jumlah elemen dalam larik itu, ukuran setiap elemen, dan fungsi perbandingan.

Itu melakukan keajaibannya dan array Anda diurutkan di tempat. Contohnya sebagai berikut:

#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;
}

3
Anda benar-benar harus menggunakan sizeof (* x) jika Anda pernah mengubah jenis di masa mendatang tetapi +1 untuk memberikan sampel.
paxdiablo

12
Dalam kasus umum, upaya untuk membandingkan int dengan mengurangi satu sama lain akan menghasilkan luapan. Lebih baik menjauhi kebiasaan buruk itu sejak awal. Gunakanreturn (f > s) - (f < s);
AnT

4
Oke, berubah sesuai sebagian besar saran. Saya menarik garis, @ChrisL, membutuhkan size_t karena array saya tidak pernah sebesar itu :-) Dan, @AndreyT, meskipun pandai hack itu, saya lebih suka kode saya dapat dibaca :-)
paxdiablo

2
@paxdiablo: "Hack" itu adalah ungkapan yang sudah mapan. Setiap programmer yang berharga akan segera mengenalinya. Ini tidak memiliki efek negatif pada keterbacaan.
AnT

2
@ JAamish ISO C99 Standard N1256, di "7.20.5.2 qsortFungsi" Poin 4 "Jika dua elemen dibandingkan sebagai sama, urutannya dalam larik terurut yang dihasilkan tidak ditentukan."
12431234123412341234123

60

Pustaka standar C / C ++ <stdlib.h>berisi qsortfungsi.

Ini bukan implementasi pengurutan cepat terbaik di dunia tetapi cukup cepat dan SANGAT MUDAH digunakan ... sintaks formal qsort adalah:

qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);

Satu-satunya hal yang perlu Anda terapkan adalah bandingkan_fungsi, yang menggunakan dua argumen berjenis "const void", yang dapat ditransmisikan ke struktur data yang sesuai, lalu mengembalikan salah satu dari tiga nilai berikut:

  • negatif, jika a harus sebelum b
  • 0, jika a sama dengan b
  • positif, jika a harus setelah b

1. Membandingkan daftar bilangan bulat :

hanya melemparkan a dan b untuk bilangan bulat jika x < y, x-ynegatif, x == y, x-y = 0, x > y, x-ypositif x-yadalah cara pintas untuk melakukannya :) mundur *x - *yuntuk *y - *xuntuk menyortir dalam mengurangi / urutan terbalik

int compare_function(const void *a,const void *b) {
int *x = (int *) a;
int *y = (int *) b;
return *x - *y;
}

2. Membandingkan daftar string :

Untuk membandingkan string, Anda membutuhkan strcmpfungsi di dalam <string.h>lib. strcmpakan secara default mengembalikan -ve, 0, ve dengan tepat ... untuk mengurutkan dalam urutan terbalik, cukup balikkan tanda yang dikembalikan oleh strcmp

#include <string.h>
int compare_function(const void *a,const void *b) {
return (strcmp((char *)a,(char *)b));
}

3. Membandingkan angka floating point :

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. Membandingkan catatan berdasarkan kunci :

Terkadang Anda perlu mengurutkan barang yang lebih kompleks, seperti catatan. Berikut adalah cara termudah untuk melakukannya menggunakan qsortlibrary.

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;
}

2
Jawaban yang cukup bagus, tetapi penjelasan nilai kembalian dari fungsi bandingkan terbalik. Juga, dalam beberapa contoh, Anda melakukan trik xy, yang dapat memberikan hasil yang salah (dan kurang jelas dibandingkan dengan perbandingan sederhana).
Adrian McCarthy

Sejauh yang saya ketahui sekarang .. ini berfungsi untuk setiap kontes;)
whacko__Cracko

5
Trik xy tidak berfungsi jika selisih antara x dan y lebih besar dari int terwakili terbesar. Jadi tidak masalah jika membandingkan dua bilangan positif, tetapi akan gagal membandingkan, misalnya INT_MAX dan -10. Suara positif karena saya suka semua contoh penyortiran jenis yang sangat berbeda.
Douglas

2
Selain masalah luapan di kedua komparator integer dan fungsi komparator kunci, fungsi perbandingan string salah. Saat mengurutkan array int, nilai yang diteruskan ke pembanding keduanya int *disamarkan sebagai void *. char *Oleh karena itu, saat menyortir array , nilai yang diteruskan ke pembanding keduanya char **disamarkan sebagaivoid * . Oleh karena itu, kode yang benar harus: int compare_function(const void *a,const void *b) { return (strcmp(*(char **)a, *(char **)b)); }.
Jonathan Leffler

1
Untuk perbandingan integer yang tahan luapan, pertimbangkan if (x > y) return +1; else if (x < y) return -1; else return 0;, atau jika Anda menginginkan ekspresi sederhana, maka return (x > y) - (x < y);. Ini selalu mengevaluasi dua perbandingan pada tingkat C, tetapi pengoptimal mungkin dapat menghindarinya. Pengurangan tidak bekerja pada nilai yang tidak bertanda tangan. Versi pertama berfungsi dengan baik ketika Anda berurusan dengan serangkaian perbandingan - membandingkan 2 anggota integer struktur terlebih dahulu, dan jika mereka sama, lalu dua ganda, lalu dua string, dll. Ada lebih dari satu cara untuk melakukannya, di C serta Perl.
Jonathan Leffler


6

Meskipun tidak persis di perpustakaan standar, https://github.com/swenson/sort hanya memiliki dua file header yang dapat Anda sertakan untuk mendapatkan akses ke berbagai perutean penyortiran yang sangat cepat, seperti:

#define SORT_NAME int64 #define SORT_TYPE int64_t #define SORT_CMP ( x , y ) (( x ) - ( y )) #include "sort.h" / * Sekarang Anda memiliki akses ke int64_quick_sort, int64_tim_sort, dll., misalnya, * / 
int64_quick_sort ( arr , 128 ); / * Asumsikan Anda memiliki beberapa int * arr atau int arr [128]; * /

   
 
  

Ini harus setidaknya dua kali lebih cepat dari perpustakaan standar qsort , karena tidak menggunakan penunjuk fungsi, dan memiliki banyak opsi algoritma pengurutan lainnya untuk dipilih.

Ada di C89, jadi pada dasarnya harus bekerja di setiap kompiler C.



4

Gunakan qsort()dalam <stdlib.h>.

@paxdiablo qsort()Fungsi tersebut sesuai dengan ISO / IEC 9899: 1990 (`` ISO C90 '').


3

Ada beberapa fungsi penyortiran C yang tersedia di stdlib.h. Anda dapat melakukannya man 3 qsortdi mesin unix untuk mendapatkan daftar mereka tetapi itu termasuk:

  • heapsort
  • quicksort
  • mergesort

7
heapsort dan mergesort tidak dalam standar.
Technowise

3
Begitu pula quicksort. Standar tidak mengamanatkan algoritma mana yang digunakan.
paxdiablo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.