【问题标题】:How to traverse a Huffman Tree recursively in search for an specific element? - C如何递归遍历霍夫曼树以搜索特定元素? - C
【发布时间】:2015-12-22 01:07:45
【问题描述】:

我正在使用 Huffman 代码,目前正处于将文本文件编码/解码为二进制文件的阶段。我有这段代码可以从树中检索一个节点及其所有相关数据(字符、频率、路线):

EmptyString ( string );
while ( ( c = fgetc ( nameTextFile ) ) != EOF ) {
    nodeHuffmanTree = SearchHuffmanTree ( rootHuffmanTree, c );
    strcpy ( string, nodeHuffmanTree -> route );
    Encode ( nameBinaryFile, string );
    EmptyString ( string );
}

假设每个节点(0 和 1)的路由已经生成。 SearchHuffmanTree 函数我想要的是,给定一个字符,它会在 Huffman 树中搜索该字符,并返回包含它的节点。这是相关的,因为该节点将包含 Encode 函数将转换为字节的路由。

我知道我不能将霍夫曼树视为二叉搜索树,因为它不具有相同的特征,所以如果我想搜索特定字符,我必须遍历整个树。

我已经寻找了不使用递归的替代方案(在某些情况下还使用了堆栈),虽然它们更容易理解,但它们生成的代码却相当不简单和干净,所以我更喜欢使用递归的解决方案。

我已经弄清楚了编码/解码部分,所以这几乎是最终完成我的代码的最后一步。期待您能给我的任何帮助。

【问题讨论】:

  • 提示:查看根节点,然后是左子树,然后是右子树。
  • @immibis 您的意思是遍历整棵树 Pre Order、In Order 还是 Post Order?我已经尝试过了,但是该函数似乎没有检索到具有我正在寻找的字符的节点,而是程序停止工作。也许我做错了什么,但我不知道为什么。我可以编辑问题,添加我想出的内容,所以也许你可以指出我哪里出错了。
  • 构建哈夫曼树后,您应该使用它来创建一个编码数组,它只是一个由 256 个结构组成的数组,其中每个结构都包含一个位模式和一个长度。这样,输入字符可以用作数组的索引以便快速查找。
  • @ShadowGeist 好吧,实际顺序并不重要,只要您查看每个节点即可。如果您的程序停止工作,那么您应该找出原因并修复它。

标签: c recursion huffman-code


【解决方案1】:

是的,您不能假设任何特定节点(即字符)在您的树中的位置,因为节点的位置取决于字符的频率而不是它们的值。因此,您必须找到一种方法来遍历整个树,而不做任何假设。

一般有两种遍历图的方法:基于队列的广度优先搜索 (BFS) 和基于堆栈的深度优先搜索 (DFS)。

由于 DFS 是基于堆栈的,它本质上是一个递归问题。此外,由于 2 种方法遍历树的方式不同,在您的情况下,DFS 平均效率会更高。

DFS 是如何工作的?

嗯,基本原则是,如果一个节点不是叶子,则对其每个子节点执行 DFS。如果您选择遍历子树的顺序,则可以先选择概率最高的路径,这样可以增加更快找到结果的机会。

下面是一个简单的算法伪代码:

DFS(node T, char x) {
    if (T is leaf)
        if (T == x)
            return found
        else
            return not found
    else
        foreach child of T
            if DFS(child, x) == found
                return found
        return not found

您可以在DFS 的维基百科页面上找到更多详细信息。

【讨论】:

  • 此解决方案是否避免使用其他数据结构?我已经在使用堆栈为树中的每个节点生成路由(堆栈使用 char 数组)。我有点想避免使用第二个堆栈来存储其他类型的元素。
  • 是的,确实如此。您可以使用不必实现的递归堆栈。实际上,我在我展示的伪代码中使用了它。
  • 只有一个问题。该伪代码用于通用树。我如何将foreach child of T 部分翻译成我的特殊情况,即只有两个孩子的树?
  • 在 else 分支中,您可以为给定节点的每个子节点调用 DFS,而无需 for 循环(即 DFS(node.left, x) 和 DFS(node.right, x))。请注意,您可能需要检查孩子是否真的存在
猜你喜欢
  • 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
相关资源
最近更新 更多