Cod sursa(job #2077505)

Utilizator AlexGAlexandru Gheorghe AlexG Data 28 noiembrie 2017 10:09:45
Problema Coduri Huffman Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.3 kb
#include <iostream>
#include <fstream>

using namespace std;

struct Nod
{
    long long numarAparitii;
    long long fiu[2];
};

const long long numarMaximSimboluri = 1000000;
struct Coada
{
    long long indice[numarMaximSimboluri];
    long long inceput;
    long long sfarsit;
    void initializeaza()
    {
        inceput = 0;
        sfarsit = -1;
    }
    void adauga(long long i)
    {
        sfarsit++;
        indice[sfarsit] = i;
    }
    bool esteGoala()
    {
        return inceput > sfarsit;
    }
    long long i()
    {
        return indice[inceput];
    }
    long long scoate()
    {
        long long deIntors = indice[inceput];
        inceput++;
        return deIntors;
    }
    bool areUnSingurElement()
    {
        return inceput == sfarsit;
    }
};

Coada coadaNoduriInitiale;
Coada coadaNoduriInterne;

long long celMaiMicNod(Nod nod[])
{
    if(coadaNoduriInterne.esteGoala())
        return coadaNoduriInitiale.scoate();
    else if(coadaNoduriInitiale.esteGoala())
        return coadaNoduriInterne.scoate();
    else if(nod[coadaNoduriInitiale.i()].numarAparitii < nod[coadaNoduriInterne.i()].numarAparitii)
        return coadaNoduriInitiale.scoate();
    else
        return coadaNoduriInterne.scoate();
}

long long lungimeMinima;
long long nodIntern(Nod nod[], long long &numarNoduri)
{
    Nod nodNou;
    nodNou.fiu[0] = celMaiMicNod(nod);
    nodNou.fiu[1] = celMaiMicNod(nod);
    cout << nod[nodNou.fiu[0]].numarAparitii << ' ' << nod[nodNou.fiu[1]].numarAparitii << '\n';
    nodNou.numarAparitii = nod[nodNou.fiu[0]].numarAparitii + nod[nodNou.fiu[1]].numarAparitii;
    lungimeMinima += nodNou.numarAparitii;
    nod[numarNoduri] = nodNou;
    long long deIntors = numarNoduri;
    numarNoduri++;
    return deIntors;
}

void construiesteNoduriInterne(Nod nod[], long long &numarNoduri)
{
    while(coadaNoduriInitiale.inceput + coadaNoduriInterne.inceput <= coadaNoduriInitiale.sfarsit + coadaNoduriInterne.sfarsit)
        coadaNoduriInterne.adauga(nodIntern(nod, numarNoduri));
}

long long lungimeCod[numarMaximSimboluri];
long long cod[numarMaximSimboluri];
void parcurgereInAdancime(Nod nod[], long long i, long long adancime, long long codZecimal)
{
    if(nod[i].fiu[0] != -1)
    {
        parcurgereInAdancime(nod, nod[i].fiu[0], adancime+1, codZecimal*2);
        parcurgereInAdancime(nod, nod[i].fiu[1], adancime+1, codZecimal*2+1);
        return;
    }
    lungimeCod[i] = adancime;
    cod[i] = codZecimal;
}

int main()
{
    long long numarSimboluri;
    ifstream fin("huffman.in");
    fin >> numarSimboluri;
    coadaNoduriInitiale.initializeaza();
    Nod nod[2*numarSimboluri - 1];
    for(long long i=0; i<numarSimboluri; i++)
    {
        fin >> nod[i].numarAparitii;
        nod[i].fiu[0] = -1;
        nod[i].fiu[1] = -1;
        coadaNoduriInitiale.adauga(i);
    }
    coadaNoduriInterne.initializeaza();
    long long numarNoduri = numarSimboluri;
    construiesteNoduriInterne(nod, numarNoduri);
    cout<<lungimeMinima;
    parcurgereInAdancime(nod, coadaNoduriInterne.scoate(), 0, 0);
    ofstream fout("huffman.out");
    fout << lungimeMinima << '\n';
    for(long long i=0; i<numarSimboluri; i++)
        fout << lungimeCod[i] << ' ' << cod[i] << '\n';
    return 0;
}