Бинарное дерево теряет узлы при построении дерева

Я построил двоичное дерево (дерево Хаффмана), используя приведенный ниже код, который принимает отсортированный в возрастающем порядке связанный список, однако, когда он завершает работу, он печатает битовые шаблоны, а некоторые из узлов, которые должны быть в дереве, не .

Код по сути:

  1. устанавливает родительский узел так, чтобы он указывал на два самых нижних узла

  2. назначает внутреннюю частоту родительского узла

  3. указывает, что начало списка теперь находится в узлах 2 от того места, где оно было (чтобы избежать повторного использования узлов)

  4. вставляет новый родительский узел в правильную позицию в дереве

  5. получает длину дерева

  6. распечатать все узлы, оставшиеся в списке

  7. повторяется до тех пор, пока не останется один узел (который является корнем).

Любые идеи относительно того, почему он «теряет» узлы по пути?

void build_tree(pqueue *list)
{

    node *temp; 
    node* parent_node;
    int min_1, min_2, ind = 0, counter = 0, length = 2, head;
    int characters[CHARACTERS];
    temp = new_node();

    while (length > 1)
    {
        min_1 = 0;
        min_2 = 0;
        temp = list->start;           
        parent_node = new_node(); 
        parent_node->letter = '#';             
        min_1 = temp->frequency;
        parent_node->left = temp;         
        temp = temp->next;               
        min_2 = temp->frequency;
        parent_node->right = temp;       
        parent_node->frequency = min_1 + min_2;
        list->start = temp->next;

        while (ind == 0) /* inserting a node to the correct place */
        {
            if (temp != NULL && temp->next != NULL)
            {
                temp = temp->next;
                if (temp->frequency >= parent_node->frequency) /* in the middle */
                {
                    parent_node->next = temp->next;
                    temp->next = parent_node;
                    ind = 1;
                }
                else if (temp->next == NULL) /* at the end */
                {
                    temp->next = parent_node;
                    parent_node -> next = NULL;
                    ind = 1;
                }
            }
        }
        ind = 0;
        temp =  list->start;
        while (temp->next != NULL) /* get number of nodes left to insert into tree */
        {
            temp = temp->next;
            counter++;
            printf("%c : %d\n", temp->letter, temp->frequency); 
        }
        printf("----------------------------------------------\n");
        length = counter;
        counter = 0;
    }
    printf("Found root with value of: %d\n", temp->frequency);
    head = 0;
    BitPatterns(temp, characters, head);
    temp = list->start;
    deallocate(temp, list);
}


void BitPatterns(node* root, int characters[], int head)
{
    if (root->left)
    {
        characters[head] = 0;
        BitPatterns(root->left, characters, head +1);
    }

    if (root->right)
    {
        characters[head] = 1;
        BitPatterns(root->right, characters, head +1);
    }


    if (isLeaf(root))
    {
        printf("'%c' : ", root->letter);
        GetChars(characters, head);

    }
}

void GetChars(int characters[], int n)
{
    int i, counter = 0;
    for (i = 0; i < n; ++i)
    {
        printf("%d", characters[i]);
        counter++;

    }
    printf(" (%d * \n", counter);

}

int isLeaf(node* root)
{
    return !(root->left) && !(root->right) ;
}

person Finlandia_C    schedule 12.12.2015    source источник
comment
Для этого вам нужно показать код BitPatterns()   -  person user007    schedule 12.12.2015
comment
Я добавил битовые шаблоны и getchars, как это называется в битовых шаблонах. isleaf - это просто return !(root->left) && !(root->right) ;   -  person Finlandia_C    schedule 12.12.2015


Ответы (1)


Ok! Это было сложно отладить. Но, думаю, я нашел проблему. Проблема заключается в цикле while, в котором вы находите длину списка, оставшегося для обработки. Поскольку условие в цикле while равно temp->next != NULL, считайте, что ваш список имеет размер 2, что-то вроде этого:

3 -> 4 -> NULL (числа представляют собой сумму частот некоторых узлов)

Если list->start указывает на 3. И вы будете измерять длину этого списка как 1, а не 2, потому что вы проверяете temp->next != NULL.

Из-за этого вы упускаете важный второй узел списка, запускаете BitPatterns() только на первом узле и пропускаете несколько узлов.

Возможным решением этой проблемы было бы вставить цикл while в начало функции для однократного измерения длины, который можно было бы уменьшить на 1 в каждой последовательной итерации цикла while, где вы объединяете два узла, поскольку вы всегда удаляя два узла и добавляя один узел в список, вам нужно только уменьшить length на 1. Это также сэкономит массу дополнительных вычислений, которые вы выполняете в конце списка для вычисления длины списка каждый раз.

Что-то вроде этого ::

temp = list->start;
while(temp != NULL) {
    length++;
    temp = temp->next;
}

РЕДАКТИРОВАТЬ :: Более того, я вижу в вашем коде еще одну логическую ошибку:

Считайте, что исходный список таков:

1 -> 2 -> 4 -> 5 -> NULL

Вы объединяете первые два узла, пусть этот узел будет называться A (with freq = 3), а list_start указывает на 4. Итак, когда вы вставляете узел в список, он выглядит примерно так:

4 -> A -> 5 -> NULL

Хотя список должен выглядеть примерно так:

A --> 4 --> 5

Это не влияет на работу кода, но может привести к некоторым неоптимизированным результатам кода Хаффмана.

person user007    schedule 12.12.2015
comment
Итак - найти длину списка - установить цикл while, чтобы смотреть на длину, и в конце каждой итерации установить длину, уменьшающуюся на 1? - person Finlandia_C; 12.12.2015
comment
@Finlandia_C Думаю, это сработало, просто посмотрите на правку, которую я сделал, может быть полезно - person user007; 12.12.2015