Kodowanie Huffmana

0

Witam

Mam problem z kodowanie Huffmana. Napisałem taki program:

#include<iostream>
using namespace std;
struct drzewo
{
    drzewo *lewy, *prawy, *rodzic;
    char znak;
    drzewo(); 
};
struct element_listy
{
    double czest;
    drzewo wezel;
    element_listy *nastepny;
    element_listy();
};
struct lista
{
    element_listy *head;
    int rozmiar;
    void dodaj(double n_czest, drzewo n_wezel);
    void znajdz(element_listy *&min1, element_listy *&min2);
    void usun(element_listy *element);
    lista(); 
};
void scal(lista l1, element_listy *min1, element_listy *min2);
void kodowanie();
int main()
{
    kodowanie();
}
drzewo::drzewo()
{
    lewy=NULL;
    prawy=NULL;
    rodzic=NULL;
}
element_listy::element_listy()
{
    nastepny=NULL;
}
lista::lista()
{
    head=NULL;
    rozmiar=0;
}
void lista::dodaj(double n_czest, drzewo n_wezel)
{
    element_listy *nowy = new element_listy;
    nowy->czest=n_czest;
    nowy->wezel=n_wezel;
    if(!head) head=nowy; else 
        element_listy *temp;
        temp=head;
        while(temp->nastepny) temp=temp->nastepny;
        temp->nastepny=nowy;
        nowy->nastepny=NULL;
    }
    rozmiar++;
}
void lista::znajdz(element_listy *&min1, element_listy *&min2)
{
    element_listy *temp1, *temp2;
    min1=head;
    min2=head->nastepny;
    if(min1->czest>min2->czest)
    {
        temp2=min1;
        min1=min2;
        min2=temp1;
    }
    temp1=head->nastepny->nastepny;
    while(temp1)
    {
        if(temp1->czest<min2->czest)
        {
            temp2=min1;
            min1=min2;
            min2=temp2;
        }
    }
    temp1=temp1->nastepny;
}
void lista::usun(element_listy *element)
{
    element_listy *temp;
    temp=head;
    if(element==temp)
    {
        head=temp->nastepny;
        rozmiar--;
    } else
    {
        do temp=temp->nastepny; while(temp->nastepny!=element);
        if(temp->nastepny->nastepny) temp->nastepny=temp->nastepny->nastepny; else temp->nastepny=NULL;
        rozmiar--;
    }
}
void scal(lista l1, element_listy *min1, element_listy *min2)
{
    drzewo *d1;
    *d1->lewy=min1->wezel;
    *d1->prawy=min2->wezel;
    d1->lewy->rodzic=d1;
    d1->prawy->rodzic=d1;
    double suma;
    suma=min1->czest+min2->czest;
    l1.usun(min1);
    l1.usun(min2);
    l1.dodaj(suma, *d1);
}
void kodowanie()
{
    int ile;
    char zn;
    double p;
    element_listy *min1, *min2;
    cin >> ile;
    lista list;
    for(int i=0; i<ile; i++)
    {
        cin >> zn >> p;
        drzewo d1;
        d1.znak=zn;
        list.dodaj(p, d1);
    }
    while(list.rozmiar>2)
    {
        list.znajdz(min1, min2);
        scal(list, min1, min2);
    }
}

Brakuje jeszcze w nim funkcji wypisującej kod.

Program się kompiluje, jednak po podaniu danych wejściowych pojawia się błąd (w instrukcji list.dodaj(p, d1);). Niestety nie wiem czym jest on spowodowany.
Będę wdzięczny za wszelkie wskazówki dotyczące tego błędu oraz ewentualnych innych błędów w programie.

Udało się wyeliminować ten błąd, ale prosiłbym o sprawdzenie czy ten program może tak wyglądać, czy są w nim jeszcze jakieś błędy.
Z góry dziękuję :)

Pozdrawiam

0

Witam

Poprawiłem program. Program działa prawidłowo, ale tylko dla niektórych danych wejściowych. Np. dla danych

 4
A 1
B 2
C 3
D 4

program daje dobre wyniki. Ale dla tych samych danych, tylko w innej kolejności:

 4
D 4
C 3
B 2
A 1

działanie programu kończy się błędem. Zauważyłem, że w niektórych przypadkach funkcja znajdz zwraca takie same wskaźniki (min1 i min2) - zamiast dwóch wartości minimalnych z listy zwraca dwa razy najmniejszą. Siedzę nad tym programem już kilka godzin i niestety nie mogę znaleźć błędu.

