哈夫曼编码和解码

哈夫曼编码方法:

1、统计字符集中每个字符在电文中出现的平均概率(概率越大,要求编码越短)。

2、利用哈夫曼树的特点:权越大的叶子离根越近;将每个字符的概率值作为权值,构造哈夫曼树。则概率越大的结点,路径越短。

3、在哈夫曼树的每个分支上标上0或1,结点的左分支标0,右分支标1,把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码。

哈夫曼解码方法:

根据编码规则在哈夫曼树中寻找叶子结点。

代码实现:

类型定义以及宏定义:

#define ArraySize 8

typedef struct HuffmanEnCode
{
    int uncode;
    int start;
    char code[ArraySize];
} HuffmanEnCode; // 哈夫曼编码结果数组类型定义

typedef struct HuffmanDecode
{
    char code[ArraySize];
    int uncode;
} HuffmanDeCode; // 哈夫曼解码结果数组类型定义

主函数:

int main()
{
    //------------------------------创建哈夫曼树----------------------------------//

    int WeightArray[ArraySize] = {7, 19, 2, 6, 32, 3, 21, 10}; // 权重数组
    HuffmanTreeNode HTree[2 * ArraySize];                      // 创建哈夫曼树的存储结构体数组
    InitHuffmanTree(HTree, 2 * ArraySize);                     // 初始化结构体数组
    CreateHuffmanTree(WeightArray, ArraySize, HTree);          // 创建哈夫曼树
    Print(HTree, 2 * ArraySize);                               // 打印结果
    printf("\n");

    //------------------------------哈夫曼编码----------------------------------//

    HuffmanEnCode HC[ArraySize + 1]; // 哈夫曼编码结果数组
    GenerateHuffmanCode(HTree, HC);  // 哈夫曼编码
    Show1(HC);                       // 编码结果显示
    printf("\n");

    //------------------------------哈夫曼解码----------------------------------//
    HuffmanDeCode HDC[ArraySize + 1]; // 哈夫曼解码结果数组
    Huffman_Decoding(HTree, HC, HDC); // 哈夫曼解码
    Show2(HDC);                       // 解码结果显示
    printf("\n");
    return 0;
}

创建哈夫曼树的内容:https://blog.csdn.net/m0_69251699/article/details/130670917

所创建的哈夫曼树的示意图:

哈夫曼编码函数:

void GenerateHuffmanCode(HuffmanTreeNode *Tree, HuffmanEnCode *HC)
{
    int Parent, Child, i, j;
    for (i = 1; i <= ArraySize; i++)
    {
        HC[i].uncode = Tree[i].weight;
        HC[i].code[ArraySize - 1] = '\0';
        j = ArraySize - 2;
        Parent = Tree[i].parent;
        Child = i;
        while (Parent != 0)
        {
            if (Tree[Parent].left == Child)
            {
                HC[i].code[j] = '0';
            }
            else
            {
                HC[i].code[j] = '1';
            }
            Child = Parent;
            Parent = Tree[Parent].parent;
            j--;
        }
        HC[i].start = j + 1;
    }
}

 哈夫曼编码结果显示函数:

void Show1(HuffmanEnCode *HC)
{
    printf("uncode\t\tcode\n");
    for (int i = 1; i <= ArraySize; i++)
    {
        printf("%d\t\t%s\n", HC[i].uncode, HC[i].code + HC[i].start);
    }
}

哈夫曼解码函数:

void Huffman_Decoding(HuffmanTreeNode *Tree, HuffmanEnCode *HC, HuffmanDeCode *HDC)
{
    int i, j, point;
    for (i = 1; i <= ArraySize; i++)
    {
        strcpy(HDC[i].code, HC[i].code + HC[i].start);
        j = 0;
        point = RootNode(Tree);
        while (HDC[i].code[j] != '\0')
        {
            if (HDC[i].code[j] == '0')
            {
                point = Tree[point].left;
            }
            else
            {
                point = Tree[point].right;
            }
            j++;
        }
        HDC[i].uncode = Tree[point].weight;
    }
}

根结点寻找函数:

int RootNode(HuffmanTreeNode *Tree)
{
    for (int i = 1; i < 2 * ArraySize; i++)
    {
        if (Tree[i].parent == 0)
        {
            return i;
        }
    }
}

哈夫曼解码结果显示函数:

