Huffman 树实现

合集下载

哈夫曼编码的实现及应用

哈夫曼编码的实现及应用

哈夫曼编码的实现及应用哈夫曼编码(Huffman Coding)是一种用于数据压缩的编码技术,它可以将数据中频繁出现的字符或符号用较短的编码表示,从而减小数据的存储或传输开销。

以下是哈夫曼编码的实现和应用:实现哈夫曼编码:1. 构建哈夫曼树:首先,需要收集数据中不同字符或符号的频率信息,然后根据这些频率构建哈夫曼树。

在哈夫曼树中,频率较高的字符位于树的较低部分,频率较低的字符位于树的较高部分。

2. 分配编码:从根节点开始,沿着哈夫曼树的路径向下,为每个字符分配唯一的编码。

左子树通常表示0,右子树表示1。

这确保了编码是前缀编码,即没有一个编码是另一个编码的前缀。

3. 编码数据:使用分配的编码,将原始数据中的字符替换为相应的编码,从而生成压缩的数据。

哈夫曼编码的应用:1. 数据压缩:哈夫曼编码广泛用于数据压缩领域,包括压缩文件、图像、音频和视频数据。

由于频率较高的字符使用较短的编码,哈夫曼编码可以显著减小文件大小。

2. 通信系统:在通信系统中,数据通常需要在网络上传输。

使用哈夫曼编码可以减小数据传输的带宽要求,提高通信效率。

3. 文本编辑器:哈夫曼编码可用于实现字典压缩,减小文本文件的大小,使其更容易存储和传输。

4. 图像压缩:JPEG图片格式使用了哈夫曼编码来压缩图像数据,减小图像文件的大小。

5. 音频压缩:MP3音频格式中的音频数据也使用了哈夫曼编码,以减小音频文件的大小。

6. 存储设备:存储设备,如硬盘和闪存驱动器,通常使用哈夫曼编码来提高存储效率,减小数据的物理存储需求。

哈夫曼编码是一种有效的数据压缩方法,可以在多个领域中应用,以减小数据的大小并提高数据传输和存储的效率。

不同应用领域可能会采用不同的编码方式,但核心原理是一致的。

哈夫曼树的建立及操作

哈夫曼树的建立及操作

哈夫曼树的建立及操作哈夫曼树是一种用于数据压缩的树形数据结构,可以有效地压缩数据并减小存储空间。

本文将介绍哈夫曼树的建立方法和相关操作。

一、哈夫曼树的建立方法:1.首先,我们需要统计给定数据中每个字符出现的频率。

频率越高的字符将被赋予较短的编码,从而实现数据的压缩。

可以使用一个字典或哈希表来记录字符及其频率。

2.创建一个包含所有字符频率的节点列表。

每个节点包含一个字符及其对应的频率。

3.排序节点列表,按照频率从小到大的顺序进行排序。

4.创建一个空的二叉树,并将频率最低的两个节点作为子节点,合并为一个新的节点。

新节点的频率为两个子节点的频率之和。

将这个新节点插入到节点列表中。

5.从节点列表中移除原先的两个子节点,插入新节点。

保持列表的有序性。

6.重复步骤4和5,直到节点列表中只剩下一个节点。

7.最后剩下的节点即为哈夫曼树的根节点。

二、哈夫曼树的操作:1.获取哈夫曼编码:根据哈夫曼树的结构,可以通过遍历树的路径来获取每个字符的编码。

左子树表示0,右子树表示1、从根节点出发,依次遍历所有叶子节点,记录下每个字符对应的路径即可得到编码。

2.数据压缩:将原始数据中的每个字符替换为对应的哈夫曼编码,从而实现数据压缩。

根据频率,越常见的字符编码越短,可以大幅减小数据存储的空间。

3.数据解压:使用相同的哈夫曼树,将压缩后的二进制编码解码为原始字符,从而还原数据。

4. 哈夫曼树的存储和传输:为了实现数据的压缩和解压缩,哈夫曼树需要存储和传输。

