Kodowanie Huffmana - problem z przechodzeniem drzewa binarnego.

0

Witam.
Piszę program który będzie kodował tekst metodą huffmana. Większość programu już mi działa jednak mam problem przy przechodzeniu drzewa binarnego. Tak wygląda fragment kodu odpowiadający z przechodzenie po drzewie, i spisywanie odpowiednich wartości:

while(kod != NULL)
    {
        if(kod->left == NULL && kod->right == NULL)
        {
            if(kod->znak < NUM_CHARS)
            {
                tab_kod[kod->znak] = "0";
                free(kod);
                kod = NULL;
            }
            else
            {
                free(kod);
                kod = NULL;
            }
        }
        else
        {
            char str[NUM_CHARS];
            ga_drzewa *zam = kod;
            int p = 0;
            while(zam->left != NULL || zam->right != NULL)
            {
                if(zam->left != NULL)
                {
                    zam = zam->left;
                    str[p] = '0';
                }
                else if(zam->right != NULL)
                {
                    zam = zam->right;
                    str[p] = '1';
                }
                p++;
            }
            if(zam->znak < NUM_CHARS)
            {
                tab_kod[zam->znak] = str;
                free(zam);
                zam = NULL;
            }
            else
            {
                free(zam);
                zam = NULL;
            }
        }
    } 

Przechodząc program krok po kroku doszedłem, że błąd powoduje zwalnianie pamięci. Proszę o radę co zrobić.
P.S.
Struktura drzewa wygląda następująco:

 
typedef struct drzewo
{
    int znak;
    struct drzewo *right, *left;
} ga_drzewa;

Proszę o szybką pomoc, problem zbyt trudny dla doświadczonego programisty pewnie nie jest.

0
manveruadunaim napisał(a)

Przechodząc program krok po kroku doszedłem, że błąd powoduje zwalnianie pamięci.

A jakie są przesłanki za tym? Na moją głowę kod jest dobry, a strzelając w ciemno: czy na pewno zawsze dbasz o to, żeby left i right były w momencie utworzenia węzła = NULL?

0

Doszedłem do czegoś takiego:

 char str[NUM_CHARS];
            ga_drzewa *zam = kod;
            int p = 0;
            while(zam->left != NULL || zam->right != NULL)
            {
                if(zam->left != NULL && (zam->left->left != NULL || zam->left->right != NULL))
                {
                    zam = zam->left;
                    str[p] = '0';
                    p++;
                }
                else if(zam->right != NULL && (zam->right->left != NULL || zam->right->right != NULL))
                {
                    zam = zam->right;
                    str[p] = '1';
                    p++;
                }
                else
                {
                    break;
                }
            }
            if(zam->left != NULL)
            {
                if(zam->left->znak < NUM_CHARS)
                {
                    str[p] = '0';
                    tab_kod[zam->left->znak] = str;
                }
                free(zam->left);
                zam->left = NULL;
            }
            else
            {
                if(zam->right->znak < NUM_CHARS)
                {
                    str[p] = '1';
                    tab_kod[zam->right->znak] = str;
                }
                free(zam->right);
                zam->right = NULL;
            }

Pozostałej części ie zmieniałem. Teraz pojawia się problem innej natury. I jestem prawie na 95% pewien, że problem powoduje zwalnianie pamięci. Otóż daje wyjaśnienie mam utworzone dajmy na to takie drzewo:
258:
left: 109
right: 257
109:
left: NULL
right: NULL
257:
left: 100
right 97
Od 100 i 97 już tylko NULL
Teraz kiedy wykonuję program to w momencie zwalniania pamięci elementu 109 występuje mi błąd:

Windows has triggered a breakpoint in huffman.exe.

This may be due to a corruption of the heap, which indicates a bug in huffman.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while huffman.exe has focus.

The output window may have more diagnostic information.

Proszę o pomoc program potrzebny jest na poniedziałek. A kompilator to MS Visual Studio 2010.

0

Jakbyś ten kod zrobił trochę ładniej, np. tak:

bool has_right(ga_drzewa *node)
{
  return node->right != NULL;
}

bool has_left(ga_drzewa *node)
{
  return node->left != NULL;
}

bool is_leaf(ga_drzewa *node)
{
  return !(has_left(node) || has_right(node));
}

void del(ga_drzewa **node)
{
  free(*node);
  *node = NULL;
}

char str[NUM_CHARS];
ga_drzewa *zam = kod;
int p = 0;
while (false == is_leaf(zam))
{
    if (true == has_left(zam) && false == is_leaf(zam))
    {
        zam = zam->left;
        str[p] = '0';
        p++;
    }
    else if(true == has_right(zam) && false == is_leaf(zam))
    {
        zam = zam->right;
        str[p] = '1';
        p++;
    }
    else
    {
        break;
    }
}
if (true == has_left(zam))
{
    if (zam->left->znak < NUM_CHARS)
    {
        str[p] = '0';
        tab_kod[zam->left->znak] = str;
    }
    del(zam->left);
}
else
{
    if(zam->right->znak < NUM_CHARS)
    {
        str[p] = '1';
        tab_kod[zam->right->znak] = str;
    }
    del(zam->right);
}

To mógłbyś sobie breakpointy wygodnie ustawić w has_left / has_right / is_leaf / del i wtedy podejrzeć callstack i ogarnąć, co się dzieje nie tak.
Mi teraz wygląda na to, że w ostatnim else brakuje ci sprawdzenia has_right(zam).

0

No analizując trochę, doszedłem, że te ułatwienie z funkcjami jest lepsze. Ale jeśli mógłbyś bardziej rozwinąć swoją wypowiedź na temat breakpoint'ów to byłbym wdzięczny. Nie orientuje się w tym, bo po prostu nie musiałem jeszcze tego nigdy używać.

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