计算机系统结构课设huffman编码实现
huffman编码和扩展编码的编码原理
Huffman编码和扩展编码的编码原理在计算机科学领域,编码是一种将信息转换成另一种形式的过程。
而Huffman编码和扩展编码则是两种常见的编码方式。
本文将分别介绍Huffman编码和扩展编码的编码原理。
Huffman编码的编码原理1. 原理概述Huffman编码是一种可变字长编码,它通过对输入的字符进行频率统计,并基于字符频率构建一棵Huffman树,然后通过遍历Huffman 树得到字符的编码。
被编码的字符频率越高,其编码长度越短,这样可以实现对数据进行高效压缩。
2. 统计字符频率对于输入的字符流,需要进行频率统计。
一般情况下,可以使用哈希表来存储字符及其出现次数,以便后续步骤使用。
3. 构建Huffman树根据字符的频率,构建一棵Huffman树。
具体的构建方法是,将字符的频率作为叶子节点的权值,然后通过合并权值最小的两个节点,构建出一颗新的节点,并将新节点放入集合中,直到所有节点都被合并为止。
4. 遍历Huffman树遍历构建好的Huffman树,对叶子节点进行编码。
通常情况下,左子节点被编码为0,右子节点被编码为1,然后将编码结果保存至编码表中供之后的编码使用。
5. 对数据进行编码根据构建好的编码表,对输入的字符进行编码,得到压缩后的数据。
6. 解码对压缩后的数据进行解码,即根据构建好的Huffman树,将编码还原为原始数据。
扩展编码的编码原理1. 原理概述扩展编码是一种通常用于将非ASCII字符表示为ASCII字符的编码方式。
其原理是使用特殊的转义序列来表示非ASCII字符,从而实现在ASCII字符集范围内表示更多的字符。
常见的扩展编码包括UTF-8、UTF-16等。
2. 字符集和编码方式扩展编码通常是针对不同的字符集设计的,比如Unicode字符集。
而具体的编码方式又可以有多种选择,比如UTF-8采用变长编码,在表示ASCII字符时只需要一个字节,在表示其他字符时需要两个或更多字节。
huffman树数据结构实验原理
huffman树数据结构实验原理
Huffman树是一种用于数据压缩的数据结构,原理如下:
1. 统计字符频率:首先,对于待压缩的数据,统计每个字符出现的频率。
可以使用哈希表或数组来记录各个字符的频率。
2. 构建最小堆:将每个字符及其频率作为一个节点,构建一个最小堆。
最小堆是一种二叉树,每个节点的值都小于或等于其子节点的值。
3. 构建Huffman树:从最小堆中取出频率最小的两个节点(即出现频率最低的两个字符),将它们合并为一个新的节点,并将新节点的频率设置为两个节点的频率之和。
将新节点插入回最小堆中。
重复这个过程,直到最小堆中只剩下一个节点。
4. 构建Huffman编码表:从Huffman树的根节点出发,根据每个字符所在的路径(左子树为0,右子树为1)来构建Huffman编码表。
Huffman编码表可以使用哈希表或数组来存储,键为字符,值为对应的Huffman编码。
5. 数据压缩:对于待压缩的数据,根据Huffman编码表将每个字符转换为对应的Huffman编码,得到压缩后的数据。
6. 数据解压:对于压缩后的数据,根据Huffman编码表将每个Huffman编码转换为对应的字符,得到解压后的数据。
Huffman树的原理在于通过构建一个最小堆,使用贪心算法来生成一个频率最小的树。
这样生成的树中,频率高的字符在树的顶部,频率低的字符在树的底部,从而实现数据压缩。
哈夫曼编码算法实现
哈夫曼编码(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)。
数据结构课程设计哈夫曼编码实验
数据结构设计性实验Huffman编码与译码学号姓名班级设计性实验—Huffman 编码与译码一.实验目的:在掌握相关基础知识的基础上,学会自己设计实验算法,熟练掌握Huffman 树的建立方法,Huffman 编码的方法,进而设计出Huffman 译码算法,并编程实现。
二.实验要求:在6学时以内,制作出能够实现基于26个英文字母的任意字符串的编译码。
写出技术工作报告并附源程序。
三.实验内容及任务:1.设字符集为26个英文字母,其出现频度如下表所示。
2.建Huffman 树; 3.利用所建Huffman 树对任一字符串文件进行编码——即设计一个Huffman 编码器;4.对任一字符串文件的编码进行译码——即设计一个Huffman 译码器。
实现步骤:1.数据存储结构设计; 2.操作模块设计; 3.建树算法设计; 4.编码器设计;5. 译码器设计;51 48 1 15 63 57 20 32 5 1频度z y x w v u t 字符11611882380频度p 21 f q15 g r 47 h s o n m l k j 字符 57 103 32 22 13 64 186 频度 i e d c b a 空格 字符四.分析以及算法描述1.分析问题1)首先学习二叉树的知识,了解二叉树的路径、权数以及带权路径长度计算。
2)认识霍夫曼树,了解霍夫曼树的定义,构造霍夫曼树构造算法①又给定的n个权值{w1,w2,w3,……,w n}构造根节点的二叉树,从而得到一个二叉树森林F={T1,T2,T3,……T n}。
②在二叉树森里选取根节点全职最小和此最小的两棵二叉树作为左右节点构造新的二叉树,此时新的二叉树的根节点权值为左右子树权值之和。
③在二叉树森林中删除作为新二叉树的根节点左右子树的两棵二叉树,将新的二叉树加入到二叉树森林F中。
④重复②和③,当二叉树森林F只剩下一棵二叉树时,这棵二叉树是所构造的霍夫曼树。
3)练习通过普通树来构造霍夫曼树。
(完整word版)数据结构课程设计(哈夫曼编码)
目录目录 (1)1 课程设计的目的和意义 (3)2 需求分析 (5)3 系统设计 (6)(1)设计思路及方案 (6)(2)模块的设计及介绍 (6)(3)主要模块程序流程图 (9)4 系统实现 (14)(1)主调函数 (14)(2)建立HuffmanTree (14)(3)生成Huffman编码并写入文件 (18)(4)电文译码 (19)5 系统调试 (22)小结 (25)参考文献 (26)附录源程序 (27)1 课程设计的目的和意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0"码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1"的序列作为和各个对应的字符的编码,这就是哈夫曼编码。
通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。
电报通信是传递文字的二进制码形式的字符串。
但在信息传递时,总希望总长度尽可能最短,即采用最短码。
作为软件工程专业的学生,我们应该很好的掌握这门技术。
在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。
在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。
这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。
在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。
更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见.同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。
huffman编码的基本原理和步骤
Huffman编码是一种常用的数据压缩算法,它通过对字符进行变长编码来实现数据的高效压缩。
本文将从基本原理和步骤两个方面来深入探讨Huffman编码。
一、基本原理Huffman编码的基本原理是根据待编码的字符在数据中出现的频率来构建不同长度的编码,频率越高的字符使用较短的编码,频率越低的字符使用较长的编码。
这样可以实现对常用字符的高效编码,从而实现数据的有效压缩。
在实际应用中,Huffman编码通常用于无损数据压缩,例如在通信领域、文件压缩领域等都有广泛的应用。
通过Huffman编码,可以大大减小数据的传输和存储成本,提高数据的传输效率,是一种非常重要的数据压缩算法。
二、步骤要实现Huffman编码,需要按照以下步骤进行:1. 统计字符出现的频率。
首先需要对待编码的数据进行扫描,统计每个字符在数据中出现的频率。
2. 构建Huffman树。
根据字符的频率构建Huffman树,频率越高的字符在树中的位置越靠近根节点,频率越低的字符在树中的位置越靠近叶子节点。
3. 生成Huffman编码。
根据构建的Huffman树,可以得出每个字符对应的Huffman编码,即根据字符在树中的位置来确定编码,从根节点到叶子节点的路径上的0和1分别代表不同的编码。
4. 进行数据编码。
根据生成的Huffman编码,可以对待编码的数据进行编码,将原始数据中的字符替换为对应的Huffman编码。
5. 进行数据解码。
接收方可以根据相同的Huffman树和编码规则来对接收到的数据进行解码,恢复出原始的数据。
总结回顾通过对Huffman编码的基本原理和步骤进行全面评估,我们可以深入地理解Huffman编码的工作原理和实现方法。
Huffman编码通过对字符出现频率的统计和树的构建来实现对数据的高效压缩,从而节省存储和传输成本,提高数据的传输效率。
在实际应用中,Huffman编码被广泛应用于数据压缩领域,为数据的高效管理和利用提供了重要支持。
霍夫曼编码和实现
霍夫曼编码(Huffman Coding)是一种被广泛应用的编码方法,它以信源空间的概率分布为基准,用概率匹配方法进行信源编码。
实现霍夫曼编码可以分为几个步骤:
1. 统计:首先,你需要对字符出现的频率进行统计。
在霍夫曼编码中,每个字符出现的频率与其在编码中的长度是一一对应的。
出现频率越高的字符,其编码长度越短;出现频率越低的字符,其编码长度越长。
2. 创建二叉树:然后,你需要创建一个二叉树。
这个二叉树的左节点和右节点分别代表0和1,每个节点都包含一个字符及其出现的频率。
这个二叉树会被用来生成霍夫曼编码。
3. 生成编码:在创建好二叉树后,你可以从最上面的根节点(也就是最左边的节点)开始,沿着树向下走,遇到左节点就向左走,遇到右节点就向右走。
当你到达一个叶子节点(也就是没有子节点的节点)时,就可以停止下来。
这个路径就是该字符的霍夫曼编码。
4. 编码和解码:在得到霍夫曼编码后,你可以通过反向遍历二叉树来解码出原始的字符。
从根节点开始,根据当前节点的状态向左或向右走,直到到达叶子节点为止。
实现霍夫曼编码可以使用任何一种编程语言。
在Python中,你可以使用类和函数来实现这些步骤。
例如,你可以创建一个类来表示
二叉树,并使用函数来创建树、生成编码和解码字符等。
以上是霍夫曼编码的基本步骤和实现方法。
在实际应用中,还需要考虑一些其他因素,例如如何处理字符集的大小、如何优化编码和解码的时间等。
软件课程设计 - Huffman编码
计算机软件基础课程设计题目:Huffman编码学院:信息与通信工程学院专业:通信工程专业任务书一摘要Huffman编码霍夫曼编码是可变字长编码的一种。
它是由Huffman于1952年提出的一种编码方法,该方法完全依据字符出现概率来构造异字头平均长度最短的码字,称之为最佳编码。
在数据通信中,需要将传送的文字转换成二进制的字符,用0、1码的不同排列来表示字符。
如果采用等长编码,编码的长度取决于报文中不同字符的个数。
如果报文中可能出现26个不同字符,则固定编码长度为5。
然而,传送报文时总是希望总长度尽可能短。
在实际应用中,各个字符的出现频度或使用次数是不同的,如果让使用平频率高的用短码,使用频率低的用长码,就可以优化整个报文编码。
关键字:Huffman编码最优二叉树数据压缩动态链接库目录1、Huffman算法---------------------------------------------------------------------------- 52、Huffman编码流程---------------------------------------------------------------------- 53、build_tree函数流程图-------------------------------------------------------------------- 64、问题解答----------------------------------------------------------------------------------- 75、参考文献----------------------------------------------------------------------------------- 86、源代码-------------------------------------------------------------------------------------- 9一、Huffman算法Huffman算法关键是建立Huffman树。
实验三 Huffman编码
实验三Huffman编码专业:通信工程学号:姓名:一实验目的1 通过本实验实现信源编码——Huffman编码2 编写M文件实现,掌握Huffman编码方法实验要求1 了解matlab中M文件的编辑、调试过程2 编写程序实现Huffman编码算法二实验步骤1 输入Huffman编码程序2 运行程序,按照提示输入相应信息,并记录输入信息,及运行结果。
注:观察结果方法:data(1).Code显示a1的编码,同理显示data(2).Code,a2的编码结果。
三程序的流程图四Huffman编码程序clearN=input('请输入信源符号的个数:') ;for i=1:N%data(1).name=input('请输入各信源符号的名称:');data(i).p=input('请输入各信源符号发生的概率:');endfor i=1:Npp(i)=data(i).p;data(i).imap=i; %各符号在编码过程中的指针data(i).Code=''; %各符号的编码结果endfor j = 1:N % N——信源符号的个数for i = 1:N - jif (pp(i) > pp(i + 1))fT = pp(i);pp(i) = pp(i + 1);pp(i + 1) = fT;for k = 1:Nif data(k).imap == idata(k).imap = i + 1;elseif data(k).imap == i + 1data(k).imap = i;endendendendendp=pp;%%%%%%%%%%%%%%%%%%%%%%// 计算哈夫曼编码表%// 开始编码for i=1:N-1for k = 1:Nif data(k).imap== idata(k).Code = strcat('1',data(k).Code);elseif (data(k).imap== i + 1)data(k).Code = strcat('0',data(k).Code);endendp(i + 1) = p(i + 1)+p(i);for k = 1:Nif (data(k).imap == i)data(k).imap = i + 1;endendfor j = i + 1:N-1if p(j) >p(j + 1)fT =p(j);p(j) = p(j + 1);p(j + 1) = fT;for k = 1:Nif (data(k).imap == j)data(k).imap = j + 1;elseif (data(k).imap == j + 1)data(k).imap = j;endendendendend五实验小结本实验基于静态的Huffman编码,实现了对简单字符串的Huffman编码与解码。
数字图像处理课程设计--Huffman编码理论及算法实现
数字图像处理课程设计课程题目 Huffman编码原理及算法实现Huffman编码理论及算法实现一、基本介绍霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。
所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。
树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln)N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。
可以证明霍夫曼树的WPL是最小的。
输入符号集合S={s1,s2,···,Sn},其S集合的大小为n。
权重集合W={w1,w2,···,Wn},其W集合不为负数且Wi=weight(Si),1 ≤ i ≤ n。
输出一组编码C(S,W)={c1,c2,···Cn},其C集合是一组二进制编码且Ci为Si相对应的编码,1 ≤ i ≤ n。
霍夫曼树常处理符号编写工作。
根据整组数据中符号出现的频率高低,决定如何给符号编码。
如果符号出现的频率太高,则给符号的码越短,相反符号的号码越长。
假设我们要给一个英文单字"F O R G E T"进行霍夫曼编码,而每个英文字母出现的频率。
二、演算过程(一)进行霍夫曼编码前,我们先创建一个霍夫曼树。
⒈将每个英文霍夫曼树字母依照出现频率由小排到大,最小在左。
⒉每个字母都代表一个终端节点(叶节点),比较F.O.R.G.E.T五个字母中每个字母的出现频率,将最小的两个字母频率相加合成一个新的节点。
Huffman编码译码实现
南阳理工学院数据结构课程设计哈夫曼编码和译码的实现移动1班李保11151156072012/5/16努力造就辉煌编程成就梦想------------------------------------------------------------------------------------------------------目录------------------------------------------------------------------------------------------------------一,题目介绍 (3)二,需求分析 (4)三,系统设计................................. (5)四,程序流程图 (9)五,代码 (10)六,总结 (28)七,参考书目 (29)一、题目: 哈夫曼编码/译码的设计与实现构建一棵哈夫曼树,并用哈夫曼树来实现编码各译码的功能二、目的与要求1、目的:通过布置具有一定难度的实际程序设计项目,使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法;使学生掌握分析问题,求解问题的方法并提高学生设计编程实现的能力。
2、要求:基本要求:1.要求利用C\C++语言来完成系统的设计;2.突出C语言的函数特征(以多个函数实现每一个子功能)或者C++语言面向对象的编程思想;3.画出功能模块图;4.进行简单界面设计,能够实现友好的交互;5.具有清晰的程序流程图和数据结构的详细定义;6.熟练掌握C语言或者C++语言的各种操作。
创新要求:在基本要求达到后,可进行创新设计,如系统用户功能控制,改进算法的实现,实现友好的人机交互等等二,需求分析哈夫曼树,又称最优二叉树。
上课时我了解了哈夫曼树的某些奇特而强大的功能,通过哈夫曼树构造的编码译码系统具有加密的特性,而且加密性非常好,在某些领域中应用非常广泛!而且哈夫曼树的还有很大的功能就是压缩性很好!压缩性能可以达到20%至80%!而且通信的数码拨号时,我通常会用到十进制、八进制、或者十六进制数等。
Huffman编码译码器
课程设计:Huffman编码/译码器一、任务描述任务:设计一个利用哈夫曼算法的编码和译码系统。
要求:建立一个文本文件,统计该文件中各字符频率,对各字符进行Huffman编码,将该文件翻译成Huffman编码文件,再将Huffman编码文件翻译成原文件。
“压缩文件”即:读文件、统计文件中的字符个数、对文件进行哈夫曼编码和译码、并将编码译码后的字符存储在文件中。
根据以上任务说明,设计数据结构,并设计程序完成功能。
二、问题分析分析设计课题的要求,要求编程实现以下功能:(1)创建最小Huffman树;(2)统计文件中个字符的个数(频率);(3)对个字符进行编码;(4)将原文件翻译成编码文件;(5)将编码文件翻译成原文件;(6)创建yuanwj.txt、yima.txt、out.txt三、数据结构设计选用二叉树链表实现。
有关的定义如下:typedef struct node //哈夫曼树节点的结构体定义{char data;int weight;int parent,lc,rc;}NODE;typedef struct abc{char ch;char str[20];int s;}ABC;四、功能设计(一)、主控菜单设计为实现编码译码的操作功能,首先设计一个含有多个菜单项的主控菜单程序,然后再为这些菜单项配上相应的功能。
程序运行后,给出4个菜单项的内容和输入提示,如下:1、键盘输入进行编码;2、读文件进行编码;3、译码;4、退出系统;(二)程序模块结构由课题要求可将程序划分为以下几个模块:(1)统计字符的频度tongji();(2)建立哈弗曼树haffman() ;(3)编码 huffmancode();(4)输入input();(5)输出output();(6)译码yima();(三)、函数调用关系其中main()是主函数,它进行菜单驱动,根据选择项0~3调用相应的函数。
main()函数使用switch循环实现重复选择。
huffman树及huffman编码的算法实现
huffman树及huffman编码的算法实现Huffman树是一种用于数据压缩的算法,它通过统计字符出现的频率来构建一个树形结构,从而实现对数据的编码和解码。
具体来说,Huffman编码是一种变长编码方式,将出现频率较高的字符用较短的编码表示,而出现频率较低的字符用较长的编码表示。
下面将介绍Huffman树的构建和编码算法的实现。
首先,我们需要统计字符串中每个字符出现的频率,并按照频率降序排列。
这可以通过读取字符串中的每个字符,利用一个哈希表来记录其出现的次数实现。
然后,我们将这些字符及其频率构建成一棵频率树,树的每个叶子节点代表一个字符,并带有相应的频率值。
接着,我们将这棵频率树转化为一棵Huffman树。
具体操作如下:1. 创建一个优先队列,并将频率树中的所有节点按照它们的频率值插入队列中。
2. 从优先队列中取出频率最低的两个节点,将它们合并成一个新的节点,并将新的节点插入到优先队列中。
3. 重复上述步骤,直到队列中只剩下一个节点,即根节点为止。
完成Huffman树的构建后,我们可以开始进行编码操作。
编码实际上是根据Huffman树的结构给每个字符分配一个唯一的二进制编码。
具体步骤如下:1. 从Huffman树的根节点出发,遍历整棵树,记录每个字符与根节点的路径。
路径的左分支表示编码为0,右分支表示编码为1。
2. 将每个字符及其相应的编码存储在一个哈希表中。
最后,我们可以根据Huffman编码对字符串进行压缩。
将字符串中的每个字符用相应的Huffman编码替换,将所有编码连在一起,即可得到压缩后的字符串。
反之,如果给出一个编码后的二进制字符串,我们可以通过解码树来还原原始的字符串。
以上是Huffman树及Huffman编码的算法实现的介绍。
通过构建Huffman树和根据编码表进行编码和解码,我们可以有效地压缩和解压数据,实现了数据的高效传输和存储。
数据结构哈夫曼编码
数据结构哈夫曼编码
哈夫曼编码是一种用于数据压缩的算法,它基于哈夫曼树(HuffmanTree)进行编码。
哈夫曼编码的基本思想是:对于出现频率高的字符,其编码长度较短;而对于出现频率低的字符,其编码长度较长。
这样,通过调整字符的编码长度,可以有效地压缩数据。
哈夫曼编码的具体步骤如下:
1.统计原始数据中每个字符的出现频率。
2.构建哈夫曼树。
在构建过程中,每次将两个权值最小的节点合并,并将它们的权值相加。
同时,将新生成的节点的权值作为新字符的出现频率。
3.根据哈夫曼树生成哈夫曼编码。
对于哈夫曼树中的每个字符,从根节点到该字符所在节点的路径可以形成一个二进制编码。
通常约定左分支标记为0,右分支标记为1。
这样,从根节点到每个叶节点的路径就可以形成一个二进制编码,该编码即为对应字符的哈夫曼编码。
4.使用哈夫曼编码对原始数据进行压缩。
对于原始数据中的每个字符,根据其哈夫曼编码进行编码,最终得到压缩后的数据。
需要注意的是,哈夫曼编码是一种无损压缩算法,即压缩和解压过程中可以完全还原原始数据。
同时,由于哈夫曼编码是基于字符出现频率进行编码的,因此对于出现频率高的字符,其编码长度较短;而对于出现频率低的字符,其编码长度较长。
这样可以有效地减少数据的存储空间,提高数据压缩率。
huffman源码及实现思路
哈夫曼编码:Huffman coding 是最古老,以及最优雅的数据压缩方法之一。
它是以最小冗余编码为基础的,即如果我们知道数据中的不同符号在数据中的出现频率,我们就可以对它用一种占用空间最少的编码方式进行编码。
这种方法是:对于最频繁出现的符号制定最短长度的编码,而对于较少出现的符号给较长长度的编码。
哈夫曼编码可以对各种类型的数据进行压缩,在我们的代码实现中仅针对字符进行编码。
1. 压缩数据压缩数据由以下步骤组成:a)检查字符在文件中的出现频率。
b)构建哈夫曼树。
c)为哈夫曼树中每个叶子创建哈夫曼编码。
d)生成压缩后结果文件,由一个文件头和压缩后的数据组成。
下面介绍这些步骤的一些细节。
a)字符出现的频率:我们对要压缩的文本进行扫描,然后记录下各个字符出现的次数(在这里我们的输入文本将仅仅由ascii 字符构成),扫描完成后我们就得到了一个字符的频率表。
这个频率表也是后面的文件头的重要组成部分。
为了降低文件头的尺寸,我们对字符频率压缩到用一个字节来表示。
由以下方法来完成:我们首先提供一个用于填充频率结果的数组(这个数组中前256个元素(0~255)是用来存放叶子节点的,后255个元素是用来存放毎两个节点形成的中间节点的),元素在这个数组中的索引就代表了该字符的ascii 码。
例如填充完毕后,假设数组名称是array,那么字符‘a’的出现频率即为array['a']b)构建哈夫曼树:哈夫曼编码的核心部分就在于构建哈夫曼树,它是一个二叉树。
哈夫曼树用下面的方式构建:我们把所有出现的字符作为二叉树上的一个叶子节点,在每个节点上标上一个数字代表每个字符出现的频率。
例如:如果我们要对源文件中的内容"abbcccadeeeeefff" 进行编码,则字符出现的频率如下所示:字符频率<- 回车 1d 1b 2a 2f 3c 3e 5一共有6个字符出现,因此最初我们有 6 个单节点的树。
数据结构课程设计哈夫曼编码译码器
数据结构课程设计哈夫曼编码译码器个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3:Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4:译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5:结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;3.函数说明1:CrtHuffmanTree():创建Huffman树;2:HuffmanCoding():对Huffman树进行遍历,生成Huffman编码;3:HuffmanDecoding():对Huffman编码进行译码,生成原文件内容;4:CompareFile():比较原文件和译码结果文件的内容是否一致;五、详细设计1.统计字符频率:定义结构体typedef struct strchar data;char num;str;其中data域存放字符名称,num域存放字符出现频率,读取文件ywq1.txt,通过循环比较将结果赋入S2[128]中;2.创建Huffman树:定义结构体typedef structchar data;int weight;int parent;int lchild;int rchild;HTNode,HuffmanTree[M+1];作为Huffman树存储节点类型,调用CrtHuffmanTree()函数,初始化各个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3.Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4.译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5.结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;六、测试1.测试数据测试文件:ywq1.txt(包含英文字母、数字和符号)2.测试结果测试结果正确,能够正确地对文件进行Huffman编码和译码,生成的译码结果文件与原文件内容一致;七、总结通过本次课程设计,我深入了解了Huffman编码/译码器的实现原理和过程,掌握了Huffman树的创建、存储和遍历方法,提高了动手能力,同时也为数据压缩问题提供了一种有效的解决方法。
huffman编码实现(详细实现)
huffman编码实现(详细实现)1、概述huffman编码是一种可变长编码(VLC:variable length coding))方式,于1952年由huffman提出。
依据字符在需要编码文件中出现的概率提供对字符的唯一编码,并且保证了可变编码的平均编码最短,被称为最优二叉树,有时又称为最佳编码。
2、原理在了解huffman树为最优二叉树时,先要明确下面几个概念:路径长度:树中一个节点到另一个节点之间分支构成这两个节点之间的路径,路径上的分支数目为其路径长度。
树的路径长度:树根到每一个节点的路径长度之和为“l”。
节点的带权路径长度:节点到树根之间的路径长度与节点上权的乘积。
n树的带权路径长度:所有节点的带权路径长度之和,记作WPL = ∑wk * lk 。
k=1n个节点,权值为{ w1, w2, - - -,wn },把此n个节点为叶子节点,构造一个带n个节点叶子节点的二叉树,每个叶子节点的带权路径长度为wi。
取节点a,b,c,d 其w[] = {2, 5, 7, 4},a=7 构造如下三棵树为例:图1:wpl = 7*2 5*2 2*2 4*2 = 36图2:wpl = 7*3 5*3 2*1 4*2 = 46图3:wpl = 7*1 5*2 2*3 4*3 = 35可以证明(图3)其带权路径长度最短,就是huffman树。
依次为两节点的连接线编码,左孩子为0,右孩子为1。
那么图3就变成了(图33):编码如下:a(0)、b(10)、c(110)、d(111)不知道是否有人会问为什么a、b、c、d都是树的叶子节点,而不存在某个是父节点呢?试想,如果a是c、d的父节点,假设a的编码为0,其左右孩子是b、c,那么b,c的编码分别是00,和01,那么当出现诸如010001的压缩串时,可分别解释为caac,cbc,因为在出现a时,如果后面的编码为0,则不确定是解释为aa还是b了,出现歧义就出问题,所以字符只能出现在叶子节点。
实验六 Huffman编码算法实现
实验六 Huffman编码算法实现---2011级通信一班尚青一、实验目的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”;⑥从根节点开始,对符号进行编码;⑦译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。
四、实验代码及结果function [h,l,hh,t]=huffman(p)%判断输入合不合法if (~isempty(find(p<0, 1)))error('Not a prob,negative component');endif (abs(sum(p)-1)>10e-10)error('Not a prob.vector,component do not add to 1')endn=length(p);q=p; %数组p附给qm=zeros(n-1,n); %创建(n-1)*n矩阵for i=1:n-1[q,l]=sort(q);%对概率数组q 进行从小至大的排序,并且用l 数组返回一个数组,该数组表示概率数组q 排序前的顺序编号m(i,:)=[l(1:n-i+1),zeros(1,i-1)];%由数组l 构建一个矩阵,该矩阵表明概率合并时的顺序,用于后面的编码q=[q(1)+q(2),q(3:n),1];%将排序后的概率数组q 的前两项,即概率最小的两个数加和,得到新的一组概率序列endfor i=1:n-1c(i,:)=blanks(n*n);%生成一个n-1 行n 列,并且每个元素的的长度为n 的空白数组,c 矩阵用于进行huffman 编码并且在编码中与 m矩阵有一定的对应关系endc(n-1,n)='0';%由于c矩阵的第n-1 行的前两个元素为进行huffman 编码加和运算时所得的最c(n-1,2*n)='1';%后两个概率,因此其值为0 或1,在编码时设第n-1 行的第一个空白字符为0,第二个空白字符1。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《计算机系统结构教程》课程设计实验报告(课程设计题目:hufferman指令优化)专业 ********************班级********************学号*****学生姓名 ********任课教师 ********2016年4月一、课设目的1)学习简单的文件输入输出程序设计;2)掌握huffman树的构建的方法;3)在指令操作码的优化上huffman编码可以实现操作码编码的优化,用最短的位数来表示指令的操作信息和地址信息。
二、任务要求1) 使用哈夫曼编码来优化指令操作码编码。
2)数据的输入、输出通过文件操作。
3)输出编码、信息熵、平均码长、以及生成的huffman树形三、开发环境操作系统:Windows 10开发工具:Eclipse环境 jdk1.8四、项目原理及算法思想哈夫曼树(Huffman tree),又名最优树,指给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。
哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。
n个权值分别设为w1、w2、…、wn,则哈夫曼树的构造规则为:(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;(3)从森林中删除选取的两棵树,并将新树加入森林;(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
将每个字符的出现频率作为字符结点的权值赋予该结点上,显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度。
因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。
霍夫曼树的构造思想是,先将权值集合看作只有一个节点的树的集合,每次选最小的两个权值的树构造一颗新树,新树根节点的权值是左右子树的权值和,在权值集合中删除这两颗权值最小的树,将新生成的树放入权值集合中。
如此重复下去,直到权值集合中只有一个元素,这就是最后整棵树的根节点了。
五、具体实现过程(按照左1右0的原则编码)首先设计txt文件读入需要输入的字符串数据,然后将字符串数据放在字符数组中,遍历该字符数组,使用同一个字符出现次数来代替该字符的出现频率。
将字符和其对应的出现频率放在一个表中,创建一个优先级队列,频率低的字符优先级更低,遍历搜索后将优先级最低的两个分别作为左右节点,从优先级队列中删除,同时将他们的父节点添加进队列,进行遍历比较,重复讲优先级最低的两个作为左右节点,最后将优先级最高的节点作为根节点,然后利用顶部节点创建Tree。
创建一个JFrame窗口,绘图大小为500*500,采用后序遍历的方式将Huffman Tree的每个节点对应到Graphics中,提前重写point函数和父类绘制窗体的方法,存储所画图形的列表,使用循环坐标点画线赋值来绘制一个树,同时将节点对应的字符标记在旁边。
文件输出,包括程序运行时间long starMili = System.currentTimeMillis();long endMili = System.currentTimeMillis();FileIO.writeStringToFile("程序运行时间 :" + (endMili - starMili) + "ms\r\n" , "fileout.txt");输入字符串,输出每个字符对应的Huffman编码,Huffman的完整编码,平均码长六、运行结果七、感想体会Huffman编码的实现过程中参考了各种各样的资料,在具体的代码编写过程中也遇到了各种各样的问题,遇到的最大难点就是在java中实现画树的操作,通过对于JFrame和Graphics,Shape的学习,了解到了应该怎样通过坐标来完成树的绘制。
在测试过程中,发现在绘图窗口中的字符和所划线有部分重叠遮挡,验证后发现是绘图窗口父类的调用问题,通过repaint函数进行重绘解决。
同时在调试过程中发现不能正确输出中文字符。
out.write(sb.toString().getBytes("utf-8"));//字符编码格式要改为utf-8,才能正确输出中文字符八、参考文献1.哈夫曼树的java实现 - jdhanhua的专栏 - 博客频道 - /jdhanhua/article/details/66210262.【code】java创建哈夫曼树和实现哈夫曼编码 - 不积跬步无以至千里不积小流无以成江海 - ITeye技术网站 /blog/11066933.JAVA画树_百度知道/link?url=ByCZne2MvpcBosGuMjMn9sArxnVencgGc-Mq 1pHYrOotiuubTwry7SvYkBlH1FCqLAVi-I9QV4mCWiAPsJWGDK4.repaint()如何理解??-CSDN论坛-中国最大的IT技术社区/topics/120068510九、附录代码主函数:package main;import java.io.IOException;import java.util.Map;import utils.FileIO;import main.HuffmanCode;import erPrint;public class Run {/***** @param args* @throws IOException*/public static void main(String[] args) throws IOException {// TODO Auto-generated method stublong starMili = System.currentTimeMillis();String oriStr = FileIO.BufferedReaderDemo("fileread.txt");Map<Character, Integer> statistics = HuffmanCode.statistics(oriStr.toCharArray());String encodedBinariStr = HuffmanCode.encode(oriStr, statistics);System.out.println("输入字符串: " + oriStr);System.out.println("输出霍夫曼编码: " + encodedBinariStr);long endMili = System.currentTimeMillis();FileIO.writeStringToFile("输出"+oriStr+"对应的霍夫曼编码: " + encodedBinariStr +"\r\n" , "fileout.txt");FileIO.writeStringToFile("程序运行时间:" + (endMili - starMili) + "ms\r\n" , "fileout.txt");FileIO.writeStringToFile("平均码长= " +averageLongth+"\r\n", "fileout.txt");}}Huffman编码操作package main;import java.io.IOException;import java.util.*;import tree.Node;import tree.Tree;public class HuffmanCode {/*** 统计数据,将key为Node中的char,value为key出现的次数以次数代替出现的频率,方便处理。
** @param 传入的字符串转化为的字符数组charArray* @return*/public static Map<Character, Integer> statistics(char[] charArray) {// 创建HashMapMap<Character, Integer> map = new HashMap<Character, Integer>();// 逐个遍历charArray中的每个字符for (char c : charArray) {Character character = new Character(c);if (map.containsKey(character)) { // 如果map中包含这个键值对,则给它的值+1map.put(character, map.get(character) + 1);} else { // 如果map中没有这个键值对,则将之初始化为1map.put(character, 1);}}return map;}/*** 构建huffman树** @param hashMap* :statistics 为char和frequence的键值对* @param 叶子节点leafs* @return 构建好的huffman树:tree*/private static Tree buildTree(Map<Character, Integer> statistics,List<Node> leafs) {Character[] keys = statistics.keySet().toArray(new Character[0]);// 初始化Node型的优先级队列priorityQueuePriorityQueue<Node> priorityQueue = new PriorityQueue<Node>();for (Character character : keys) {// 逐个遍历statistics中的Character(key数组)// 设置node中属性Node node = new Node();node.setChars(character.toString());node.setFrequence(statistics.get(character));// 将该node置入优先级队列priorityQueue.add(node);// 给leafs列表中加入nodeleafs.add(node);}// 获取priorityQueue的容量int size = priorityQueue.size();for (int i = 1; i <= size - 1; i++) {// 按照优先级遍历完priorityQueue中的元素// poll出优先级最低的两个节点,并将他们从priorityQueue中删除Node node1 = priorityQueue.poll();Node node2 = priorityQueue.poll();// 创建新父节点sumNodeNode sumNode = new Node();// 新节点的值以及优先级为node1和node2相加sumNode.setChars(node1.getChars() + node2.getChars());sumNode.setFrequence(node1.getFrequence() + node2.getFrequence());// 设置node1,node2分别为新节点的左,右子节点sumNode.setLeftNode(node1);sumNode.setRightNode(node2);// 将node1,node2的父节点设置为sumNodenode1.setParent(sumNode);node2.setParent(sumNode);// 将新生成的sumNode节点加入priorityQueue中,并且由priorityQueue 内部自动进行排序priorityQueue.add(sumNode);}// 取出优先级队列中仅剩的一个节点,作为根节点画出Huffman树utils.drawTree.drawHuffmanTree(priorityQueue.peek());// 用顶部节点构建Tree并返回Tree tree = new Tree();tree.setRoot(priorityQueue.poll());return tree;}/*** 编码** @param 原来的字符串originalStr* @param char和frequence的键值对* :statistics* @return 编码后的huffman串buffer.toString()* @throws IOException*/public static String encode(String originalStr,Map<Character, Integer> statistics) throws IOException {if (originalStr == null || originalStr.equals("")) {// 若原字符串为空,则返回""return "";}// 将原字符串从String型转化为字符数组处理char[] charArray = originalStr.toCharArray();// 初始化叶子节点列表leafNodesList<Node> leafNodes = new ArrayList<Node>();// 用statistics返回一个构建好的HuffmanTreebuildTree(statistics, leafNodes);// 调用buildEncodingInfo对叶子节点进行编码Map<Character, String> encodInfo = buildEncodingInfo(leafNodes);// 初始化buffer,将编码后的二进制存放进去StringBuffer buffer = new StringBuffer();for (char c : charArray) {Character character = new Character(c);buffer.append(encodInfo.get(character));}// 将编好的huffman编码输出到fileout.txt中utils.FileIO.writeHuffmanCodeToFile(encodInfo, "fileout.txt");return buffer.toString();}/*** 编码规则规定左1右0的编码方式** @param 叶子节点* :leafNodes* @return codewords*/private static Map<Character, String> buildEncodingInfo(List<Node> leafNodes) { Map<Character, String> codewords = new HashMap<Character, String>();for (Node leafNode : leafNodes) {// 遍历所有叶子节点Character character = new Character(leafNode.getChars().charAt(0));// 初始化codewordString codeword = "";// 初始化当前节点Node currentNode = leafNode;do {//当当前节点有父节点时进行if (currentNode.isLeftChild()) {// 如果当前节点为左子节点codeword = "1" + codeword;} else {// 当前节点为右子节点codeword = "0" + codeword;}//将当前节点的父节点设置为新的父节点currentNode = currentNode.getParent();} while (currentNode.getParent() != null);//将编号的huffman编码以及对应的character存入codewords键值对中codewords.put(character, codeword);}return codewords;}}绘制Huffman树图形package utils;import java.awt.Graphics;import tree.Node;import ui.drawLine;import ui.MyWindow;import ui.Word;/*** 画出huffman树的方法**/public class drawTree {/*** 画Huffman树* @param 根节点root*/public static void drawHuffmanTree(Node root) {MyWindow jf = new MyWindow();jf.setSize(500, 500);jf.setVisible(true);jf.setDefaultCloseOperation(3);drawTree(root, jf, 200, 100, 1);}/*** 后序遍历Huffman树,并且将它们画出* @param 根节点:a* @param 封装好的MyWindow:jf* @param 横坐标:x* @param 纵坐标:y* @param 层数:level*/public static void drawTree(Node a, MyWindow jf, int x, int y, int level) { //初始化图形gGraphics g = jf.getGraphics();//level加一level++;level++;level++;level++;level++;if (a.getLeftNode() == null && a.getRightNode() == null) {g.drawString("" + a.getChars(), x, y);jf.getShapes().add(new Word(a.getChars(), x-5, y));//在树边标记对应字符// System.out.println("绘制节点" + a.getChars());}if (a.getLeftNode() != null) {g.drawLine(x, y, x - 500 / level, y + 10 * level);jf.getShapes().add(new drawLine(x, y, x - 500 / level, y + 10 * level));drawTree(a.getLeftNode(), jf, x - 500 / level, y + 10 * level, level);}if (a.getRightNode() != null) {g.drawLine(x, y, x + 500 / level, y + 10 * level);jf.getShapes().add(new drawLine(x, y, x + 500 / level, y + 10 * level));drawTree(a.getRightNode(), jf, x + 500 / level, y + 10 * level, level);}}}文件操作package utils;import java.io.*;import java.util.Iterator;import java.util.Map;public class FileIO {/*** 利用PrintStream写文件* @param 文件路径path* @return String字符串* @throws IOException*/public static String BufferedReaderDemo(String path) throws IOException{File file=new File(path);if(!file.exists()||file.isDirectory())throw new FileNotFoundException();BufferedReader br = new BufferedReader(new FileReader(file));String temp=null;StringBuffer sb=new StringBuffer();temp=br.readLine();while(temp!=null){sb.append(temp);temp=br.readLine();}return sb.toString();}public static void writeHuffmanCodeToFile(Map<Character, String> encodInfo,String path) throws IOException{File file=new File(path);if(!file.exists())file.createNewFile();FileOutputStream out=new FileOutputStream(file,true);StringBuffer sb=new StringBuffer();out.write("所有的Huffman编码如下所示:\r\n".toString().getBytes("utf-8"));Iterator<Character> itor = encodInfo.keySet().iterator();while(itor.hasNext()){Character key = itor.next();String value = encodInfo.get(key);sb.append("字符:"+ key + "----对应霍夫曼编码:"+ value +"\r\n");}out.write(sb.toString().getBytes("utf-8"));//字符编码格式要改为utf-8,才能正确输出中文字符out.close();}public static void writeStringToFile(String writeStr,String fileStr) throws IOException{ File file = new File(fileStr);if (!file.exists())file.createNewFile();FileOutputStream out = new FileOutputStream(file, true);out.write(writeStr.getBytes("utf-8"));//字符编码格式要改为utf-8,才能正确输出中文字符out.close();}}。