qsort - aliohjelman vikana on löysä tyypitys ja erityisesti se, ettei sille voi viedä parametrinä lisätietoa lajittelusta. STL:stä löytyy joukko algoritmeja, joita voidaan soveltaa STL:n omien tietorakenteiden lisäksi myös tavallisille taulukoille.
Edellisessä esimerkissä qsort-rivi voitaisiin korvata rivillä:
sort(x,x+KOKO);
Tällöin ei itse asiassa tarvita edes lajittelufunktiota, koska sort lajittelee oletuksena taulukon nousevaan järjestykseen edellyttäen että taulukon alkioita voidaan verrata < -operaattorilla.
Varsinainen etu sort-algoritmista saadaan, mikäli lajittelujärjestystä halutaan muuttaa tai lajittelufunktiolle halutaan antaa parametrejä. Parametrit pystytään toteuttamaan funktio-olioiden (joskus sanotaan myös funktoreiksi) avulla.
Seuraavassa esimerkissä merkkijonotaulukko lajitellaan ensin nousevaan järjestykseen luottaen string-luokan <-operaattoriin. Sitten taulukko lajitellaan laskevaan järjestykseen oman laskeva-vertailufunktion avulla. Tosin kirjastossa on valmiina funktio-oliot tämänkaltaisiin vertailuihin. Lopuksi en esimerkki, jossa jonot lajitellaan nousevaan järjestykseen jonon toisen kirjaimen perusteella. Tämä voitaisiin vielä tehdä qsort-funktiollakin, mutta jos se, monennenko kirjaimen mukaan lajittelu tehdään, halutaan parametriksi, olisi globaali muuttuja ainoa vaihtoehto qsort-funktiota käytettäessä.
sort-algoritmia (tai esimerkissä stable_sort, säilyttää "samansuuruisten" keskinäisen järjestyksen) kutsuttaessa luodaan tilapäinen (lajittelun ajan elävä) cVertaaPaikka funktio-olio, jonka konstruktorille välitetään lajiteltavan kirjaimen indeksi. Luokkaan määritellyn ()-operaattorin ansiosta luokaa edustavaa oliota voidaan kutsua funktiomaisesti kahdella merkkijojonolla.
// Esimerkki sort-algoritmin käytöstä // Vesa Lappalainen 26.12.2001 #include <iostream> #include <string> #include <algorithm> #include <functional> using std::string; using std::ostream_iterator; using std::cout; class cVertaaPaikka { // Vertailuluokka joka vertaa jonoja paikassa unsigned int paikka; // paikka olevan kirjaimen mukaan public: cVertaaPaikka(unsigned int ipaikka) { paikka = ipaikka; } // Jos on cVertaaPaikka vertaa(1); niin seuraavaa operaattoria voi kutsua // "funktiomaisesti": if ( vertaa(jono1,jono2) ) ... bool operator() (const string &a, const string &b) const { if ( ( a.length() <= paikka ) || ( b.length() <= paikka ) ) return a.length() < b.length(); return a[paikka] < b[paikka]; } }; bool laskeva(const string &a,const string &b) { return b < a; } void tulosta(const string nimet[],int lkm) { copy(nimet,nimet+lkm,ostream_iterator<string>(cout," ")); cout << "\n"; } int main(void) { const int lkm = 6; string nimet[lkm] = { "Aku","Mikki","Roope","Hannu","Pelle","Sepe" }; // Nouseva: Aku Hannu Mikki Pelle Roope Sepe sort(nimet,nimet+lkm); tulosta(nimet,lkm); // Laskeva: Sepe Roope Pelle Mikki Hannu Aku sort(nimet,nimet+lkm,laskeva); tulosta(nimet,lkm); sort(nimet,nimet+lkm,std::greater<string>()); tulosta(nimet,lkm); // Toisen kirjaimen mukaan: Hannu Sepe Pelle Mikki Aku Roope stable_sort(nimet,nimet+lkm,cVertaaPaikka(1)); tulosta(nimet,lkm); // HUOM! Sepe oli ennen Pelleä, koska stabiili lajittelu return 0; }