可以使用二进制格式存储树的结构和频率信息,并在解压缩时重新构建树。

还可以考虑使用霍夫曼编码的变种,如Adaptive Huffman Coding(自适应哈夫曼编码),使得树结构可以随着数据的变化进行更高效的编码和解码。

总结:哈夫曼树是一种用于数据压缩的树形数据结构,可以通过统计字符频率来生成树,并生成对应的编码。

通过编码,可以实现原始数据的高效压缩和解压缩。

在实际应用中,哈夫曼树被广泛应用于数据压缩,如文件压缩、图像压缩等。

哈夫曼树的实际应用

哈夫曼树的实际应用

哈夫曼树的实际应用
哈夫曼树(Huffman Tree)是一种重要的数据结构,它在信息编码和压缩、数据传输和存储、图像处理等领域有广泛应用。

1. 数据压缩:哈夫曼树是一种无损压缩的方法,能够有效地减小数据的存储空间。

在进行数据压缩时,可以使用哈夫曼树构建字符编码表,将出现频率较高的字符用较短的编码表示,而出现频率较低的字符用较长的编码表示,从而减小数据的存储空间。

2. 文件压缩:在文件压缩领域,哈夫曼树被广泛应用于压缩算法中。

通过构建哈夫曼树,可以根据字符出现的频率来生成不同长度的编码,从而减小文件的大小。

常见的文件压缩格式如ZIP、GZIP等都使用了哈夫曼树。

3. 图像压缩:在图像处理中,哈夫曼树被用于图像压缩算法中。

通过将图像中的像素值映射为不同长度的编码,可以减小图像的存储空间,提高图像传输和存储的效率。

常见的图像压缩格式如JPEG、PNG等都使用了哈夫曼树。

4. 文件传输:在数据传输中,哈夫曼树被用于数据压缩和传输。

通过对数据进行压缩,可以减小数据的传输时间和带宽占用。

在传输过程中,接收方可以通过哈夫曼树解码接收到的数据。

5. 数据加密:在数据加密中,哈夫曼树可以用于生成密钥,从而实现数据的加密和解密。

通过将字符映射为不同长度的编码,可以实
现对数据的加密和解密操作。

哈夫曼树在信息编码和压缩、数据传输和存储、图像处理等领域有广泛应用,能够有效地减小数据的存储空间、提高数据传输效率、实现数据加密等功能。

哈夫曼编码原理及方法

哈夫曼编码原理及方法

哈夫曼编码原理及方法哈夫曼编码(Huffman Coding)是一种变长编码(Variable Length Code)的压缩算法。

它的原理是将频率较高的字符用较短的编码,频率较低的字符用较长的编码,以此降低数据的传输成本。

下面将详细介绍哈夫曼编码的原理及方法。

一、哈夫曼编码的原理哈夫曼编码的原理基于贪心算法(Greedy Algorithm),即对每个要编码的字符进行评估,按照字符在文本中出现的频率多少,将频率高的字符赋予较短的编码,频率低的字符赋予较长的编码。

这样在实际使用中,字符出现频率越高的编码长度越短,从而达到压缩数据的目的。

二、哈夫曼编码的方法1. 构建哈夫曼树(Huffman Tree)构建哈夫曼树的过程首先要确定每个字符在文本中出现的频率,然后将每个字符看作一个节点,并按照其频率大小建立一个小根堆(Min Heap)。

接下来,选取频率最小的两个节点,将它们合并到一起作为一个新的节点,并更新频率值,然后继续重复以上步骤,直到堆中只剩下一个节点,即为哈夫曼树的根节点。

2. 生成哈夫曼编码生成哈夫曼编码可以采用递归的方式,从根节点开始向左遍历时,将标记为 0,向右遍历时,将标记为 1,直到叶节点为止,然后向上回溯,将遍历的结果保存下来,得到该叶节点的哈夫曼编码。

