Cod sursa(job #1758194)

Utilizator sulzandreiandrei sulzandrei Data 16 septembrie 2016 19:20:45
Problema Sortare prin comparare Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.4 kb
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <unordered_map>
using namespace std;

#define nmax 500003


ifstream in("algsort.in");
ofstream out("algsort.out");
//////////////////////////////
///////////
///////////      LSD Radix sort using countsort for bytes
///////////
//////////////////////////////
#define max_n 10000000+1
int v[max_n],temp[max_n];

const int max_byte = (1<<8)-1;//valoarea maxima a unui byte
const int nr_bytes = sizeof(int);//nr de bytes din un int
inline int ithbyte(int n,int i)//al i byte de la stanga la dreapta pentru numarul n
{
    return (n>>(i*8))&max_byte;//un nr are 8 biti si vrem sa shiftam i bytes la dreapta deci i*8 si apoi
    // facem & cu valoarea maxima a unui byte pentru a obtine doar al i-lea byte din numar
}
void byte_numsort(int *A, int *B,int n, int byte_nr)//folosim sortarea countsort modificata O(n+K) unde K e valoare maxima a unui byte
{                                    //pentru a sorta numerele in functie de al byte_nr-lea byte de la stanga la dreapta
    int C[max_byte+1];                          // C[i] nr de aparitii al byte-ului i in toate numerele
    int index[max_byte+1];                      //index[i] = numarul de numere care au al byte_nr -lea byte mai mic ca i
    for(int i = 0 ; i <= max_byte ; i ++)
        C[i] = 0;                                   //initial nu avem bytes
    for(int i = 0 ; i < n ; i ++)
        C[ithbyte(A[i],byte_nr)]++;        // pentru fiecare al byte_nr -lea byte din fiecare nr incrementam aparitia in C
    index[0] = 0;                           //initial nu avem niciun byte < 0
    for(int i = 1 ; i <= max_byte; i++)//pentru fiecare numar de la 0 la valorea maxima a unui byte
        index[i] = index[i-1]+C[i-1];//numarul de bytes mai mici ca i va fi nr de aparitii al al i-1-lea byte in
                                    // toate numerele +  numarul de bytes mai mici ca i-1
    for(int i = 0 ; i < n ; i++)//pentru fiecare numar vedem unde ii este locul in functie de valoarea celui
                             //de-al byte_nr -lea byte
    {
        B[index[ithbyte(A[i],byte_nr)]] = A[i];//deci index de un byte reprezinta pozitia valorii A[i] in vectorul B
        index[ithbyte(A[i],byte_nr)]++;//si deoarece am asezat pe pozitia aceea deja o valoare crestem pozitia
    }
    for(int i = 0 ;  i< n ; i++)
        A[i] = B[i];//punem la loc in A valoriile in ordinea corespunazatoare
}
void LSD_byte_radixsort(int *v, int n)//sortam folosind LSD radix sort vectorul v cu n elemente de la 0 la n-1
{                                     //O(dn +dK) pentru unde d = numarul de bytes si K e valoarea maxima a unui byte
    for(int i = 0 ; i< nr_bytes ; i++)//pentru fiecare byte
        byte_numsort(v,temp,n,i);//sortam folosind countsort in functie de al i-ea byte de la dreapt la stanga
}
vector<int> bucket[10];//bucket vector de galeti si fiecare cifra de la 0...9 este o galeata unde bagam numerele cu aceea cifra
void LSD_digit_radixsort(int *v, int n)//LSD radix sort pentru  cifre
{
    int max_el = *max_element(v,v+n);//elementul maxim
    int digits = 0;//numar de cifre maxime dintr-un numar
    do{max_el/=10;digits++;}while(max_el);//aici le aflam
    int pow10[10];//si pow10[i] va fi 10^i
    pow10[0] = 1;
    for(int i = 1 ; i <= 9 ; i++)
        pow10[i] = pow10[i-1]*10;
    int k;//pentru a baga inapoi in v din galeti valorile
    for(int i = 0 ; i < digits ; i++)//pentru fiecare cifra de la dreapta la stanga unui numar
    {
        for(int j = 0 ; j < n ; j++)//pentru toate numerele
            bucket[(v[j]/pow10[i])%10].push_back(v[j]);//bagam valoarea v[j] in galeata cu indexul = a i cifra de la dreapta
        k = 0;                                      //la stanga a numarului v[j] si obtime cifra cu formula (v[j]/pow10[i])%10
        for(int j = 0 ; j <= 9 ; j++)//bagam numerele din fiecare galeata in ordine de la cea mai mica cifra la cea mai mare
        {
            for(const auto& nr:bucket[j])//pentru fiecare valoare din acceea galeata o bagam inapoi in vectorul v
                v[k++] = nr;//pe pozitia corecta
            bucket[j].clear();//si golim tot ce e in galeata
        }
    }
}
int main()
{
     int n,i;
    in >> n;

    int v[n+5];
    for( i = 0 ; i < n ; i++)
        in >> v[i];
    LSD_byte_radixsort(v,n);
    for(int i = 0 ; i < n ; i ++)
        out << v[i] << " ";
    return 0;
}