哈夫曼编码算法实现完整版[终稿]
哈夫曼编码算法实现
哈夫曼编码(Huffman Coding)是一种常见的数据压缩算法,它通过构建哈夫曼树(Huffman Tree)来实现。
以下是一个简单的哈夫曼编码算法的实现示例,使用Python 语言:pythonCopy codeimport heapqfrom collections import defaultdictclass HuffmanNode:def __init__(self, char, frequency):self.char = charself.frequency = frequencyself.left = Noneself.right = Nonedef __lt__(self, other):return self.frequency < other.frequencydef build_huffman_tree(data):frequency = defaultdict(int)for char in data:frequency[char] += 1priority_queue = [HuffmanNode(char, freq) for char, freq in frequency.items()]heapq.heapify(priority_queue)while len(priority_queue) > 1:node1 = heapq.heappop(priority_queue)node2 = heapq.heappop(priority_queue)merged_node = HuffmanNode(None, node1.frequency + node2.frequency)merged_node.left = node1merged_node.right = node2heapq.heappush(priority_queue, merged_node)return priority_queue[0]def build_huffman_codes(root, current_code="", codes={}):if root:if root.char is not None:codes[root.char] = current_codebuild_huffman_codes(root.left, current_code + "0", codes)build_huffman_codes(root.right, current_code + "1", codes)return codesdef huffman_encoding(data):if not data:return None, Noneroot = build_huffman_tree(data)codes = build_huffman_codes(root)encoded_data = "".join([codes[char] for char in data])return encoded_data, rootdef huffman_decoding(encoded_data, root):if not encoded_data or not root:return Nonecurrent_node = rootdecoded_data = ""for bit in encoded_data:if bit == "0":current_node = current_node.leftelse:current_node = current_node.rightif current_node.char is not None:decoded_data += current_node.charcurrent_node = rootreturn decoded_data# 示例data = "abracadabra"encoded_data, tree_root = huffman_encoding(data) decoded_data = huffman_decoding(encoded_data, tree_root)print("Original data:", data)print("Encoded data:", encoded_data)print("Decoded data:", decoded_data)。
(2021年整理)哈夫曼编码_汉明编码
(完整)哈夫曼编码_汉明编码编辑整理:尊敬的读者朋友们:这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望((完整)哈夫曼编码_汉明编码)的内容能够给您的工作和学习带来便利。
同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。
本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为(完整)哈夫曼编码_汉明编码的全部内容。
1 课题描述信息论理论基础的建立,一般来说开始与香农(C.E。
Shannon)在研究通信系统时所发表的论文。
信息论是在信息可以度量的基础上,对如何有效、可靠的传递信息进行研究的科学,它涉及信息亮度、信息特性、信息传输速率、信道容量、干扰对信息传输的影响等方面的知识。
通常把上述范围的信息论称为狭义信息论,又因为它的创始人是香农,故又称为香农信息论。
广义信息论则包含通信的全部统计问题的研究,除了香农信息论之外,还包括信号设计、噪声理论、信号的检测与估值等。
当信息在传输、存储和处理的过程中,不可避免的要受到噪声或其他无用信号的干扰时,信息理论会为可靠、有效的从数据中提取信息提供必要的根据和方法。
因此必须研究噪声和干扰的性质以及它们与信息本质上的差别,噪声与干扰往往具有某种统计规律的随机特性,信息则具有一定的概率特性,如度量信息量的熵值就是概率性质的。
信息论、概率轮、随机过程和数理统计学是信息论应用的基础和工具。
信息论主要研究如何提高信息系统的可靠性、有效性、保密性和认证性,以使信息系统最优化.所谓可靠性高就是要使信源发出的消息经过信道传输以后,尽可能准确的、不失真的再现在接收端;而所谓有效性高,就是经济效果好,即用尽可能少的资源和尽可能少的设备来传送一定数量的信息;所谓保密性就是隐蔽和保护通信系统中传送的信息,使它只能被授权接受者获取,而不能被未授权者接受和理解;而认证性是指接受者能正确的判断所接受的消息的正确性,验证消息的完整性,而不是接收伪造的和被修改的信息。
Matlab函数实现哈夫曼编码算法讲解--实用.doc
编写 Matlab 函数实现哈夫曼编码的算法一、设计目的和意义在当今信息化代,数字信号充斥着各个角落。
在数字信号的理和中,信源是首先遇到的,一个信源的好坏劣直接影响到了后面的理和。
如何无失真地,如何使的效率最高,成了大家研究的象。
哈夫曼就是其中的一种,哈夫曼是一种的方案。
它由最二叉既哈夫曼得到,元内容到根点的路径中与父点的左右子的。
所以哈夫曼在在数字通信中有着重要的意。
可以根据信源符号的使用概率的高低来确定元的度。
既了信源的无失真地,又使得的效率最高。
二、设计原理哈夫曼 (Huffman Coding) 是一种方式,哈夫曼是可字 (VLC) 的一种。
uffman 于 1952 年提出一种方法,方法完全依据字符出概率来构造异字的平均度最短的字,有称之最佳,一般就叫作 Huffman 。
而哈夫曼的第一步工作就是构造哈夫曼。
哈夫曼二叉的构造方法原如下,假有 n 个,构造出的哈夫曼有 n 个叶子点。
n 个分 w1、 w2、⋯、wn,哈夫曼的构造:(1)将 w1、w2、⋯,wn 看成是有 n 棵的森林 (每棵有一个点 );(2)在森林中出两个根点的最小的合并,作一棵新的左、右子,且新的根点其左、右子根点之和;(3)从森林中除取的两棵,并将新加入森林;(4)重复 (2)、 (3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
具体过程如下图 1 产所示:(例)图 1哈夫曼树构建过程哈夫曼树构造成功后,就可以根据哈夫曼树对信源符号进行哈夫曼编码。
具体过程为先找到要编码符号在哈夫曼树中的位置,然后求该叶子节点到根节点的路径,其中节点的左孩子路径标识为 0,右孩子路径标识为 1,最后的表示路径的 01 编码既为该符号的哈夫曼编码。
可以知道,一个符号在哈夫曼树中的不同位置就有不同的编码。
而且,不同符号的编码长度也可能不一样,它由该结点到父结点的路径长度决定,路径越长编码也就越长,这正是哈夫曼编码的优势和特点所在。
用c语言实现哈夫曼编码
用c语言实现哈夫曼编码哈夫曼编码是一种用于无损数据压缩的熵编码算法。
以下是一个简单的使用C语言实现哈夫曼编码的例子。
这个例子只实现了编码过程,没有实现解码过程。
c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>// 节点结构体typedef struct Node {char data;int freq;struct Node *left, *right;} Node;// 创建新节点Node* newNode(char data, int freq) {Node* node = (Node*) malloc(sizeof(Node));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 计算前缀和int getSum(Node* root) {if (!root) return0;return root->freq + getSum(root->left) + getSum(root->right);}// 创建哈夫曼树Node* createHuffmanTree(char data[], int freq[], int size) { if (size == 0) return NULL;Node *left = newNode(data[size-1], freq[size-1]);Node *right = createHuffmanTree(data, freq, size-1);Node *top = newNode(0, getSum(right));top->left = left;top->right = right;return top;}// 打印哈夫曼编码void printHuffmanCode(Node* root, int n, char code[]) {if (!root) return;if (root->data != 0) printf("%c: ", root->data);code[n] = root->data;printHuffmanCode(root->left, n+1, code);printHuffmanCode(root->right, n+1, code);}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data)/sizeof(data[0]);Node* root = createHuffmanTree(data, freq, size);char code[256] = {0}; // 存放哈夫曼编码,初始为空字符串,表示没有编码,对应字符的编码为空字符串。
哈夫曼编码实验超详尽版
编码步骤
6
在F中选取两棵根结点权值最小的树作为新构造 的二叉树的左右子树,新二叉树的根结点的权 值为其左右子树的根结点的权值之和。 从F中删除这两棵树,并把这棵新的二叉树同样 以升序排列加入到集合F中。 重复二和三两步,直到集合F中只有一棵二叉树 为止。
示例
7
假如有A,B,C,D,E五个字符,出现的频率(即权值) 分别为5,4,3,2,1,那么我们第一步先取两个最小权值 作为左右子树构造一个新树,即取1,2构成新树, 其结点为1+2=3,如图:
原理
3
首先统计信源中各符号出现的概率,按符号出现的
概率从大到小排序; 把最小的两个概率相加合并成新的概率,与剩余的 概率组成新的概率集合; 对新的概率集合重新排序,再次把其中最小的两个 概率相加,组成新的概率集合。如此重复进行,直 到最后两个概率的和为l;原理4 Nhomakorabea
分配码字:码字分配从最后一步开始反向进行,
9
实现过程:首先通过 HuffmanTree() 函数构造哈夫 曼树,然后在主函数 main()中自底向上开始(也就 是从数组序号为零的结点开始)向上层层判断,若 在父结点左侧,则置码为 0,若在右侧,则置码为 1。 最后输出生成的编码。 typedef struct
{ int bit[MAXBIT]; int start; } HCodeType; /* 编码结构体 */
五、程序部分代码及其分析
13
/* 设置找到的两个子结点 x1、x2 的父结点信息 */ HuffNode[x1].parent = n+i; HuffNode[x2].parent = n+i; HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight; HuffNode[n+i].lchild = x1; HuffNode[n+i].rchild = x2;
哈夫曼编码算法实现完整版.doc
哈夫曼编码算法实现完整版.doc
哈夫曼编码(Huffman Coding)是一种编码方式,它通过对最常出现频率最高的字符
串编码最短的字节,以节省带宽和存储空间。
它可以将字符信息编码为变长的序列,最短
的字符占用的位数就更少,而最长的字符占用的位数则更多。
实现哈夫曼编码步骤:
(1)统计字符串中字符出现的次数,并生成频率表
(2)将每个字符对应的频率以及编码长度(未分配)加入一个哈夫曼树(Huffman Tree)的叶节点集合中
(3)将集合中的叶节点按照哈夫曼编码的原则进行排序,并重新构造哈夫曼树
(4)从根节点开始计算叶节点的哈夫曼编码,并以二进制形式记录:找到从根节点
到叶节点的路径,从根节点出发,左子节点编码为0,右子节点编码为1
(5)最终给出每个字符对应的哈夫曼编码
哈夫曼编码有如下特点:
(1)使用有穷自动机原理:利用“最优子结构”和“贪心算法”的原理,构造符合
条件的哈夫曼树,从而获得哈夫曼编码;
(2)信源编码理论:哈夫曼编码是考虑到信源编码理论的一种应用,它能把信源各
字符的分布概率考虑在内,根据信源各字符分布给出较合理的字符编码,使得信源编码长
度最短;
(3)使用哈夫曼编码能更加有效地利用存储空间;
(4)哈夫曼编码能减少网络传输数据量,加快网络传输速度;
(5)哈夫曼编码的解码有较高的效率,可以采用类似BinarySearch的方式进行搜索,时间复杂度可以以O(log n)的速度进行解码
通过使用哈夫曼编码,能使编码的效率更高,节省大量存储空间和带宽。
此外,它的
实现原理相对较为简单,因此,现有大多数编码解码系统都会支持哈夫曼编码。
Matlab函数实现哈夫曼编码算法讲解--实用.doc
编写 Matlab 函数实现哈夫曼编码的算法一、设计目的和意义在当今信息化代,数字信号充斥着各个角落。
在数字信号的理和中,信源是首先遇到的,一个信源的好坏劣直接影响到了后面的理和。
如何无失真地,如何使的效率最高,成了大家研究的象。
哈夫曼就是其中的一种,哈夫曼是一种的方案。
它由最二叉既哈夫曼得到,元内容到根点的路径中与父点的左右子的。
所以哈夫曼在在数字通信中有着重要的意。
可以根据信源符号的使用概率的高低来确定元的度。
既了信源的无失真地,又使得的效率最高。
二、设计原理哈夫曼 (Huffman Coding) 是一种方式,哈夫曼是可字 (VLC) 的一种。
uffman 于 1952 年提出一种方法,方法完全依据字符出概率来构造异字的平均度最短的字,有称之最佳,一般就叫作 Huffman 。
而哈夫曼的第一步工作就是构造哈夫曼。
哈夫曼二叉的构造方法原如下,假有 n 个,构造出的哈夫曼有 n 个叶子点。
n 个分 w1、 w2、⋯、wn,哈夫曼的构造:(1)将 w1、w2、⋯,wn 看成是有 n 棵的森林 (每棵有一个点 );(2)在森林中出两个根点的最小的合并,作一棵新的左、右子,且新的根点其左、右子根点之和;(3)从森林中除取的两棵,并将新加入森林;(4)重复 (2)、 (3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
具体过程如下图 1 产所示:(例)图 1哈夫曼树构建过程哈夫曼树构造成功后,就可以根据哈夫曼树对信源符号进行哈夫曼编码。
具体过程为先找到要编码符号在哈夫曼树中的位置,然后求该叶子节点到根节点的路径,其中节点的左孩子路径标识为 0,右孩子路径标识为 1,最后的表示路径的 01 编码既为该符号的哈夫曼编码。
可以知道,一个符号在哈夫曼树中的不同位置就有不同的编码。
而且,不同符号的编码长度也可能不一样,它由该结点到父结点的路径长度决定,路径越长编码也就越长,这正是哈夫曼编码的优势和特点所在。
哈夫曼编码算法实现完整版
哈夫曼编码算法实现完整版下面是哈夫曼编码算法的完整实现。
1.统计字符频率首先,我们需要统计待压缩的文本中每个字符出现的频率。
遍历文本文件,统计每个字符的出现次数。
将字符和对应的频率存储在一个频率表中。
2.构建哈夫曼树接下来,我们使用统计得到的频率表构建哈夫曼树。
哈夫曼树是一种二叉树,每个内部节点都有两个子节点,分别代表0和1首先,将频率表中的每个字符作为叶子节点,并按照频率从小到大进行排序。
然后,依次选择频率最小的两个节点,将它们作为子节点创建一个新的节点,并将新节点的频率设置为这两个节点频率之和。
将新节点插入到频率表中,然后删除原来的两个节点。
重复上述步骤,直到频率表中只剩下一个节点,即哈夫曼树的根节点。
3.生成编码表根据构建好的哈夫曼树,我们可以生成字符的编码表。
遍历哈夫曼树,记录从根节点到每个叶子节点的路径,其中0代表左子节点,1代表右子节点。
4.压缩数据通过编码表,我们可以将原始数据进行压缩。
遍历原始文本,将每个字符替换为对应的编码,然后将所有编码拼接成一个二进制字符串。
5.存储压缩后的数据将压缩后的二进制字符串进行存储,可以使用二进制文件或者文本文件存储。
6.解压数据对于解压,我们需要加载压缩后的数据,并重新构建哈夫曼树。
遍历压缩后的二进制字符串,根据哈夫曼树的结构逐个读取二进制位,当遇到叶子节点时,输出对应的字符。
通过上述步骤,我们可以实现对文本数据的压缩和解压。
需要注意的是,由于哈夫曼编码是基于字符频率进行优化的,所以对于不同的文本文件,编码效果也会有所不同。
较为重复的字符出现频率高的文本文件,哈夫曼编码效果会更好。
哈夫曼编码详解(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编码算法实现
实验六 Huffman编码算法实现一、实验目的1、加深对压缩理论和技术的理解;2、增进对压缩编码算法的设计和编写能力;3、编写Vc++的Huffman编码;4、编写Matlab函数实现哈夫曼编码的算法。
(3或4选做一个即可)二、实验原理1、哈夫曼树的定义:假设有n个权值,试构造一颗有n个叶子节点的二叉树,每个叶子带权值为wi,其中树带权路径最小的二叉树成为哈夫曼树或者最优二叉树;2、哈夫曼树的构造:weight为输入的频率数组,把其中的值赋给依次建立的HT Node对象中的data属性,即每一个HT Node对应一个输入的频率。
然后根据data属性按从小到大顺序排序,每次从data取出两个最小和此次小的HT Node,将他们的data相加,构造出新的HTNode作为他们的父节点,指针parent,leftchild,rightchild赋相应值。
在把这个新的节点插入最小堆。
按此步骤可以构造构造出一棵哈夫曼树。
通过已经构造出的哈夫曼树,自底向上,由频率节点开始向上寻找parent,直到parent 为树的顶点为止。
这样,根据每次向上搜索后,原节点为父节点的左孩子还是右孩子,来记录1或0,这样,每个频率都会有一个01编码与之唯一对应,并且任何编码没有前部分是同其他完整编码一样的。
三、实验内容①初始化,统计文本文件中各字符的个数作为权值,生成哈夫曼树;②根据符号概率的大小按由大到小顺序对符号进行排序;③把概率最小的两个符号组成一个节点;④重复步骤(2)(3),直到概率和为1;⑤从根节点开始到相应于每个符号的“树叶”,概率大的标“0”,概率小的标“1”;⑥从根节点开始,对符号进行编码;⑦译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。
%哈夫曼编码的MATLAB实现(基于0、1编码):clc;clear;A=[0.3,0.2,0.1,0.2,0.2];信源消息的概率序列A=fliplr(sort(A));%按降序排列T=A;[m,n]=size(A);B=zeros(n,n-1);%空的编码表(矩阵)for i=1:nB(i,1)=T(i);%生成编码表的第一列endr=B(i,1)+B(i-1,1);%最后两个元素相加T(n-1)=r;T(n)=0;T=fliplr(sort(T));t=n-1;for j=2:n-1%生成编码表的其他各列for i=1:tB(i,j)=T(i);endK=find(T==r);B(n,j)=K(end);%从第二列开始,每列的最后一个元素记录特征元素在%该列的位置r=(B(t-1,j)+B(t,j));%最后两个元素相加T(t-1)=r;T(t)=0;T=fliplr(sort(T));t=t-1;endB;%输出编码表END1=sym('[0,1]');%给最后一列的元素编码END=END1;t=3;d=1;for j=n-2:-1:1%从倒数第二列开始依次对各列元素编码for i=1:t-2if i>1 & B(i,j)==B(i-1,j)d=d+1;elsed=1;endB(B(n,j+1),j+1)=-1;temp=B(:,j+1);x=find(temp==B(i,j));END(i)=END1(x(d));endy=B(n,j+1);END(t-1)=[char(END1(y)),'0']; END(t)=[char(END1(y)),'1']; t=t+1;END1=END;endA%排序后的原概率序列END%编码结果for i=1:n[a,b]=size(char(END(i)));L(i)=b;endavlen=sum(L.*A)%平均码长H1=log2(A);H=-A*(H1')%熵P=H/avlen%编码效率。
实验6:哈夫曼树及哈夫曼编码的算法实现-副本
实验6:哈夫曼树及哈夫曼编码的算法实现-副本实验6:哈夫曼树及哈夫曼编码的算法实现实验所需学时数2学时实验目的1)掌握哈夫曼树的基本概念及其存储结构;2)掌握哈夫曼树的建立算法;3)掌握哈夫曼树的应用(哈夫曼编码和译码)。
实验内容对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。
实验所需器材计算机及VC++ 6.0软件内容要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
测试数据:输入字符串“this*program*is*my*favourite”,完成这28个字符的编码和译码。
实验结果1、演示程序运行结果。
2、说明调试过程中出现的现象学生实验评价依据:优:实验认真、刻苦,有钻研精神,不无故缺席。
良:能认真对待实验,不无故缺席。
中:基本能认真对待实验,不无故缺席。
差:对待实验不够认真,有少量迟到、早退或无故缺席现象。
不及格:对待实验马虎、敷衍,经常迟到、早退或无故缺席。
#include#include#define maxvalue 10000 //定义最大权值常量#define maxnodenumber 100 //定义节点最大数#define maxbit 10 //定义哈弗曼编码最大长度typedef struct{ //定义新数据类型即节点结构int weight; //权重域int parent,lchild,rchild; //指针域}htnode; //节点类型标识符//typedef htnode * huffmanstree; //定义哈弗曼数类型htnode ht[maxnodenumber]; //定义三叉链表存储数组typedef struct {//定义保存一个叶子节点哈弗曼编码的结构int bit[maxbit]; //定义一维数组为编码域int start; //定义位置域}hcnodetype; //定义编码类型htnode * creatstree(int n) //huffmanstree creatstree(int n) //建立哈夫曼树算法实现函数{int i,j,m1,m2,k1,k2; //局部变量for(i=0;i<2*n-1;i++) //初始化各节点{ht[i].weight=0; //权重初始化为0ht[i].parent=-1; //根节点和给左右孩子初始化为-1ht[i].lchild=-1;ht[i].rchild=-1;}for(i=0;i<="">{scanf("%d",&ht[i].weight);}for(i=0;i<="">{m1=maxvalue; //预置最小权值变量为最大权值m2=maxvalue; //预置次小权值变量为最大权值k1=0; //预置最小权值节点位置为下标为0处k2=0; //预置次小权值节点位置为下标为0处for(j=0;j<="">if(ht[j].parent==-1&&ht[j].weight<m1)< p="">{m2=m1;k2=k1;m1=ht[j].weight;k1=j;}else //当小于当前次小m2则更新m2及其位置if(ht[j].parent==-1&&ht[j].weight<m2)< p="">{m2=ht[j].weight;k2=j;}ht[k1].parent=n+i; //修改最小权值节点的双亲为刚生成的新节点ht[k2].parent=n+i; //修改次小权值节点的双亲为刚生成的新节点ht[n+i].weight=ht[k1].weight+ht[k2].weight; //将新生成的权重值填入新的根节点ht[n+i].lchild=k1; //新生节点左孩子指向k1 ht[n+i].rchild=k2; //新生节点右孩子指向k2}return ht; //返回哈夫曼树指针}void getstree(htnode * ht,int n) //哈夫曼编码算法及打印函数的实现{int i,j,c,p; //局部变量的定义hcnodetype cd[maxnodenumber]; //定义存储哈夫曼编码的数组for(i=0;i<="">{c=i; //为编码各节点初始化c和jj=maxbit;do{j--; //j指向bit中存放编码为的正确位置p=ht[c].parent; //p指向c的双亲节点if(ht[p].lchild==c) //如果c是p的左孩子cd[i].bit[j]=0; //编码为赋值0else //否则即c是p的右孩子cd[i].bit[j]=1; //编码赋值1c=p;//更新当前指针,为下一节点编码做准备}while(ht[p].parent!=-1); //判断是否编码结束即循环至最终根节点cd[i].start=j; //编码完成,记下编码开始位置}for(i=0;i<="">{for(j=cd[i].start;j<="">printf("%d",cd[i].bit[j]);printf("\n"); //每输出一编码后换行}}int main() //主函数{int n;printf("请输入节点数:"); //用户输入节点数scanf("%d",&n);htnode * p; // huffmanstree p //定义哈夫曼树类型pp=(htnode * )malloc(sizeof(htnode *));//p=(huffmanstree)malloc(sizeof(huffmanstree))//分配内存空间p=creatstree(n);//调用建立哈夫曼树函数赋返回值给pgetstree(p,n); //调用编码函数读入建立的哈夫曼树p进行编码return 0;}</m2)<></m1)<>。
哈夫曼编码的实现
哈夫曼编码的实现张zhaohan 10804XXXXX2010/6/12自拟问题利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
试为这样的信息传输写一个哈夫曼编/译码系统。
系统设计(一)设计目标一个完整的系统应具有以下功能:●:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
输出哈夫曼树,及各字符对应的编码。
●W:输入(Input)。
从终端读入需要编码的字符串s,将字符串s存入文件Tobetran.txt中。
●E:编码(Encoding)与译码(Decoding)。
编码(Encoding)。
利用已建好的哈夫曼树(如不在内存,则从文件htmTree 中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
译码(Decoding)。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
印代码文件(Print)。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码写入文件CodePrint中。
T:印哈夫曼树(Tree Printing)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
5)Q:退出程序。
返回WINDOWS界面。
(二)设计思想哈夫曼编码(Huffman Coding)是一种编码方式,以哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。
是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。
这种方法是由David.A.Huffman发展起来的。
例如,在英文中,e的出现概率很高,而z的出现概率则最低。
哈夫曼树及哈夫曼编码的算法实现
哈夫曼树及哈夫曼编码的算法实现1. 哈夫曼树的概念和原理哈夫曼树是一种带权路径长度最短的树,也称最优二叉树。
它是由美国数学家大卫・哈夫曼发明的,用于数据压缩编码中。
哈夫曼树的构建原理是通过贪心算法,将权重较小的节点不断合并,直到所有节点都合并成为一个根节点,形成一棵树。
这样构建的哈夫曼树能够实现数据的高效压缩和解压缩。
2. 哈夫曼编码的概念和作用哈夫曼编码是一种可变长度编码,它根据字符在文本中出现的频率来进行编码,频率越高的字符编码越短,频率越低的字符编码越长。
这种编码方式能够实现数据的高效压缩,减小数据的存储空间,提高数据传输的效率。
3. 哈夫曼树和编码的算法实现在实现哈夫曼树和编码的算法过程中,首先需要统计文本中每个字符出现的频率,并根据频率构建哈夫曼树。
根据哈夫曼树的结构,确定每个字符的哈夫曼编码。
利用哈夫曼编码对文本进行压缩和解压缩。
4. 个人观点和理解哈夫曼树及哈夫曼编码算法是一种非常有效的数据压缩和编码方式,能够在保证数据完整性的前提下,减小数据的存储和传输成本。
在实际应用中,哈夫曼编码被广泛应用于通信领域、数据存储领域以及图像压缩等领域。
通过深入理解和掌握哈夫曼树及哈夫曼编码的算法实现,可以为我们在实际工作中处理大量数据时提供便利和效率。
5. 总结与回顾通过本篇文章的详细讲解,我深入了解了哈夫曼树及哈夫曼编码的算法原理和实现方式,对其在数据处理中的重要性有了更深刻的认识。
掌握了哈夫曼树及哈夫曼编码的算法实现,将为我未来的工作和学习提供更多的帮助和启发。
根据您提供的主题,本篇文章按照从简到繁、由浅入深的方式探讨了哈夫曼树及哈夫曼编码的算法实现。
文章共计超过3000字,深入剖析了哈夫曼树和编码的原理、实现方式以及应用场景,并结合个人观点进行了阐述。
希望本篇文章能够满足您的需求,如有任何修改意见或其他要求,欢迎随时告知。
哈夫曼树和哈夫曼编码是一种十分重要的数据压缩和编码方式,它们在实际的数据处理和传输中发挥着非常重要的作用。
c语言实现哈夫曼编码
c语言实现哈夫曼编码一、概述哈夫曼编码是一种常用的无损数据压缩算法,其原理是基于字符的出现概率来构建编码表,从而实现数据的压缩。
本教程将介绍如何使用C语言实现哈夫曼编码算法。
二、算法原理哈夫曼编码算法的基本思想是:将字符按照出现概率的大小进行排序,然后构建一个树状结构,每个节点代表一个字符,节点的左子节点和右子节点分别代表字符的频率较小和较大的分支。
最终,通过路径进行解码即可还原出原始数据。
三、实现步骤1.统计字符频率,构建字符频率表;2.按照频率从小到大排序,构建哈夫曼树;3.根据哈夫曼树构建编码表,将字符映射为编码;4.实现解码过程,还原出原始数据。
四、代码实现下面是一个简单的C语言实现哈夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<ctype.h>#defineMAX_CHARS1000//最大字符数#defineMAX_FREQ100//最大频率值//字符频率表intfreq[MAX_CHARS+1];//构建哈夫曼树函数structnode{charch;intfreq;structnode*left,*right;};structnode*build_huffman_tree(intfreq[],intn){structnode*root=(structnode*)malloc(sizeof(structnode));root->freq=freq[0];//根节点的频率为最小的频率值root->left=root->right=NULL;for(inti=1;i<=n;i++){if(freq[i]==root->freq){//如果当前字符的频率与根节点的频率相同,则添加到左子树或右子树中if(i<n&&freq[i]==freq[i+1]){//如果当前字符的频率与下一个字符的频率相同,则添加到左子树中root->left=(structnode*)malloc(sizeof(structnode));root->left->ch=i+'a';//左子节点的字符为当前字符的下一个字符(假设所有字符都是小写字母)root->left->left=root->left->right=NULL;//左子树为空树i++;//跳过下一个字符,继续寻找下一个不同的频率值}else{//如果当前字符的频率与下一个字符的频率不相同,则添加到右子树中root->right=(structnode*)malloc(sizeof(structnode));root->right->ch=i+'a';//右子节点的字符为当前字符root->right->left=root->right->right=NULL;//右子树为空树}}elseif(freq[i]<root->freq){//如果当前字符的频率小于根节点的频率,则添加到左子树中root->left=(structnode*)malloc(sizeof(structnode));root->left->ch=i+'a';//左子节点的字符为当前字符的下一个字符(假设所有字符都是小写字母)root->left->left=build_huffman_tree(freq,i);//子树的左孩子为当前字符构成的右子树节点和子哈夫曼树的左孩子合并得到的左孩子节点,这个步骤继续调用本函数,从而继续构建右子树的下一级和再下一级,最终实现三级左右子的嵌套式结构树型哈夫曼编码)注:这种思想并非标准的哈夫曼编码)//子树的右孩子为当前节点(即当前字符)构成的右子树节点和子哈夫曼树的右孩子节点合并得到的右孩子节点)注:这种思想并非标准的哈夫曼编码)//子树的左孩子为空树)注:这种思想并非标准的哈夫曼编码)根节点的频率是根节点的最小频率值(因为构建哈夫曼树的过程中总是从最小的频率值开始)根节点的左子树是构建出的三级左右子的嵌套式结构树型哈夫曼编码根节点的右子树为空树(假设所有字符都是小写字母)在添加左子节点后需要调用本函数构建右子树的下一级和再下一级来得到三级左右子的嵌套式结构。
哈夫曼编码算法实现 -回复
哈夫曼编码算法实现-回复哈夫曼编码算法是一种广泛应用于数据压缩领域的编码算法,它可以将字符或符号转化为比特流,实现数据的高效压缩和传输。
本文将详细介绍哈夫曼编码算法的原理、步骤和实现过程。
一、哈夫曼编码算法的原理1. 引入概念在介绍哈夫曼编码算法之前,我们首先需要了解一些基本概念。
在信息理论中,每个字符或符号都可以表示为一个固定长度的编码,例如ASCII编码中,每个字符都用8个比特位表示。
而哈夫曼编码算法通过构建一棵哈夫曼树,使得出现频率较高的字符或符号使用较短的编码,而出现频率较低的字符或符号使用较长的编码,从而实现了数据的高效压缩。
2. 构建哈夫曼树哈夫曼树是一种特殊的二叉树,在构建哈夫曼树时,我们需要根据字符或符号的频率来确定每个节点的权值。
首先,将每个字符或符号作为一个独立的节点,并将频率作为权值。
接着,选取出现频率最低的两个节点,将它们作为子节点构建一个新的父节点,该父节点的权值为两个子节点的权值之和。
重复这一过程,直到所有的节点都被合并为一个根节点,就构建出了哈夫曼树。
3. 分配编码在哈夫曼树构建完成后,我们可以通过遍历树的路径来分配编码。
从根节点出发,遍历左子树时,将路径上的0作为对应的编码;遍历右子树时,将路径上的1作为对应的编码。
直到到达叶子节点,即为某个字符或符号,我们就得到了它的哈夫曼编码。
4. 压缩数据使用哈夫曼编码后,数据可以被高效地压缩。
原始数据中的每个字符被替换为对应的哈夫曼编码,从而减少了所需的比特位数。
因为出现频率较高的字符使用了较短的编码,所以整体上可以实现数据量的压缩。
二、哈夫曼编码算法的步骤1. 统计频率:遍历原始数据,统计每个字符或符号的出现频率,并将其作为节点的权值。
2. 构建哈夫曼树:根据频率,构建哈夫曼树,合并频率最低的两个节点,直到构建出完整的哈夫曼树。
3. 分配编码:根据哈夫曼树的结构,为每个字符或符号分配对应的编码。
4. 压缩数据:将原始数据中的每个字符替换为对应的哈夫曼编码,从而实现数据的压缩。
哈夫曼编码的C语言实现
哈夫曼编码的C语言实现一、大致思路输入信源符号的概率,构造哈夫曼树,从叶子结点到根结点进行编码二、编码实现#include <stdio.h>#define n 7 //leaf number#define m 2*n-1 //all numbertypedef struct{char ch;double weight;int left;int right;int parent;}Node;typedef struct{char ch;int codeis[50];int start;}Code;void HuffmanTree (Node node[],int number){int i,j,x1=0,x2=0;double m1,m2;for(i=0;i<n-1;i++){ //loop n-1m1=m2=1; //least probability p<1//m1 最小 m2第二小for(j=0;j<n+i;j++){if(node[j].weight <m1 && node[j].parent ==-1){m2=m1;x2=x1;m1=node[j].weight;x1=j;} //是最小的else if(node[j].weight <m2 &&node[j].parent ==-1){m2=node[j].weight;x2=j;}} //找结点node[x1].parent = number+i;node[x2].parent = number+i;node[number+i].weight = node[x1].weight + node[x2].weight;node[number+i].left = x1;node[number+i].right = x2;}//end for}int main(int argc, const char * argv[]) {double x[n]={0};printf("请输入%d个符号的概率",n);int i;for(i=0;i<n;i++){scanf("%lf",&x[i]);}Node node[2*n-1]; // 2*len-1 is the number of all nodefor(i=0;i<2*n-1;i++){node[i].weight = 0;node[i].left = -1;node[i].right = -1;node[i].parent = -1;} //initializefor(i=0;i<n;i++){node[i].weight=x[i];}Code code[n],tempcode; //save the code of leafHuffmanTree(node,n); //创建好了哈夫曼树//编码int p,c,j=0;for(i=0;i<n;i++){c=i;tempcode.start = n-1;p=node[c].parent;while(p!=-1){if(node[p].left == c)tempcode.codeis[tempcode.start] = 1; elsetempcode.codeis[tempcode.start] = 0; tempcode.start--;c=p;p=node[c].parent;} //end whilefor(j=tempcode.start+1;j<n;j++){code[i].codeis[j]=tempcode.codeis[j];}//保存下载刚才的结果code[i].start = tempcode.start;} //end forfor (i=0;i<n;i++){for (j=code[i].start+1;j<n;j++){printf("%d",code[i].codeis[j]);}printf("\n");}getchar();return 0;}三、总结1.创建了哈夫曼树,n是叶子结点数。
哈弗曼编码的实现
如何实现哈夫曼编码一、编码【题目描述】给定一篇用于通信的英文电文,统计该电文中每个字符出现的频率,按频率左小右大的方法为这些字符建立哈夫曼(Huffamn)树,并编出每个字符的哈夫曼树码,输出该电文的哈夫曼码译文。
【输入】输入文件huffman.in是一篇用于通信的英文电文。
【输出】输出文件huffman.out输出该电文的哈夫曼码译文。
【输入输出样例1】【数据限制】2<=英文电文字符数<=10000000统计以上abcd出现的个数。
a:3 b:2 c:4 d:10构造出哈夫曼树a:011 b:010 c :00 d:1 下面主要通过两个结构体数组来实现:struct node1{ int w, lch, rch, parent;}ht[2*N0-1+1];-》-》.。
struct node2{ char ch;//对应的字符abcdint start;//编码的起始位置注意这个编码是倒着的所以这里用start int code[N0];//这个是编码数组}hc[N0+1];大概图如下面下面给出大家想要的程序部分view plaincopy to clipboardprint? //#include "stdio.h"//#include "string.h "#include <iostream>#include <string>const int N0=10;const int N=100;const int INF=1000000;struct node1{ int w, lch, rch, parent;}ht[2*N0-1+1];struct node2{ char ch;int start;int code[N0];}hc[N0+1];int n,root;//n为叶子的个数void readData(){ char ch;int num[256]={ 0 };n=0;freopen( "huffman.in", "r", stdin);//读文本文件while( (ch=getchar()) != EOF )num[ch]++;for( int i=0; i<=255; i++ ){ if( num[i] ){ n++;ht[n].w=num[i];hc[n].ch=i;}}}void select1( int t, int *s1, int *s2)//用两个数来记录没有在树上的最小的两个值,从而进一步生成树。
哈夫曼编码
Huffman算法可描述如下:(1)根据给定的n个权值{w1,w2,…,w n}构造n棵二叉树的集合F={T1,T2,…,T n},其中每棵二叉树T i中只有一个带权为w i的根结点,其左、右子树均为空。
(2)在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点权值为其左、右子树根结点的权值之和。
(3)在F中用新得到的二叉树代替这两棵树。
(4)重复(2)、(3)过程,直到F中只含有一棵树为止。
具体在实现Huffman算法时,可以采用有序链表存放集合F中各子树根结点的权值。
以后每循环一次就在链表的表头取下连续两棵子树(即为最小和次最小权值的二叉子树)作为左右子树去构造一倮棵新的子树,再将新生成的子树按其根的权值插入到有序链表中去,一旦链表中只有一棵树时,该棵树即为所求的Huffman树。
/////////////////////////////////////////////////////////////////////////////////Huffman算法#include <iostream>using namespace std;#define MAX 99char cha[MAX];char hc[MAX-1][MAX];int s1,s2; //设置全局变量,以便在方法(函数)select中返回两个变量void menu();typedef struct //huffman树存储结构{unsigned int wei;int lch,rch,parent;}hufftree;void select(hufftree tree[],int k) //找寻parent为0,权最小的两个节点{ int i;for (i=1;i<=k && tree[i].parent!=0 ;i++); s1=i;for (i=1;i<=k;i++)if (tree[i].parent==0 && tree[i].wei<tree[s1].wei) s1=i;for (i=1; i<=k ; i++)if (tree[i].parent==0 && i!=s1) break; s2=i;for (i=1;i<=k;i++)if ( tree[i].parent==0 && i!=s1 && tree[i].wei<tree[s2].wei) s2=i;}void huffman(hufftree tree[],int *w,int n) //生成huffman树{ int m,i;if (n<=1) return;m=2*n-1;for (i=1;i<=n;i++){ tree[i].wei=w[i];tree[i].parent=0;tree[i].lch=0;tree[i].rch=0;}for (i=n+1;i<=m;i++){ tree[i].wei=0;tree[i].parent=0;tree[i].lch=0;tree[i].rch=0;}for (i=n+1;i<=m;i++){ select(tree, i-1);tree[s1].parent=i;tree[s2].parent=i;tree[i].lch=s1;tree[i].rch=s2;tree[i].wei=tree[s1]. wei+ tree[s2].wei;}}void huffmancode(hufftree tree[],char code[],int n){ int start,c,i,f;code[n-1]='\0';cout <<"Huffman编码:" <<endl;for(i=1;i<=n;i++){ start=n-1;for(c=i,f=tree[i].parent;f!=0;c=f,f=tree[f].parent){ if(tree[f].lch==c)code[--start]='0';elsecode[--start]='1';}strcpy(hc[i],&code[start]);cout <<cha[i] <<"-->" <<hc[i] <<endl;}}void tohuffmancode(int n){ int i=0,j;char anychar[9999];cout <<"请输入一段字符:" <<endl;cin >>anychar;cout <<"进行Huffman编码后的结果为:" <<endl;for (;anychar[i]!='\0';i++){ j=0;for(;anychar[i]!=cha[j]&&j<=n;)j++;if (j<=n)cout <<hc[j];}cout <<endl;}void decode(char ch[],hufftree tree[],int n){ int i,j,m;char b;m=2*n-1;i=m;cout <<"请输入你要解码的编码:" <<endl;cin >>b;cout <<"解码结果为:" <<endl;while(b!='#') //遇到#时,结束{ if(b=='0')i=tree[i].lch;elsei=tree[i].rch;if(tree[i].lch==0){ cout <<ch[i];j=i,i=m;}cin >>b;}if(tree[j].lch!=0)cout <<"发生错误!!";}void main(){ int i=0,n=0;int *w,wei[MAX];char code[MAX];hufftree tree[MAX];w=wei;cout <<"请输入n(n为你要建树的字符个数):" <<endl; cin >>n;cout <<"请输入字符和它的权值(例如:a20):" <<endl; for(i=1;i<=n;i++){ cin >>cha[i] >>wei[i];}huffman(tree,w,n); //生成huffman树huffmancode(tree,code,n); //编码A tohuffmancode(n);//编码B decode(cha,tree,n); //译码}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
哈夫曼编码算法实现完整版[终稿] 实验三树的应用一.实验题目:树的应用——哈夫曼编码二.实验内容:利用哈夫曼编码进行通信可以大大提高信道的利用率~缩短信息传输的时间~降低传输成本。
根据哈夫曼编码的原理~编写一个程序~在用户输入结点权值的基础上求哈夫曼编码。
要求:从键盘输入若干字符及每个字符出现的频率~将字符出现的频率作为结点的权值~建立哈夫曼树~然后对各个字符进行哈夫曼编码~最后打印输出字符及对应的哈夫曼编码。
三、程序源代码:#include <iostream.h>#include <fstream.h>#include <string.h>#include <stdlib.h>typedef struct{char data;int weight;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char * * HuffmanCode;void Select(HuffmanTree &HT,int n,int m){HuffmanTree p=HT;int tmp;for(int j=n+1;j<=m;j++){int tag1,tag2,s1,s2;tag1=tag2=32767;for(int x=1;x<=j-1;x++){ if(p[x].parent==0&&p[x].weight<tag1){ tag1=p[x].weight;s1=x;}}for(int y=1;y<=j-1;y++){ if(p[y].parent==0&&y!=s1&&p[y].weight<tag2){ tag2=p[y].weight;s2=y;}}if(s1>s2) //将选出的两个节点中的序号较小的始终赋给s1{ tmp=s1; s1=s2; s2=tmp;}p[s1].parent=j;p[s2].parent=j;p[j].lchild=s1;p[j].rchild=s2;p[j].weight=p[s1].weight+p[s2].weight;}}void HuffmanCoding(HuffmanTree &HT,int n,char *w1,int*w2) {int m=2*n-1;if(n<=1) return;HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));HuffmanTree p=HT;for(int i=1;i<=n;i++){ p[i].data=w1[i-1];p[i].weight=w2[i];p[i].parent=p[i].lchild=p[i].rchild=0;}for(;i<=m;i++){ p[i].weight=p[i].parent=p[i].lchild=p[i].rchild=0; }Select(HT,n,m);ofstream outfile; //生成hfmTree文件outfile.open("hfmTree.txt",ios::out);for (i=1;i<=m;i++){outfile<<HT[i].weight<<"\t"<<HT[i].parent<<"\t"<<HT[i].lchild <<"\t"<<HT[i].rchild<<"\t"<<endl; }outfile.close();cout<<"初始化结果已保存在hfmTree文件中\n";}void ToBeTree() //将正文写入文件ToBeTree中{ofstream outfile;outfile.open("ToBeTree.txt",ios::out);outfile<<"THIS PROGRAM IS MYFAVORITE";outfile.close();}void Encoding(HuffmanTree &HT,int n) //编码{HuffmanCode HC;HC=(HuffmanCode)malloc((n+1)*sizeof(char *));char *cd;cd=(char *)malloc(n*sizeof(char));cd[n-1]='\0';for(int k=1;k<=n;k++){ int start=n-1;for(int c=k,f=HT[k].parent;f!=0;c=f,f=HT[f].parent) { if(HT[f].lchild==c) cd[--start]='0';else cd[--start]='1';}HC[k]=(char *)malloc((n-start)*sizeof(char)); strcpy(HC[k],&cd[start]);}cout<<"输出哈夫曼编码:"<<endl;for(int h=1;h<=n;h++) //输出编码{ cout<<HT[h].data<<":";cout<<HC[h];cout<<" ";if (h%8==0) cout<<endl;}cout<<endl<<"输出正文编码:"<<endl; ToBeTree();//读取TOBETREE文件里的正文~并进行编码fstream infile;infile.open("ToBeTree.txt",ios::in);char s[80];while(!infile.eof()){infile.getline(s,sizeof(s));}infile.close();fstream outfile;outfile.open("CodeFile.txt",ios::out);int count=0;for (h=0;s[h]!='\0';h++){ for(k=1;k<=n;k++)if (s[h]==HT[k].data){ cout<<HC[k];cout<<" ";count++;outfile<<HC[k];break;}if (count%9==0) cout<<endl; //每输出7个换行}outfile.close();cout<<"\n编码结果已保存在文件CodeFile中.";cout<<endl;}void Decoding(HuffmanTree &HT,int n) //译码{int f=2*n-1;fstream infile;infile.open("CodeFile.txt",ios::in);char s[1000];while(!infile.eof()){infile.getline(s,sizeof(s));}infile.close();int i=0;int j=0;fstream outfile;outfile.open("TextFile.txt",ios::out);while(s[i]!='\0'){ f=2*n-1;while(HT[f].lchild!=0)//以f对应的节点的左孩子的值==0作为结束{if (s[j]=='0') f=HT[f].lchild;else f=HT[f].rchild;j++;}i=j;cout<<HT[f].data;outfile<<HT[f].data;}outfile.close();cout<<"\n译码结果已保存在文件TextFile中.";cout<<endl;}void Print() //印代码文件 { int count=0;fstream infile;infile.open("CodeFile.txt",ios::in);char s[1000];while(!infile.eof()){infile.getline(s,sizeof(s));for(int i=0;s[i]!='\0';i++){ cout<<s[i];count++;if (count%50==0) cout<<endl; //在终端上每行显示50个代码}}infile.close();cout<<endl;}char menu() //菜单函数 { cout<<"功能菜单如下:"<<endl; cout<<"* * * * * * * * * * * * * * * * * * * * *"<<endl; cout<<" I:初始化(Initialization) "<<endl;cout<<" E:编码(Encoding) "<<endl;cout<<" D:译码(Decoding) "<<endl;cout<<" P:印代码文件(Print) "<<endl;cout<<" Q:退出(Exit) "<<endl;cout<<"* * * * * * * * * * * * * * * * * * * * *"<<endl; cout<<"请输入功能字符:";char ch;cin>>ch;return ch;}void main(){ int n;int Array[100];char cArray[100];HuffmanTree HT;cout<<"输入n个字符:";cin.getline(cArray,100);n=strlen(cArray);cout<<"一共"<<n<<"个字符.\n";cout<<"依次输入各个字符的权值:"<<endl;for (int i=1;i<=n;i++) cin>>Array[i];int tag;char x=menu();while(1){ switch (x){case 'I':HuffmanCoding(HT,n,cArray,Array);break; case 'E':Encoding(HT,n);break;case 'D':Decoding(HT,n);break;case 'P':Print();break;case 'Q':tag=0;cout<<"结束"<<endl;break; default:cout<<"你输入错误!"<<endl;}if(tag==0) break;cout<<"y(继续) or n(退出)"<<endl;char ch;cin>>ch;if (ch=='y'){ cout<<"请输入功能字符:";char c;cin>>c;x=c;}else exit(1);}}测试数据:用下表给出的字符集和频度的实际统计数据建立哈夫曼树~并实现以下报文的译码和编码:"THIS PROGRAM IS MY FAVORITE".字符空格 A B C D E F G H I J K L M频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20字符 N O P Q R S T U V W X Y Z频度 57 63 15 1 48 51 80 23 8 18 1 16 1四.测试结果:如图一所示五.实验体会通过本次实验~尤其在自己对程序的调试过程中~感觉对树的存储结构~终结状态~还有编码~译码的过程都有了比较清晰的认识。