遍历完所有的叶子节点后,即可得到所有字符的哈夫曼编码。

3. 压缩数据在使用哈夫曼编码进行数据压缩时,将字符替换为其对应的哈夫曼编码,这样可以将原始数据压缩为更小的数据量,达到压缩数据的目的。

在解压数据时,需要根据已生成的哈夫曼树,将压缩后的数据转换为原始数据,即将哈夫曼编码转换为对应的字符。

三、哈夫曼编码的优缺点哈夫曼编码的优点是具有压缩比高、压缩速度快、压缩后的数据无损还原等特点,可以广泛用于图像、音频、视频等多种数据类型的压缩。

同时,由于哈夫曼编码采用变长编码方式,所以可以使用相对较短的编码表示经常出现的字符,从而达到更好的压缩效果。

huffman编码例题

huffman编码例题

huffman编码例题Huffman编码是一种流行的数据压缩技术,也是许多压缩软件中使用的算法。

它可以通过建立权值树来生成对应的固定长度编码,称为Huffman编码。

在本文中,我们将介绍Huffman编码的原理以及一个具体的例题。

一、Huffman编码原理Huffman编码的实现原理是基于贪心算法。

它的目的是将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,以达到压缩数据的目的。

具体实现步骤如下:1.统计每个字符出现的频率。

2.建立哈夫曼树,每个节点代表一个字符,节点的权重为字符出现的频率。

3.对哈夫曼树进行遍历,为每个字符生成对应的Huffman编码。

4.将字符串中的每个字符替换成对应的Huffman编码。

二、Huffman编码例题假设有一个字符串"hello world",请编写程序进行Huffman编码和解码。

1统计每个字符出现的频率 h:1 e:1 l:3 o:2 w:1 r:1 d:12建立哈夫曼树从频率最小的字符开始,依次合并至根节点,得到以下哈夫曼树:11/ \5 6/ \ / \2 3 3 3/ / \h r d3生成Huffman编码从根节点开始遍历哈夫曼树,向左走为"0",向右走为"1",生成以下Huffman编码: h: 100 e: 1010 l: 00 o: 1011 w: 1100 r: 1101 d: 11104进行编码和解码使用步骤三中的编码表,将字符串"hello world"分别编码为: 101000001111001011111001101000011010111011100解码时,从根节点开始依次读取编码,遇到"0"则向左走,遇到"1"则向右走,直到读取完整个编码,找到对应的字符。

将编码解析后得到的二进制数转成对应的字符,即可得到原字符串"hello world"。

哈夫曼编码树构建方法

哈夫曼编码树构建方法

哈夫曼编码树构建方法哈夫曼编码树(Huffman coding tree)是一种常用的数据压缩技术,通过利用字符出现的频率构建树结构来实现编码。

在本文中,我们将介绍哈夫曼编码树的构建方法,详细说明其原理和步骤,并以实例加以说明。

一、哈夫曼编码树的原理哈夫曼编码树的构建基于字符出现的频率,频率越高的字符编码越短。

该原理的关键在于使用较短的编码表示高频率的字符,从而实现数据压缩。

哈夫曼编码树是一棵二叉树,其中每个叶子节点表示一个字符,根据字符的频率形成不同深度的叶子节点。

通过从根节点到叶子节点的路径确定每个字符的编码。

二、哈夫曼编码树的构建步骤1. 统计每个字符的频率,得到字符频率表。

2. 将字符频率表转化为叶子节点集合。

3. 构建哈夫曼编码树的规则如下:- 从叶子节点集合中挑选两个频率最小的节点作为左右孩子,创建一个新的父节点。

- 将父节点的频率设置为左右孩子的频率之和。

- 将父节点加入叶子节点集合。

- 重复上述步骤,直到叶子节点集合中只剩一个节点,此节点即为根节点,哈夫曼编码树构建完成。

