【问题标题】:Assigning binary tree values (huffman encoding)分配二叉树值(霍夫曼编码)
【发布时间】:2015-12-07 15:06:13
【问题描述】:

目的是读取文件,计算每个字符的频率并执行霍夫曼编码,其中最常见的字母将是短二进制代码,即 001,而最不常见的字母会更长,即 01000100。

我创建了一个链接列表,其中包含所有字符及其各自频率的排序(按升序)列表。这被传递给下面的函数。在这个函数中,我的目标是添加两个最低频率并像这样构建二叉树,直到树的长度为 1。我不确定从这里去哪里,我知道我必须查看树并查看哪个将它向左或向右移动,然后存储 0(左)或 1(右)。 - 但我不知道如何构建一个函数来做到这一点!

void traverse_list(pqueue *list)
    {
    char letters[CHARACTERS] = { 0 };
    int frequencies[CHARACTERS] = { 0 };
    int j = 0, l = 0, len = 0;
    node *temp = list->head;
    tree *array[CHARACTERS];
    while (temp != NULL)
    {
        letters[j] = temp->letter;
        frequencies[j] = temp -> frequency;
        temp = temp->next;
        j++;
    }
    for (l = 0; l < CHARACTERS; l++)
    {
        if (frequencies[j])
        {
            tree* huffman = calloc(1, sizeof(tree));
            huffman -> letter = letters[l];
            huffman -> frequency = frequencies[l];
            array[len++] = huffman;
        }
    }

    while (len > 1)
    {
        tree* huffman = malloc(sizeof(tree));
        huffman -> left = array[len--];
        huffman -> right = array[len--];
        huffman -> frequency = huffman -> left -> frequency + huffman -> right -> frequency;
        array[len++] = huffman;
    } 
}

为了便于阅读,结构如下所示:

typedef struct Node
{
    char letter;
    int frequency;
    struct Node *next;

}node;

typedef struct pqueue
{
    node *head;

}pqueue;

typedef struct tree
{
    struct tree *left;
    struct tree *right;
    char letter;
    int frequency;
}tree;

【问题讨论】:

标签: c linked-list binary-tree huffman-code


【解决方案1】:

我不明白你为什么要创建这么多数组,然后再次使用它们创建新节点。我认为这可以通过修改Node 的结构来轻松完成。像这样的东西::

typedef struct Node
{
    char letter;
    int frequency;
    struct Node *next;
    struct Node *left, *right;
}node;

因此,您可以执行以下操作来形成一棵树。

void huffman(plist *list) {
    while(1) {
        node *left = list->head;
        list->head = list->head->next;
        node *right = list->head;
        list->head = list->head->next;

        node *huffman = malloc(sizeof(node));
        huffman->frequency = left->frequency;
        huffman->left = left;
        huffman->right = right;
        huffman->next = NULL;

        if(list->head == NULL) {
            list->head = huffman;
            break;
        }
        insertHuffman(root, huffman);
    }
}

您的insertHuffman() 将在pList 中按排序顺序插入新的node。所以,最后你在树中只剩下一个node,然后你可以简单地进行一次遍历来决定每个节点的值。您绝对可以选择比我使用的while(1) 更好的条件! :P 我使用它是因为这是我想到的第一件事。我相信你肯定可以写insertHuffman()

编辑::

void printHuffman(node *head, node *parent, char *a, int len) {
    if(head->left == NULL && head->right == NULL) {
        if(parent != NULL && parent->right == head) {
            cout << head->letter << " " << a << "1";
        } else if(parent != NULL && parent->left == head) {
            cout << head->letter << " " << a;
        }
    } else {
        a[len] = '0';
        printHuffman(head->left, head, a, len + 1);
        a[len] = '1';
        printHuffman(head->right, head, a, len + 1);
    }
}

我认为这将打印每个字符的霍夫曼值。

这里,a 是大小为CHARACTERS 的字符数组,所有初始化为\0len 的值都保存当前代码的值。

编辑 2 ::

我已经看到您尝试将字符 tree 节点组合成 1 个 tree 节点的方式,方法是从升序排序数组中取出最后两个节点,并将它们组合成一个新节点,该节点位于结束数组。根据我对霍夫曼编码的了解,您不会将具有最大频率的元素组合在一起,而是将具有最低频率的元素组合在一起,然后形成用于查找霍夫曼编码的树。

【讨论】:

  • 我很欣赏这一点,但其余代码围绕我之前所做的构建,我现在无法更改它,这将花费太长时间。问题是我不知道如何遍历树来确定值:(
  • @Finlandia_C 添加两个指向 struct 的指针,我认为这不会影响其他大部分代码,您可以将其留用于代码的其他部分,或者您可以复制 plist 你在函数中接收,然后处理复制的列表。我将更新有关遍历树的答案。
  • 谢谢,如果你能对我的做法进行遍历,这样我就会知道这两种方式!
  • @Finlandia_C 这与您尝试做的事情不符,但我认为这会奏效。我会看看你想用你的代码做什么!
  • @Finlandia_C 检查答案,并分享您用于制作霍夫曼代码的霍夫曼算法链接。
【解决方案2】:

尝试改变

        huffman -> left = array[len--];
        huffman -> right = array[len--];

        huffman -> left = array[--len];
        huffman -> right = array[--len];

为了得到数组的最后一个元素。

【讨论】:

  • 谢谢。但也许我没有正确地用词。我被困在如何实际执行通过树查看它向左/向右移动的功能,然后如何分配这些二进制代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多