LearnToCP
Prijavi se
Navigacija
PočetnaRoad-mapaProblemiO Nama
Teorija
Takmičarsko Znanje
Izbor Radnog Okruženja (IDE)Interaktivni ZadaciOutput-only Zadaci
Osnove
Tvoj Prvi ProgramTipovi podataka, Unos i IzlazC++ sintaksaModuloFunkcijeVektoriMatriceVremenska Složenost Algoritma
Sortiranje
SortiranjeSortiranje PrebrojavanjemRadix Sort
Tehnike Optimizacije
Dva PokazivačaZbir brojeva od 1 do nZbir PrefiksaBinarna PretragaPohlepni AlgoritmiFunkcije Binarne PretrageBinarna Pretraga po RešenjuPodeli, pa Vladaj
Binarni Brojevi
Binarni BrojeviBrojevi u koduOperacije nad BitovimaBitmaske
Matematika
Binarno StepenovanjeProsti BrojeviRastavljanje na proste činioceNZD i NZSEratostenovo SitoModifikovano Sito
Strukture Podataka
Niske (Stringovi)StekRedMapeSkupovi (Set)Red sa PrioritetomKorišćenje Proizvoljnih KriterijumaSegmentna StablaFenvikova StablaSparse TabeleDisjunktni SkupoviSqrt Dekompozicija
Kombinatorika
Pravilo SabiranjaPravilo MnoženjaKombinatorni ObjektiPrincip Uključenja Isključenja
Geometrija
Osnove GeometrijeVektoriVektorski i Skalarni ProizvodLinijePoligoniUgloviTačka u PoligonuRastojanja i Tačke PresekaKonveksni OmotačKrugovi
Rekurzija
PokazivačiRekurzijaGenerisanje Kombinatornih Objekata
Dinamičko Programiranje
O DP-uDP problemiDP nad StablimaDP nad Bitmaskama
Teorija Grafova
GrafoviDFS i BFSNajkraći PuteviStablaTopološko SortiranjeDajkstrin AlgoritamMinimalna Razapinjuća StablaAlgoritmi Najkraćih Puteva
Napredna Teorija Grafova
Dvostruka PovezanostJako Povezane KomponenteBipartitni GrafMaksimalni Protok u GrafuFord-Fulkersonov AlgoritamDualnost Protoka i Minimalnog PresekaTeško-Laka DekompozicijaCentroidna Dekompozicija
Napredne Strukture Podataka
2D i 3D Segmentna StablaLenjo PropagiranjeImplicitna Segmentna StablaPerzistentna Segmentna StablaNajbliži Zajednički PredakTrieBalansirana Binarna Stabla PretrageMoov Algoritam

Sortiranje Prebrojavanjem

U ovoj lekciji upoznaćemo se sa posebnom vrstom sortiranja koja radi u vremenskoj složenosti O(n + m)!

Iako je ova tehnika veoma brza, postoji jedno važno ograničenje - radi samo kada sortiramo relativno male nenegativne brojeve
(otprilike brojeve <= 10^5 i >= 0).

Hajde da vidimo zašto.

Teorija

Zamislimo da imamo niz:

a = 4, 5, 6, 3, 1, 7, 3

Glavna ideja je da svaki broj posmatramo kao indeks.

Napravimo pomoćni niz b i postavimo sve njegove vrednosti na 0.

b[i] će čuvati koliko puta se vrednost i pojavljuje.

Zatim za svaki element iz niza a povećavamo b[a[i]] za jedan.

i = 0 => a[i] = 4 => b[4] = 0 + 1 = 1

i = 1 => a[i] = 5 => b[5] = 0 + 1 = 1

Kada ovo uradimo za sve elemente, niz b izgleda ovako:

Couning Sort.jpg

Da bismo ispisali sortiran niz, samo prolazimo kroz b i ispisujemo i, tačno b[i] puta!

Napomena:
Duplikati se automatski pravilno obrađuju, jer b[i] čuva koliko puta se element pojavio.

Implementacija

Solution.cpp
#include <bits/stdc++.h>

using namespace std;

int main(){

    vector<int> a = {4, 5, 6, 3, 1, 7,3};

    vector<int> b(100, 0); //biramo veličinu za koju znamo da je veća od najvećeg elementa u nizu

    for(int i=0;i<a.size();i++){
        b[a[i]]++;
    }

    for(int i =0;i<b.size();i++){

        for(int j=0; j<b[i];j++){ //ispisujemo i, b[i] puta
            cout<<i<<" ";
        }
    }

    return 0;
 }

Niz: 4 5 6 3 1 7 3
Output: 1 3 3 4 5 6 7

Vremenska složenost: O(m + n), gde je m maksimalna vrednost u nizu a.

Važno je napomenuti da ako je m prevelik, možemo dobiti MLE (Memory Limit Exceeded) i program neće moći da se izvrši.
Zato ova tehnika funkcioniše samo kada su vrednosti relativno male.