三、哈夫曼编码树构建实例以下是一个构建哈夫曼编码树的实例,假设有四个字符A、B、C、D及其对应的频率如下表所示:字符频率A 10B 20C 30D 401. 根据字符的频率,按照从小到大的顺序排序如下:A(10) < B(20) < C(30) < D(40)2. 从叶子节点集合中选取频率最小的两个节点A(10)和B(20),构建一个新的父节点AB(30)。

3. 更新叶子节点集合,得到如下序列:AB(30) < C(30) < D(40)4. 从叶子节点集合中选取频率最小的两个节点AB(30)和C(30),构建一个新的父节点ABC(60)。

5. 更新叶子节点集合,得到如下序列:ABC(60) < D(40)6. 从叶子节点集合中选取频率最小的两个节点D(40)和ABC(60),构建一个新的父节点ABCD(100)。

哈夫曼编码详解(C语言实现)

哈夫曼编码详解(C语言实现)

哈夫曼编码详解(C语言实现)哈夫曼编码是一种常见的前缀编码方式,被广泛应用于数据压缩和传输中。

它是由大卫·哈夫曼(David A. Huffman)于1952年提出的,用于通过将不同的字符映射到不同长度的二进制码来实现数据的高效编码和解码。

1.统计字符频率:遍历待编码的文本,记录每个字符出现的频率。

2.构建哈夫曼树:根据字符频率构建哈夫曼树,其中出现频率越高的字符位于树的较低层,频率越低的字符位于树的较高层。

3.生成编码表:从哈夫曼树的根节点开始,遍历哈夫曼树的每个节点,为每个字符生成对应的编码。

在遍历过程中,从根节点到叶子节点的路径上的“0”表示向左,路径上的“1”表示向右。

4.进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。

5.进行解码:根据生成的编码表和编码结果,将编码替换为原始字符。

下面是一个用C语言实现的简单哈夫曼编码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>//定义哈夫曼树的节点结构体typedef struct HuffmanNodechar data; // 字符数据int freq; // 字符出现的频率struct HuffmanNode *left; // 左子节点struct HuffmanNode *right; // 右子节点} HuffmanNode;//定义编码表typedef structchar data; // 字符数据char *code; // 字符对应的编码} HuffmanCode;//统计字符频率int *countFrequency(char *text)int *frequency = (int *)calloc(256, sizeof(int)); int len = strlen(text);for (int i = 0; i < len; i++)frequency[(int)text[i]]++;}return frequency;//创建哈夫曼树HuffmanNode *createHuffmanTree(int *frequency)//初始化叶子节点HuffmanNode **leaves = (HuffmanNode **)malloc(256 * sizeof(HuffmanNode *));for (int i = 0; i < 256; i++)if (frequency[i] > 0)HuffmanNode *leaf = (HuffmanNode*)malloc(sizeof(HuffmanNode));leaf->data = (char)i;leaf->freq = frequency[i];leaf->left = NULL;leaf->right = NULL;leaves[i] = leaf;} elseleaves[i] = NULL;}}//构建哈夫曼树while (1)int min1 = -1, min2 = -1;for (int i = 0; i < 256; i++)if (leaves[i] != NULL)if (min1 == -1 , leaves[i]->freq < leaves[min1]->freq) min2 = min1;min1 = i;} else if (min2 == -1 , leaves[i]->freq < leaves[min2]->freq)min2 = i;}}}if (min2 == -1)break;}HuffmanNode *parent = (HuffmanNode*)malloc(sizeof(HuffmanNode));parent->data = 0;parent->freq = leaves[min1]->freq + leaves[min2]->freq;parent->left = leaves[min1];parent->right = leaves[min2];leaves[min1] = parent;leaves[min2] = NULL;}HuffmanNode *root = leaves[min1];free(leaves);return root;//生成编码表void generateHuffmanCode(HuffmanNode *root, HuffmanCode *huffmanCode, char *code, int depth)if (root->left == NULL && root->right == NULL)code[depth] = '\0';huffmanCode[root->data].data = root->data;huffmanCode[root->data].code = strdup(code);return;}if (root->left != NULL)code[depth] = '0';generateHuffmanCode(root->left, huffmanCode, code, depth + 1);}if (root->right != NULL)code[depth] = '1';generateHuffmanCode(root->right, huffmanCode, code, depth + 1);}//进行编码char *encodeText(char *text, HuffmanCode *huffmanCode)int len = strlen(text);int codeLen = 0;char *code = (char *)malloc(len * 8 * sizeof(char));for (int i = 0; i < len; i++)strcat(code + codeLen, huffmanCode[(int)text[i]].code);codeLen += strlen(huffmanCode[(int)text[i]].code);}return code;//进行解码char* decodeText(char* code, HuffmanNode* root) int len = strlen(code);char* text = (char*)malloc(len * sizeof(char)); int textLen = 0;HuffmanNode* node = root;for (int i = 0; i < len; i++)if (code[i] == '0')node = node->left;} elsenode = node->right;}if (node->left == NULL && node->right == NULL) text[textLen] = node->data;textLen++;node = root;}}text[textLen] = '\0';return text;int maichar *text = "Hello, World!";int *frequency = countFrequency(text);HuffmanNode *root = createHuffmanTree(frequency);HuffmanCode *huffmanCode = (HuffmanCode *)malloc(256 * sizeof(HuffmanCode));char code[256];generateHuffmanCode(root, huffmanCode, code, 0);char *encodedText = encodeText(text, huffmanCode);char *decodedText = decodeText(encodedText, root);printf("Original Text: %s\n", text);printf("Encoded Text: %s\n", encodedText);printf("Decoded Text: %s\n", decodedText);//释放内存free(frequency);free(root);for (int i = 0; i < 256; i++)if (huffmanCode[i].code != NULL)free(huffmanCode[i].code);}}free(huffmanCode);free(encodedText);free(decodedText);return 0;```上述的示例代码实现了一个简单的哈夫曼编码和解码过程。