#include<iostream>
using namespace std;
struct drzewo
{
    drzewo *lewy, *prawy, *rodzic;
    char znak;
    drzewo(); //konstruktor domyslny
};
struct element_listy
{
    double czest;
    drzewo *wezel;
    element_listy *nastepny;
    element_listy(); //konstruktor domyslny
};
struct lista
{
    element_listy *head;
    int rozmiar;
    void dodaj(double n_czest, drzewo *n_wezel);
    void znajdz(element_listy *&min1, element_listy *&min2);
    void usun(element_listy *element);
    lista(); //konstruktor domyslny
};
void scal(lista &l1, element_listy *min1, element_listy *min2);
void kodowanie();
void inorder(drzewo * n, char c[], int lenc);
int main()
{
    kodowanie();
}
drzewo::drzewo()
{
    lewy=NULL;
    prawy=NULL;
    rodzic=NULL;
}
element_listy::element_listy()
{
    nastepny=NULL;
}
lista::lista()
{
    head=NULL;
    rozmiar=0;
}
void lista::dodaj(double n_czest, drzewo *n_wezel)
{
    element_listy *nowy = new element_listy;
    nowy->czest=n_czest;
    nowy->wezel=n_wezel;
    if(!head) head=nowy; else //jezeli lista jest pusta to nowy element jest jej pierwszym elementem, w przeciwnym razie nowy element zostaje dodany na koniec listy
    {
        element_listy *temp;
        temp=head;
        while(temp->nastepny) temp=temp->nastepny;
        temp->nastepny=nowy;
        nowy->nastepny=NULL;
    }
    rozmiar++;
}
void lista::znajdz(element_listy *&min1, element_listy *&min2)
{
    element_listy *temp1, *temp2;
    min1=head;
    min2=head->nastepny;
    if(min1->czest>min2->czest)
    {
        temp2=min1;
        min1=min2;
        min2=temp2;
    }
    temp1=head->nastepny->nastepny;
    while(temp1)
    {
        if(temp1->czest<min2->czest)
        {
            min2=temp1;
            if(min1->czest>min2->czest)
            {
                temp2=min2;
                min1=min2;
                min2=temp2;
            }
        }
        temp1=temp1->nastepny;
    }

}
void lista::usun(element_listy *element)
{
    element_listy *temp;
    temp=head;
    if(element==temp)
    {
        head=temp->nastepny;
        rozmiar--;
    } else
    {
        while(temp->nastepny!=element) temp=temp->nastepny;
        if(temp->nastepny->nastepny) temp->nastepny=temp->nastepny->nastepny; else temp->nastepny=NULL;
        rozmiar--;
    }
}
void scal(lista &l1, element_listy *min1, element_listy *min2)
{
    drzewo *d1=new drzewo;
    d1->lewy=min1->wezel;
    d1->prawy=min2->wezel;
    d1->lewy->rodzic=d1;
    d1->prawy->rodzic=d1;
    double suma;
    suma=min1->czest+min2->czest;
    l1.usun(min1);
    l1.usun(min2);
    l1.dodaj(suma, d1);

    //delete min1;
    //delete min2;
}
void kodowanie()
{
    int ile;
    char zn;
    double p;
    element_listy *min1, *min2;
    cin >> ile;
    lista list;
    for(int i=0; i<ile; i++)
    {
        cin >> zn >> p;
        drzewo *d1=new drzewo;
        d1->znak=zn;
        list.dodaj(p, d1);
    }
    while(list.rozmiar>1)
    {
        list.znajdz(min1, min2);
        scal(list, min1, min2);
    }
    char hcodes[256];
    inorder(list.head->wezel, hcodes, 0);
}
void inorder(drzewo * n, char c[], int lenc)
{
  if(!(n->lewy))
  {
    cout << n->znak << " : ";
    for(int i = 0; i < lenc; i++) cout << c[i];
    cout << endl;
  }
  else
  {
    c[lenc] = '0'; inorder(n->lewy,c,lenc + 1);
    c[lenc] = '1'; inorder(n->prawy,c,lenc + 1);
  }
}
 
0

Chyba rzeczywiście ten błąd spowodowany jest funkcją znajdz, bo po dodaniu instrukcji //if(min1==min2) {cout << "Blad!"; break;} else
scal(list, min1, min2);* w funkcji kodowanie, w pętli while, program wykonuje się poprawnie dla wszystkich danych wejściowych (ale oczywiście nie zwraca prawidłowych wyników). Ale funkcja *znajdz// wygląda na poprawną i nie mogę znaleźć tam błędu. Będę wdzięczny za wszelkie wskazówki

1 użytkowników online, w tym zalogowanych: 0, gości: 1