【问题标题】:Compressing files program压缩文件程序
【发布时间】:2018-05-16 09:52:11
【问题描述】:

我正在尝试构建一个用于压缩文件的程序。 我正在使用霍夫曼算法,并通过视频进行了研究:https://www.youtube.com/watch?v=dM6us854Jk0&t=436s

我尝试在位上使用相同的方式 - 首先我在 Nibbles 上尝试过: 我把每个 Nibbles(16 个选项)都给了一个随机频率,然后我构建了一个二叉树,按 Nibbles 的频率排序,就像在视频中一样。

我成功地将 22K 的位压缩成 18K,到目前为止它工作正常。 然后我在 Bytes(256 选项)上尝试了它,但它没有工作 - 一开始它有 13M 位,压缩后它有 89M。

我有一张图片展示了 Nibble 示例的二叉树:

还有两个exel文件,指定计算Nibbles树和Bytes树:

我用C语言实现了算法,这里有部分函数:

typedef struct INFO
{
    unsigned char binary;   //Binary number
    int amount; //Frequency
} INFO;

typedef struct TREE
{
    INFO info;
    struct TREE *prev;
    struct TREE *left;
    struct TREE *right;
} TREE;



/** Function that allocates memory and creates a tree node and initializes it */
TREE * treeNodeMalloc()
{
    TREE *p;
    p = (TREE *)malloc(sizeof(TREE));
    if (!p)
        return NULL;
    p->prev = p->left = p->right = NULL;
    return p;
}


/** Function that builds the first sub-root node consist of two binary numbers */
TREE * firstNode(INFO first, INFO second)
{
    TREE *head, *p;
    int i;
    head = treeNodeMalloc();
    if (!head) return 0;
    for (i = 1; i <= 2; i++)
    {
        p = treeNodeMalloc();
        if (!p) { freeTree(head); return 0; }
        p->prev = head;
        if (i % 2)
        {
            p->info.amount = first.amount;
            p->info.binary = first.binary;
            head->left = p;
        }
        else
        {
            p->info.amount = second.amount;
            p->info.binary = second.binary;
            head->right = p;
        }
    }
    head->info.amount = head->left->info.amount + head->right->info.amount;
    return head;
}


/** Function that builds a sub-root node that consist of a node of binary number and a sub-root of two previous binary numbers */
TREE * continuanceNode(TREE *p1, INFO info)
{
    TREE *h, *p2;
    h = treeNodeMalloc();
    if (!h) { freeTree(p1); return 0; }
    p2 = treeNodeMalloc();
    if (!p2) { free(h); freeTree(p1); return 0; }
    p2->info.amount = info.amount;
    p2->info.binary = info.binary;
    p1->prev = p2->prev = h;
    h->left = p1;
    h->right = p2;
    h->info.amount = h->left->info.amount + h->right->info.amount;
    return h;
}


/** Function that builds the last node of the tree - the main root */
TREE * LastNode(TREE *p1, TREE *p2)
{
    TREE *p3;
    p3 = treeNodeMalloc();
    if (!p3)
    {
        freeTree(p1);
        freeTree(p2);
        return NULL;
    }
    p3->left = p1;
    p3->right = p2;
    p1->prev = p2->prev = p3;
    p3->info.amount = p3->left->info.amount + p3->right->info.amount;
    return p3;
}



/** Function that builds the binary tree from the array of INFO (binary numbers and their frequencies),
The function builds the tree from bottum to the top (reverse build) */
TREE * dataToTree(INFO arr[], int size)
{
    int i;
    TREE *h, *p, *t=NULL;
    p = firstNode(arr[0], arr[1]);
    if (!p) return 0;
    for (i = 2; i < size; i++)
    {
        if (p->info.amount > arr[size - 1].amount)
            if (!t)
            {
                t = firstNode(arr[i], arr[i + 1]); 
                i++;
                if (!t) { freeTree(p); return NULL; }
            }
            else
                if (p->info.amount < t->info.amount)
                {
                    p = continuanceNode(p, arr[i]);
                    if (!p) { freeTree(t); return 0; }
                }
                else
                {
                    t = continuanceNode(t, arr[i]);
                    if (!t) { freeTree(p); return 0; }
                }
        else
        {
            p = continuanceNode(p, arr[i]);
            if (!p) { freeTree(t); return 0; }
        }
    }
    h = LastNode(p, t);
    return h;
}

每个人都说 Huffman 算法最适合压缩文件,那么我在这里缺少什么? 我在做什么?

【问题讨论】:

  • 请查看是否可以将代码缩短到最小长度 - stackoverflow.com/help/mcve
  • 恐怕它已经很少了——完整的代码很长,我只添加了相关的函数和结构。代码完全按照我想要的方式工作,并在我“看到”它时实现算法,我只是想也许你会要求它。我认为问题在于我在位上使用算法的方式,(我如何“看到”它)
  • Everyone says Huffman algorithm is the best for compressing files 谁在什么情况下?看看Kolmogorov complexity
  • 我还没有了解算法的复杂性,现在我尝试实现它,如果你问谁告诉我使用它,我已经在需要时进行了研究寻找最适合压缩文件的算法,并找到合适的算法。

标签: c algorithm compression binary-tree huffman-code


【解决方案1】:

您构建的霍夫曼树是错误的。在每个步骤中,您都需要融合所有可用根节点中频率最低的两个节点。因此,首先将 9 和 14 融合起来:

  21
 /  \
9   14

下一步是融合 21 和 20

    41
   /  \
  21  20
 /  \
9   14

然后是 41 和 50

      91
     /  \
    41  50
   /  \
  21  20
 /  \
9   14

但是这一步最低的两个是70和80,所以分开融合

      91     150
     /  \   /  \
    41  50 70  80
   /  \
  21  20
 /  \
9   14

然后你必须融合最低的两个,91和100等。

然后树会更加“平衡”,结果可能会更好。

你应该知道(从编码理论)有些文本是不能压缩的。对于给定的压缩算法,始终存在至少一个无法压缩的文本。通常,无论您尝试使用任何算法,都至少存在一个无法压缩的文本。所有这些都需要一些更多的理论解释,但大致就是理论可以说的。

【讨论】:

  • 非常感谢,我会尝试根据您的构造重建树并返回结果。
  • 很抱歉,我觉得我在算法步骤上迷路了,我不知道如何从这里继续:drive.google.com/file/d/1RVJoumOydsiiE5zI-qdc42FOgHOR9nEL/…
  • 建立一个节点列表,按权重排序,融合两个最低权重,用列表中的根替换两者,对列表进行排序(简单的插入就足够了),然后继续直到列表被简化为单个根节点。
  • 谢谢,我试试看。
猜你喜欢
  • 2013-11-16
  • 1970-01-01
  • 2011-12-03
  • 2015-11-09
  • 1970-01-01
  • 2010-09-05
  • 2019-02-24
  • 1970-01-01
  • 2010-12-14
相关资源
最近更新 更多