哈夫曼树和哈夫曼编码的原理和应用领域

哈夫曼树和哈夫曼编码的原理和应用领域

哈夫曼树和哈夫曼编码的原理和应用领域哈夫曼树(Huffman Tree)和哈夫曼编码(Huffman Coding)是数据压缩领域中常用的算法。

哈夫曼编码通过对出现频率较高的字符使用较短的编码,对出现频率较低的字符使用较长的编码,从而实现对数据进行高效压缩。

本文将介绍哈夫曼树和哈夫曼编码的原理以及它们在通信和存储领域的应用。

一、哈夫曼树的原理哈夫曼树是一种特殊的二叉树,它的构建基于贪心算法。

首先,根据字符出现的频率构建一组叶子节点,每个叶子节点代表一个字符,并且带有该字符出现的频率。

接着,从这组叶子节点中选择出现频率最低的两个节点,将它们合并成一个新的节点,并将这个新节点的频率设置为两个节点频率之和。

新节点成为新的叶子节点,参与下一次的合并。

重复这个过程,直到最终只剩下一个节点,即为哈夫曼树的根节点。

二、哈夫曼编码的原理在哈夫曼树构建完成后,我们根据哈夫曼树的结构来为每个字符生成对应的编码。

对于每个字符,从根节点出发,向左子树走表示添加编码的0,向右子树走表示添加编码的1,直到到达叶子节点。

将每个字符的编码保存起来,就得到了哈夫曼编码。

由于哈夫曼树的构建过程保证了频率较高的字符拥有较短的编码,而频率较低的字符拥有较长的编码,所以哈夫曼编码具有前缀码的特性。

即任何一个字符的编码都不是其他字符编码的前缀,这样在进行解码的时候就不会出现歧义。

三、哈夫曼编码的应用领域1. 数据压缩:哈夫曼编码常被用于数据的无损压缩,通过将频率较高的字符用较短的编码表示,可以大大减小数据的存储空间。

