Cod sursa(job #2077476)

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

using namespace std;

struct Nod
{
    int numarAparitii;
    int indice;
    Nod *stanga;
    Nod *dreapta;
};

const int numarMaximNoduri = 2000000;
struct Coada
{
    Nod *nod[numarMaximNoduri];
    int inceput;
    int sfarsit;
    void initializeaza()
    {
        inceput = 0;
        sfarsit = -1;
    }
    void adauga(Nod *nodNou)
    {
        sfarsit++;
        nod[sfarsit] = nodNou;
    }
    int numarAparitii()
    {
        return nod[inceput]->numarAparitii;
    }
    bool esteGoala()
    {
        return inceput > sfarsit;
    }
    Nod *scoate()
    {
        Nod *deIntors = nod[inceput];
        inceput++;
        return deIntors;
    }
    bool areUnSingurElement()
    {
        return inceput == sfarsit;
    }
};

Nod *nodInitial(int numarAparitii, int indice)
{
    Nod *nodNou = new Nod;
    nodNou->numarAparitii = numarAparitii;
    nodNou->indice = indice;
    nodNou->stanga = NULL;
    nodNou->dreapta = NULL;
    return nodNou;
}

Coada coadaNoduriInitiale;
Coada coadaNoduriInterne;

Nod *celMaiMicNod()
{
    if(coadaNoduriInterne.esteGoala())
        return coadaNoduriInitiale.scoate();
    else if(coadaNoduriInitiale.esteGoala())
        return coadaNoduriInterne.scoate();
    else if(coadaNoduriInitiale.numarAparitii() < coadaNoduriInterne.numarAparitii())
        return coadaNoduriInitiale.scoate();
    else
        return coadaNoduriInterne.scoate();
}

long long lungimeMinima;
Nod *nodIntern()
{
    Nod *nodNou = new Nod;
    nodNou->stanga = celMaiMicNod();
    nodNou->dreapta = celMaiMicNod();
    nodNou->numarAparitii = nodNou->stanga->numarAparitii + nodNou->dreapta->numarAparitii;
    lungimeMinima += nodNou->numarAparitii;
    return nodNou;
}

void construiesteNoduriInterne()
{
    while(!coadaNoduriInitiale.esteGoala() || !coadaNoduriInterne.areUnSingurElement())
        coadaNoduriInterne.adauga(nodIntern());
}

const int numarMaximSimboluri = 1000000;
int lungimeCod[numarMaximSimboluri];
long long cod[numarMaximSimboluri];
void parcurgereInAdancime(Nod *radacina, int adancime, long long codZecimal)
{
    if(radacina->stanga != NULL)
    {
        parcurgereInAdancime(radacina->stanga, adancime+1, codZecimal*2);
        parcurgereInAdancime(radacina->dreapta, adancime+1, codZecimal*2+1);
        return;
    }
    lungimeCod[radacina->indice] = adancime;
    cod[radacina->indice] = codZecimal;
}

int main()
{
    int numarSimboluri;
    ifstream fin("huffman.in");
    fin >> numarSimboluri;
    coadaNoduriInitiale.initializeaza();
    for(int i=0; i<numarSimboluri; i++)
    {
        int numarAparitii;
        fin >> numarAparitii;
        coadaNoduriInitiale.adauga(nodInitial(numarAparitii, i));
    }
    coadaNoduriInterne.initializeaza();
    construiesteNoduriInterne();
    parcurgereInAdancime(coadaNoduriInterne.scoate(), 0, 0);
    ofstream fout("huffman.out");
    fout << lungimeMinima << '\n';
    for(int i=0; i<numarSimboluri; i++)
        fout << lungimeCod[i] << ' ' << cod[i] << '\n';
    return 0;
}