void Show2(HuffmanDeCode *HDC)
{
    printf("code\t\tuncode\n");
    for (int i = 1; i <= ArraySize; i++)
    {
        printf("%s\t\t%d\n", HDC[i].code, HDC[i].uncode);
    }
}

程序运行结果:

哈夫曼树创建结果:

哈夫曼编码结果:

哈夫曼解码结果:

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
哈夫曼编码是一种常用的数据压缩算法,它通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现对数据的压缩。以下是哈夫曼编码解码的基本步骤: 1. 统计字符频率:遍历待编码的文本,统计每个字符出现的频率。 2. 构建哈夫曼树:根据字符频率构建哈夫曼树。哈夫曼树是一种特殊的二叉树,其中每个叶子节点代表一个字符,而非叶子节点代表字符频率之和。 3. 生成编码表:从根节点开始,遍历哈夫曼树的路径,左子树路径标记为0,右子树路径标记为1,将每个字符对应的路径记录下来,形成编码表。 4. 进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。 5. 进行解码:使用相同的哈夫曼树和编码表,将编码后的数据进行解码,恢复原始文本。 在C#中实现哈夫曼编码解码可以按照以下步骤进行: 1. 定义字符频率统计函数:遍历待编码的文本,统计每个字符出现的频率。 2. 构建哈夫曼树:根据字符频率构建哈夫曼树。可以使用优先队列(PriorityQueue)来实现。 3. 生成编码表:从根节点开始,遍历哈夫曼树的路径,左子树路径标记为0,右子树路径标记为1,将每个字符对应的路径记录下来,形成编码表。 4. 进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。 5. 进行解码:使用相同的哈夫曼树和编码表,将编码后的数据进行解码,恢复原始文本。 以下是C#代码示例: ```csharp // 定义节点类 class Node { public char Character { get; set; } public int Frequency { get; set; } public Node Left { get; set; } public Node Right { get; set; } } // 构建哈夫曼树 private static Node BuildHuffmanTree(Dictionary<char, int> frequencies) { var priorityQueue = new PriorityQueue<Node>(Comparer<Node>.Create((a, b) => a.Frequency - b.Frequency)); foreach (var kvp in frequencies) { priorityQueue.Enqueue(new Node { Character = kvp.Key, Frequency = kvp.Value }); } while (priorityQueue.Count > 1) { var left = priorityQueue.Dequeue(); var right = priorityQueue.Dequeue(); var parent = new Node { Frequency = left.Frequency + right.Frequency, Left = left, Right = right }; priorityQueue.Enqueue(parent); } return priorityQueue.Dequeue(); } // 生成编码表 private static Dictionary<char, string> GenerateCodeTable(Node root) { var codeTable = new Dictionary<char, string>(); TraverseTree(root, "", codeTable); return codeTable; } // 遍历哈夫曼树,生成编码表 private static void TraverseTree(Node node, string code, Dictionary<char, string> codeTable) { if (node.Left == null && node.Right == null) { codeTable[node.Character] = code; return; } TraverseTree(node.Left, code + "0", codeTable); TraverseTree(node.Right, code + "1", codeTable); } // 进行编码 private static string Encode(string text, Dictionary<char, string> codeTable) { var encodedText = new StringBuilder(); foreach (var c in text) { encodedText.Append(codeTable[c]); } return encodedText.ToString(); } // 进行解码 private static string Decode(string encodedText, Node root) { var decodedText = new StringBuilder(); var currentNode = root; foreach (var bit in encodedText) { if (bit == '0') { currentNode = currentNode.Left; } else if (bit == '1') { currentNode = currentNode.Right; } if (currentNode.Left == null && currentNode.Right == null) { decodedText.Append(currentNode.Character); currentNode = root; } } return decodedText.ToString(); } // 示例用法 string text = "Hello, World!"; Dictionary<char, int> frequencies = new Dictionary<char, int>(); foreach (var c in text) { if (frequencies.ContainsKey(c)) { frequencies[c]++; } else { frequencies[c] = 1; } } Node root = BuildHuffmanTree(frequencies); Dictionary<char, string> codeTable = GenerateCodeTable(root); string encodedText = Encode(text, codeTable); string decodedText = Decode(encodedText, root); Console.WriteLine("Encoded Text: " + encodedText); Console.WriteLine("Decoded Text: " + decodedText); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值