在C上建立霍夫曼树时,父节点出现问题

时间:2020-10-13 11:30:51

标签: arrays c struct huffman-code

我正在尝试构建霍夫曼树,但是父节点有问题,在某些情况下,它们的起点指向错误的节点(带有字母的节点)。那不应该。怎么回事?我不知道!

UPD:我认为@auth(rules: [{ allow: owner, operations: [create, read, update] }]) { ... } whileextract_min()tr_build()循环中的某个错误。

优先级队列实现了类似指向insert_element()的指针的数组。

优先级队列工作良好,但是当我尝试构建树时出现问题。

huffman.h

pq_node

huffman.c

#ifndef PRIORITY_QUEUE
#define PRIORITY_QUEUE
#include <stdlib.h>
struct pq_node {
    unsigned long frequency;
    struct pq_node *parent;
    struct pq_node *left;
    struct pq_node *right;
    char symbol;
};

struct priority_queue {
    struct pq_node **heap_on_array;
    size_t size;
    size_t capacity;
};

// Return 0 if all is OK, -1 if can't alloc pq and -2 if can't alloc pq->heap_on_array.
int init_queue(struct priority_queue **pq, size_t capacity);

void shift_up(struct priority_queue *pq, int i);

void shift_down(struct priority_queue *pq, size_t i);

struct pq_node *extract_min(struct priority_queue *pq);

// Return position if find, or -1 if not.
int find(struct priority_queue *pq, char symbol);

// Return 0 if all is OK, and -1 if we can't alloc memory, if node is not NULL ignore `symbol` and `frequency` and add node.
int insert_element(struct priority_queue *pq, char symbol, unsigned long frequency, struct pq_node *node);

void node_swap(struct pq_node *first, struct pq_node *second);

struct pq_node *tr_build(struct pq_node *first, struct pq_node *second);
#endif

main.c

#include "huffman.h"
int init_queue(struct priority_queue **pq, size_t capacity)
{
    (*pq) = malloc(sizeof(struct priority_queue));
    if((*pq) == NULL)
    {
        return -1;
    }

    (*pq)->heap_on_array = malloc(sizeof(struct pq_node) * capacity);
    if((*pq)->heap_on_array == NULL)
    {
        return -2;
    }

    for(size_t i = 0; i < capacity; ++i)
    {
        (*pq)->heap_on_array[i] = malloc(sizeof(struct pq_node));
    }
    
    (*pq)->capacity = capacity;
    (*pq)->size = 0;
    return 0;
}

void shift_up(struct priority_queue *pq, int i)
{
    while (pq->heap_on_array[i]->frequency < pq->heap_on_array[(i-1)/2]->frequency)
    {
        node_swap((pq->heap_on_array[i]), (pq->heap_on_array[(i-1)/2]));
        i = (i - 1) / 2;
    }
}

void shift_down(struct priority_queue *pq, size_t i)
{
    while ((2 * i + 1) < pq->size)
    {
        size_t left = 2 * i + 1;
        size_t right = 2 * i + 2;
        size_t j = left;
        if((right < pq->size) && (pq->heap_on_array[right]->frequency < pq->heap_on_array[left]->frequency))
        {
            j = right;
        }
        if(pq->heap_on_array[i]->frequency <= pq->heap_on_array[j]->frequency)
        {
            break;
        }
        node_swap((pq->heap_on_array[i]), (pq->heap_on_array[j]));
        i = j;
    }
}

struct pq_node *extract_min(struct priority_queue *pq)
{
    struct pq_node *tmp = malloc(sizeof(struct pq_node)); //pq->heap_on_array[0];
    if(tmp == NULL)
    {
        return NULL;
    }

    tmp = pq->heap_on_array[0];

    pq->heap_on_array[0] = pq->heap_on_array[pq->size - 1];
    pq->size--;
    shift_down(pq, 0);
    return tmp;
}

int find(struct priority_queue *pq, char symbol)
{
    for(size_t i = 0; i < pq->size; ++i)
    {
        if(pq->heap_on_array[i]->symbol == symbol)
        {
            return (int)i;
        }
    }
    return -1;
}

int insert_element(struct priority_queue *pq, char symbol, unsigned long frequency, struct pq_node *node)
{
    int pos = 0;
    if(((pos = find(pq, symbol)) != -1) && (node == NULL))
    {
        pq->heap_on_array[pos]->frequency+=frequency;
        shift_down(pq, pos);
        return 0;
    }

    if(pq->size == pq->capacity)
    {
        pq->heap_on_array = reallocarray(pq->heap_on_array, pq->size * 2, sizeof(struct pq_node*));
        if(pq->heap_on_array == NULL)
        {
            return -1;
        }
        pq->capacity = pq->capacity * 2;
        for(size_t i = pq->size; i < pq->capacity; ++i)
        {
            pq->heap_on_array[i] = malloc(sizeof(struct pq_node));
        }
    }

    pq->size++;
    if(node == NULL)
    {
        pq->heap_on_array[pq->size - 1]->symbol = symbol;
        pq->heap_on_array[pq->size - 1]->frequency = frequency;
        pq->heap_on_array[pq->size - 1]->left = NULL;
        pq->heap_on_array[pq->size - 1]->right = NULL;
        pq->heap_on_array[pq->size - 1]->parent = NULL;
    }
    else
    {
        pq->heap_on_array[pq->size - 1] = node; // Здесь node->paret == NULL. Вот.
    }
    shift_up(pq, pq->size - 1);
    return 0;
}

void node_swap(struct pq_node *first, struct pq_node *second)
{
    struct pq_node tmp = *first;
    *first = *second;
    *second = tmp;
}

struct pq_node *tr_build(struct pq_node *first, struct pq_node *second)
{
    struct pq_node *tmp = malloc(sizeof(struct pq_node));
    if(tmp == NULL)
    {
        return NULL;
    }

    if(first == NULL || second == NULL)
    {
        return NULL;
    }

    first->parent = tmp;
    second->parent = tmp;

    if(first->frequency <= second->frequency)
    {
        tmp->left = first;
        tmp->right = second;
    }
    else
    {
        tmp->left = second;
        tmp->right = first;
    }

    tmp->parent = NULL;
    tmp->frequency = first->frequency + second->frequency;
    tmp->symbol = -1;
    return tmp;
}

如果我们在程序末尾查看GDB,我们将看到下一个:

int main()
{
    struct priority_queue *pq = NULL;
    char code[32] = {'\0'};

    init_queue(&pq, 1);
    insert_element(pq, 'a', 1, NULL);
    insert_element(pq, 'b', 1, NULL);
    insert_element(pq, 'c', 1, NULL);
    insert_element(pq, 'd', 1, NULL);

    while (pq->size > 1)
    {
        struct pq_node *tmp1 = extract_min(pq);
        struct pq_node *tmp2 = extract_min(pq);
        struct pq_node *tmp3 = tr_build(tmp1, tmp2); 
        insert_element(pq, -1, 0, tmp3);
    }
    return 0;
}

0 个答案:

没有答案
相关问题