2. 文件传输:在文件传输过程中,为了减小文件的大小,常常会使用哈夫曼编码对文件进行压缩,减少网络传输的时间和带宽占用。

3. 图像压缩:哈夫曼编码在图像压缩中也有广泛的应用。

通过对图像像素点进行编码,可以显著减小图像文件的体积,提高图像在传输和存储中的效率。

4. 视频压缩:在视频压缩中,哈夫曼编码被用于对视频帧中的运动矢量、亮度和色度信息进行编码,从而减小视频文件的大小。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#pragma once#include<iostream>using namespace std;template<typename T>class MinHeap{public:MinHeap(int n);~MinHeap();void BuildHeap();int Parent(int pos);int leftChild(int pos);int rightChild(int pos);bool isLeaf(int pos);bool Remove(int pos,T & node);bool Insert(const T & newNode);T & RemoveMin();void shiftDown(int pos);void shiftUp(int pos);void swap(int sizex,int sizey);//private:T * heapArray;int currentSize;int maxSize;};template<typename T>MinHeap<T>::MinHeap(int n){if(n <= 0){return;}maxSize = n;currentSize = 0;//数ºy组Á¨¦下?标À¨º从䨮0开a始º?heapArray = new T[maxSize];this->BuildHeap();}template<typename T>MinHeap<T>::~MinHeap(){delete heapArray;}template<typename T>void MinHeap<T>::BuildHeap(){for(int i = currentSize / 2 - 1; i >= 0 ; i--){ this->shiftDown(i);}}template<typename T>int MinHeap<T>::Parent(int pos){return (pos - 1) / 2;}template<typename T>int MinHeap<T>::leftChild(int pos){return (pos + 1) * 2 - 1;}template<typename T>int MinHeap<T>::rightChild(int pos){return (pos + 1) * 2;}template<typename T>bool MinHeap<T>::isLeaf(int pos){return (pos >= currentSize/2) && (pos < currentSize);}template<typename T>bool MinHeap<T>::Insert(const T & newNode){if(currentSize == maxSize){cerr<<"The heap is fulling."<<endl;return false;}heapArray[currentSize] = newNode;currentSize++;shiftUp(currentSize - 1);return true;}template<typename T>void MinHeap<T>::shiftDown(int pos){int i = pos; // 标À¨º识º?父?结¨¢点Ì?int j = leftChild (i); // 标À¨º识º?关?键¨¹值¦Ì较?小?的Ì?子Á¨®结¨¢点Ì?T temp = heapArray[i]; // 保À¡ê存ä?父?结¨¢点Ì?while (j < currentSize) { // 过y筛¦?if ((j < currentSize-1) && (heapArray[j]>heapArray[j + 1]))//若¨?有®D右®¨°子Á¨®节¨²点Ì?,ê?且¨°小?于®¨²左Á¨®子Á¨®节¨²点Ì?j++; // j指?向¨°右®¨°子Á¨®结¨¢点Ì?if (temp>heapArray[j]) { //若¨?父?节¨²点Ì?大䨮于®¨²子Á¨®节¨²点Ì?的Ì?值¦Ì则¨°交?换?位?置?heapArray[i] = heapArray[j];i = j;j = leftChild(j); }else break; //堆?序¨°满¨²足Á?,ê?跳¬?出?}heapArray[i] = temp;//ruguoniyuanyi}template<typename T>bool MinHeap<T>::Remove(int pos,T & node){if((pos < 0) || (pos >= currentSize)){cerr<<"The pos hvent node which name is "<<pos<<endl;return false;}node = heapArray[pos];heapArray[pos] = heapArray[--currentSize];if(heapArray[Parent(pos)] > heapArray[pos]){shiftUp(pos);}else{shiftDown(pos);}return true;}template<typename T>T & MinHeap<T>::RemoveMin(){if(currentSize <= 0){cerr<<"The heap is already empty."<<endl;exit(-1);}swap(0,--currentSize);// 交?换?堆?顶£¤和¨ª最Á?后¨®一°?个?元a素?if(currentSize > 1){shiftDown(0);}return heapArray[currentSize];}template<typename T>void MinHeap<T>::shiftUp(int pos){int temppos = pos;T temp = heapArray[temppos];while ((temppos>0) && (heapArray[Parent(temppos)]>temp)) { heapArray[temppos] = heapArray[Parent(temppos)];temppos = Parent(temppos);}heapArray[temppos] = temp;}template<typename T>void MinHeap<T>::swap(int sizex,int sizey){T temp = this->heapArray[sizex];this->heapArray[sizex] = this->heapArray[sizey];this->heapArray[sizey] = temp;}//HuffmanTreeNode.h#pragma oncetemplate<typename T>class HuffmanTreeNode{public:HuffmanTreeNode();bool operator < (HuffmanTreeNode<T> & obj2);bool operator > (HuffmanTreeNode<T> & obj2);//private:int element;T data;HuffmanTreeNode * rightchild;HuffmanTreeNode * leftchild;HuffmanTreeNode * parent;};template<typename T>bool HuffmanTreeNode<T>::operator < (HuffmanTreeNode<T> & obj2){ return this->element < obj2.element;}template<typename T>bool HuffmanTreeNode<T>::operator > (HuffmanTreeNode<T> & obj2){ return this->element > obj2.element;}template<typename T>HuffmanTreeNode<T>::HuffmanTreeNode(){element = 0;data = NULL;rightchild = NULL;leftchild = NULL;parent = NULL;}//HuffmanTree.h#pragma once#include"MinHeap.h"#include<queue>#include<fstream>#include<string>#include"HuffmanTreeNode.h"template<typename T>class HuffmanTree{public:HuffmanTree(int weight[],int n);~HuffmanTree(){};void MergeTree(HuffmanTreeNode<T> & ht1,HuffmanTreeNode<T> &ht2,HuffmanTreeNode<T> * parent);void DeleteTree(HuffmanTreeNode<T> * root);void levelOrder(HuffmanTreeNode<T> * root);void Generate();void Tranverse(HuffmanTreeNode<T> * pTree,string str);void preOrder(HuffmanTreeNode<T> * root){if(root != NULL){if(root->leftchild == NULL && root->rightchild == NULL)cout<<root->data<<endl;preOrder(root->leftchild);preOrder(root->rightchild);}}void decoding();HuffmanTreeNode<T> * root;};template<typename T>HuffmanTree<T>::HuffmanTree(int weight[],int n){//bulid the huffman treeMinHeap<HuffmanTreeNode<T>> heap(n);HuffmanTreeNode<T> * parent, * firstchild, * secondchild;HuffmanTreeNode<T> * NodeList = new HuffmanTreeNode<T>[n];int index = 0;for(int i = 0 ; i < n ; i++){if(weight[i] == 0){continue;}NodeList[index].element = weight[i];NodeList[index].data = i;NodeList[index].parent = NodeList[index].rightchild = NodeList[index].leftchild = NULL;heap.Insert(NodeList[index]);index++;}for(int i = 0 ; i < index - 1 ; i++){parent = new HuffmanTreeNode<T>;firstchild = new HuffmanTreeNode<T>();secondchild = new HuffmanTreeNode<T>();*firstchild = heap.RemoveMin();;*secondchild = heap.RemoveMin();MergeTree(*firstchild,*secondchild,parent);heap.Insert(*parent);root = parent;}delete [] NodeList;}template<typename T>//merge the ht1 tree and the ht2 tree...void HuffmanTree<T>::MergeTree(HuffmanTreeNode<T> &ht1,HuffmanTreeNode<T> & ht2,HuffmanTreeNode<T> * parent){ parent->leftchild = &ht1;parent->rightchild = &ht2;parent->element = ht1.element + ht2.element;parent->parent = NULL;ht1.parent = ht2.parent = parent;}template<typename T>void HuffmanTree<T>::levelOrder(HuffmanTreeNode<T> * root){ queue<HuffmanTreeNode<T> *> nodeQueue;//用队列储存将要访问的结点HuffmanTreeNode<T> * pointer = root;if(pointer != NULL){nodeQueue.push(pointer);}while(!nodeQueue.empty()){pointer = nodeQueue.front();//if(pointer->leftchild == NULL && pointer->rightchild == NULL)cout<<pointer->data<<endl;nodeQueue.pop();if(pointer->leftchild){nodeQueue.push(pointer->leftchild);}if(pointer->rightchild){nodeQueue.push(pointer->rightchild);}}}template<typename T>void HuffmanTree<T>::Generate(){//递归调用生成哈弗曼编码string str;this->Tranverse(root,str);}template<typename T>void HuffmanTree<T>::Tranverse(HuffmanTreeNode<T> * pointer,string str){if(pointer == NULL){return;}ofstream outFile;outFile.open("output.txt",ios_base::app);//采用追加操作if(!outFile){cerr<<"Can't open the output txt"<<endl;exit(-1);}if(pointer->leftchild == NULL && pointer->rightchild == NULL){//是叶结点,递归结束outFile<<pointer->data<<'\t'<<str<<endl;for(int i = 0 ; i < str.length() ; i++){code[pointer->data][i] = str[i];}//cout<<pointer->data<<" "<<str<<" "<<str.length()<<endl;outFile.close();return;}//非叶结点this->Tranverse(pointer->leftchild,str + "0");this->Tranverse(pointer->rightchild,str + "1");}template<typename T>void HuffmanTree<T>::decoding(){//解码,解读的decoding文件中01字符串,并将解读后的文件输出到屏幕ifstream inFile("decoding.txt");if(!inFile){cerr<<"Can't open the decoding.txt"<<endl;exit(-1);}char c = '0';HuffmanTreeNode<T> * pointer = root;while(inFile>>c){if(c == '1'){pointer = pointer->rightchild;}else if(c == '0'){pointer = pointer->leftchild;}else{return;}if(pointer->leftchild == NULL && pointer->rightchild == NULL){ cout<<pointer->data;pointer = root;}}}//main.cpp#include"HuffmanTree.h"#include<fstream>#include<iostream>using namespace std;int weight[128];//记录每个字符产生的次数char code[128][20];//记录每个字符对应产生的编码void reader_the_file(){//通过读文件得到weight[]memset(weight,0,sizeof(weight));ifstream inFile("input.txt");if(!inFile){cerr<<"Can't open the iutput.txt"<<endl;exit(-1);}char c = '0';while(inFile>>c){weight[(int)c]++;}inFile.close();}void fliter(){//fliter the number of the minimum nad maximum;int temp = 100000;int index = 0;for(int i = 0 ; i < 128 ; i++){//delete the maximum num if(weight[i] > 0){if(weight[i] < temp){temp = weight[i];index = i;}}}weight[index] = 0;temp = -1;for(int i = 0 ; i < 128 ; i++){//delete the minimum num if(weight[i] > 0){if(weight[i] > temp){temp = weight[i];index = i;}}}weight[index] = 0;}void encoding(){//编码,并将已经解码的后的结果存入decoding文件ifstream inFile("input.txt");if(!inFile){cerr<<"Can't open the iutput.txt"<<endl;exit(-1);}ofstream outFile;outFile.open("decoding.txt",ios_base::app);if(!outFile){cerr<<"Can't open the decodingt.txt"<<endl;exit(-1);}char c = '0';while(inFile>>c){outFile<<code[(int)c];}}int main(){reader_the_file();fliter();HuffmanTree<char> man(weight,128);man.Generate();//产生编码/* for(int i = 0 ; i < 128 ; i++){cout<<code[i]<<endl;}*/encoding();man.decoding();// man.levelOrder(man.root);// man.preOrder(man.root);return 0;}。

相关文档
最新文档