精华内容
下载资源
问答
  • 哈夫曼树和哈夫曼编码唯一吗?
    千次阅读
    2021-12-11 21:58:24

    哈夫曼树和编码都不唯一!只有树的WPL(带权路径长度)才是唯一的!

    更多相关内容
  • 哈夫曼编码

    千次阅读 2020-12-29 21:27:44
    然而哈夫曼编码并不是唯一的。例如对字符串"aaaxuaxz",容易得到字母 ‘a’、‘x’、‘u’、‘z’ 的出现频率对应为 4、2、1、1。我们可以设计编码 {‘a’=0, ‘x’=10, ‘u’=110, ‘z’=111},也可以用另一套 {‘a...

    7-7 哈夫曼编码 (30分)
    给定一段文字,如果我们统计出字母出现的频率,是可以根据哈夫曼算法给出一套编码,使得用此编码压缩原文可以得到最短的编码总长。然而哈夫曼编码并不是唯一的。例如对字符串"aaaxuaxz",容易得到字母 ‘a’、‘x’、‘u’、‘z’ 的出现频率对应为 4、2、1、1。我们可以设计编码 {‘a’=0, ‘x’=10, ‘u’=110, ‘z’=111},也可以用另一套 {‘a’=1, ‘x’=01, ‘u’=001, ‘z’=000},还可以用 {‘a’=0, ‘x’=11, ‘u’=100, ‘z’=101},三套编码都可以把原文压缩到 14 个字节。但是 {‘a’=0, ‘x’=01, ‘u’=011, ‘z’=001} 就不是哈夫曼编码,因为用这套编码压缩得到 00001011001001 后,解码的结果不唯一,“aaaxuaxz” 和 “aazuaxax” 都可以对应解码的结果。本题就请你判断任一套编码是否哈夫曼编码。

    输入格式:
    首先第一行给出一个正整数 N(2≤N≤63),随后第二行给出 N 个不重复的字符及其出现频率,格式如下:

    c[1] f[1] c[2] f[2] … c[N] f[N]
    其中c[i]是集合{‘0’ - ‘9’, ‘a’ - ‘z’, ‘A’ - ‘Z’, ‘_’}中的字符;f[i]是c[i]的出现频率,为不超过 1000 的整数。再下一行给出一个正整数 M(≤1000),随后是 M 套待检的编码。每套编码占 N 行,格式为:

    c[i] code[i]
    其中c[i]是第i个字符;code[i]是不超过63个’0’和’1’的非空字符串。

    输出格式:
    对每套待检编码,如果是正确的哈夫曼编码,就在一行中输出"Yes",否则输出"No"。

    注意:最优编码并不一定通过哈夫曼算法得到。任何能压缩到最优长度的前缀编码都应被判为正确。

    输入样例:

    7
    A 1 B 1 C 1 D 3 E 3 F 6 G 6
    4
    A 00000
    B 00001
    C 0001
    D 001
    E 01
    F 10
    G 11
    A 01010
    B 01011
    C 0100
    D 011
    E 10
    F 11
    G 00
    A 000
    B 001
    C 010
    D 011
    E 100
    F 101
    G 110
    A 00000
    B 00001
    C 0001
    D 001
    E 00
    F 10
    G 11
    

    输出样例:

    Yes
    Yes
    No
    No
    

    这题的主要目标就是判断是不是哈夫曼编码,哈夫曼编码有两个特点:1 最短带权路径长度WPL; 2 编码互不为前缀。
    所以我们可以根据给出的字符和出现频率,先建一个哈夫曼树,求出其平均码长(WPL)。
    然后根据接下来输入的信息做两步判断。
    1 判断平均码长是否相同,若不同,则肯定不是哈夫曼编码
    2 编码是否互相不为前缀,只有互相不为前缀才是合理的编码

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    struct HuffmanNode{
    	char data;
    	double weight;
    	int parent,lchild,rchild;
    };
    class HuffmanTree{
    	private:
    		vector<HuffmanNode> hufftree;
    		int n;
    		void SelectSmall(int &least,int &less,int n)
    		{
    			int cnt=0;
    			for(int i=0;i<n;i++)
    			{
    				if(hufftree[i].parent==-1)
    				{
    					if(cnt==0) least=i;
    					else if(cnt==1) {
    						if(hufftree[i].weight<hufftree[least].weight)
    						{
    							less=least;least=i;
    						}
    						else
    							less=i;
    					}
    					else
    					{
    						if(hufftree[i].weight<hufftree[least].weight)
    						{
    							less=least;least=i;
    						}
    						else
    						{
    							if(hufftree[i].weight<hufftree[less].weight)
    								less=i;
    						}
    					}
    					
    					cnt++;
    				}
    			}
    		}
    	public:
    		//HuffmanTree的构造函数 
    		HuffmanTree(vector<HuffmanNode> &leafs)
    		{
    			n=leafs.size();
    			hufftree.resize(2*n-1);
    			int i;
    			for( i=0;i<n;i++)
    			{
    				hufftree[i].data=leafs[i].data;
    				hufftree[i].weight=leafs[i].weight;
    				hufftree[i].parent=hufftree[i].lchild=hufftree[i].rchild=-1;
    			}
    			for(i=n;i<2*n-1;i++)
    			{
    				int least,less;
    				SelectSmall(least,less,i);
    				hufftree[least].parent=hufftree[less].parent=i;
    				hufftree[i].parent=-1;
    				hufftree[i].lchild=least;
    				hufftree[i].rchild=less;
    				hufftree[i].weight=hufftree[least].weight+hufftree[less].weight;
    			}
    		}
    		//Huffman编码算法 
    		vector<int> GetCode(int i)
    		{
    			vector<int> code;
    			int p=i;
    			int parent=hufftree[i].parent;
    			while(parent!=-1)
    			{
    				if(hufftree[parent].lchild==p)
    					code.insert(code.begin(),'0');
    				else
    					code.insert(code.begin(),'1');
    				p=parent;
    				parent=hufftree[parent].parent;
    			}
    			return code;
    		}
    };
    int main()
    {
    	vector<HuffmanNode> leafs;
    	vector<int> x,source;
    	string result;
    	int N,M;
    	cin>>N;
    	struct HuffmanNode Huffman[100];
    	for(int i=0;i<N;i++)
    	{
    		cin>>Huffman[i].data>>Huffman[i].weight;
    		leafs.push_back(Huffman[i]);
    	}
    //	for(int i=0;i<N;i++)
    //	{
    //		cout<<leafs[i].data<<" "<<leafs[i].weight<<endl;
    //	}
    	HuffmanTree BT(leafs);
    	int s=0;
    	//先计算哈夫曼树编码的平均码长(最短带权路径) 
    	for(int i=0;i<N;i++)
    	{
    		vector<int> v=BT.GetCode(i);
    		s=s+v.size()*Huffman[i].weight;
    	}
    	cin>>M;char ch;
    	while(M--)
    	{
    		int s1=0;
    		string str[100];
    		for(int i = 0; i < N; i++) {
                cin>>ch>>str[i];
                s1 = s1 + str[i].size() * Huffman[i].weight;
            }
            //平均码长相同,则看任何编码是不是都符合不为其他编码前缀这一条件 
            if(s==s1){
            	bool res=true;
            	for(int i=0;i<N-1;i++)
            	{
            		for(int j=i+1;j<N;j++)
            		{
            			int flag=0,size=0;
            			if(str[i].size()>str[j].size()) size=str[j].size();
            			else size=str[i].size();
            			for(int k=0;k<size;k++)
            			if(str[i][k]!=str[j][k]) flag=1;
            			
            			if(!flag) res=false;
    				}
    			}
    			if(res) cout<<"Yes"<<endl;
    			else cout<<"No"<<endl;
    		}
    		//平均码长不同,则肯定不是哈夫曼编码 
    		else {
    			cout<<"No"<<endl;
    		}
    	} 
    	
    	return 0;
    }
    
    展开全文
  • 哈夫曼树的定义 我们给树的结点赋予一个表示某种意义的值,称为该结点的权; 我们再定义从根结点到某个结点需要经过的边数,与该结点的权的乘积,称为结点的带权路径长度; 所有叶子结点的带权路径长度之和,称为树...

    哈夫曼树的定义

    我们给树的结点赋予一个表示某种意义的值,称为该结点的权

    我们再定义从根结点到某个结点需要经过的边数,与该结点的权的乘积,称为结点的带权路径长度

    所有叶子结点的带权路径长度之和,称为树的带权路径长度,记为WPL

     
    下面,先来直观感受一下WPL的含义:

    在这里插入图片描述

    (a) WPL = 7×2 + 5×2 + 2×2 + 4×2 = 36

    (b) WPL = 4×2 + 7×3 + 5×3 + 2×1 = 46

    (c) WPL = 7×1 + 5×2 + 2×3 + 4×3 = 35

     
    好了,下面给出哈夫曼树的定义:

    在含有n个带权叶子结点的所有二叉树中,其中带权路径长度(WPL)最小的二叉树称为哈夫曼树。

     
     
     

    哈夫曼树的构造

    给定n个带有权值的结点,构造哈夫曼树的算法描述如下:

    选出权值最小的两个结点,构造成一个新的结点,且新结点的权值看作两个结点的权值之和;不断重复这个过程。

    由此构造出的哈夫曼树有如下特点:

    1)每个结点最终都会称为叶子结点,权值越小的叶子越靠下,权值越大的叶子越靠上;

    2)构造过程是个两两结合的过程,因此共新建了 n-1 个结点,最终哈夫曼树的总结点数为 2n-1

    3)构造过程是个两两结合的过程,因此不会出现度为 1 的结点;

    4)构造出的哈夫曼树是不唯一的,但是最小带权路径长度(WPL)是最小且唯一的。

     
    看看图解,一下就会!!!以 {3,5,6,9,12} 为例:

    在这里插入图片描述

     
     
     

    哈夫曼编码

    在数据通信中,对字符的编码可以是长度固定的,也可以是长度不等的。可变长度编码有个极大的好处,就是可以使得字符的平均编码长度减短,起到数据压缩的效果。

    想要对不同的字符使用不同长度的编码的前提是,一个编码不能是另一个编码的前缀。这不难理解,假设合法编码有“110”、“11”、“0”,那么在翻译“1100”时,分割结果是不唯一的。

    哈夫曼树有一个优秀的性质,即权值越小的叶子越靠下,权值越大的叶子越靠上。那么,如果我们把叶子结点权值设置为字符出现的频度,比给边标记上0/1,将从根结点到叶子经过的边的所有标记序列作为编码的话——频度越高的字符编码越短,频度越低的字符编码越长,并且不会出现一个编码是另一个编码的前缀的情况!

    还是看个栗子吧 >_<!!!

    在这里插入图片描述

    展开全文
  • 哈夫曼树 概念 哈夫曼树也是二叉树 叶子结点的权值,权值比如重要性,某种含义的数字 叶子结点的带权路径长度 = 根到该结点的路径长度(也可以说是该叶子结点的父亲结点的高度)*该结点的权值 树的带权路径长度WPL...

    哈夫曼树

    在这里插入图片描述

    1. 概念

      • 哈夫曼树也是二叉树
      • 叶子结点的权值,权值比如重要性,某种含义的数字
      • 叶子结点的带权路径长度 = 根到该结点的路径长度(也可以说是该叶子结点的父亲结点的高度)*该结点的权值
      • 树的带权路径长度WPL = 树中所有叶子结点的带权路径长度之和
      • 哈夫曼树是WPL最小的二叉树,比它大的都不叫哈夫曼树,由此可见哈夫曼树也是最优二叉树
    2. 构造哈夫曼树

      • 每次选2个叶子结点权值最小的合并,并将2个权值的和作为新的根结点的权值
      • 由此可见,如果有n个结点,会有n-1次合并,也就是会多出n-1个非叶子结点,整个二叉树的结点=n + n -1 = 2n-1
      • 哈夫曼树不唯一,但是WPL的值都是最小值
    3. 哈弗曼编码

      • 将字符出现频次作为字符结点的权值,权值越大的叶子结点我们放在离根节点最近的地方,可以使得WPL值最小,来构造哈夫曼树,由此可见也可以压缩数据
      • 前缀编码,没有一个编码是另外一个编码的前缀,这个作用是我们可以顺序识别一串二进制代表的意思,没有歧义
      • 固定长度编码,每个字符用等长的二进制表示
      • 可变长编码,允许不同字符用不等长的二进制表示

    例子,构造哈夫曼树过程
    在这里插入图片描述

    展开全文
  • 哈夫曼树以及哈夫曼编码

    千次阅读 2017-01-11 15:39:10
    1.哈夫曼树 假设有n个权值{w1, w2, …, wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树。...哈夫曼编码 通信传
  • 0023 算法笔记贪心算法哈夫曼编码问题 1 问题描述 哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法 其 压缩率通常在 20% 90% 之间哈夫曼编码 算法 用字符在文件中出现的 频率表来建立一个用 0 1 串表示各...
  • 2)哈夫曼编码是最小冗余码,其编码方式并不唯一,例如,字符串“aaxuaxz”中各字符的出现的频率分别为a:4、x:2、u:1、z:1。编码{'a'=0, 'x'=10, 'u'=110, 'z'=111}和 {'a'=1, 'x'=01, 'u'=001, 'z'=000}都可以将该...
  • 哈夫曼编码(30分)

    千次阅读 2020-02-10 17:02:05
    然而哈夫曼编码并不是唯一的。例如对字符串"aaaxuaxz",容易得到字母 'a'、'x'、'u'、'z' 的出现频率对应为 4、2、1、1。我们可以设计编码 {'a'=0, 'x'=10, 'u'=110, 'z'=111},也可以用另一套 {'a'=1, 'x'=01, '...
  • 哈夫曼编码原理了解一下

    万次阅读 2018-06-14 21:27:16
    什么是哈夫曼编码呢?这种编码方法在1952年由美国计算机科学家戴维·哈夫曼先生提出,它是一种数据压缩技术。这是一种很著名的编码方法哦,我们来了解一下吧。为啥说它是一种数据压缩技术呢,这完全因为它的编码思想...
  • 6.6 Huffman树及其应用;教学内容;数据结构;解决方案1;解决方案2;数据结构;数据结构;Huffman树的一个实例;Huffman树的一个实例;Huffman树的一个实例;Huffman树的构造思路;数据结构;13;数据结构;...2020/3/
  • 哈夫曼树、哈夫曼编码详解

    千次阅读 多人点赞 2021-06-17 09:33:06
    哈夫曼树、哈夫曼编码,也就这么一回事,一文搞懂!
  • 数据结构之哈夫曼编码

    万次阅读 2018-11-11 20:27:39
    (1)数据结构 基于哈夫曼编码的通信系统的设计与实现 https://zhidao.baidu.com/question/130785002.html?qbl=relate_question_3&amp;amp;amp;word=���ù�������������ͨ�ſ��Դ�����...
  • 信息论与编码课程中的哈夫曼编码唯一可译码的课程设计过程代码及总结
  • 哈夫曼树和哈夫曼编码

    千次阅读 2020-02-07 23:25:34
    1.哈夫曼树 叶子结点的路径长度是指从根结点出发到达该结点所经过的边数。 把叶子结点的权值乘以其路径长度的结果称为这个叶子结点的带权路径长度。 另外,树的带权路径长度( Weighted PathLength of Tree,WPL)...
  • Huffman编码效果的唯一

    千次阅读 2019-05-30 11:10:51
    在构造霍夫曼树的时候发现会出现两个17,这时就有两条路可以走下去,当然,因为树的不固定会有若干种结果,比如你的A是10110,他的A是00000,但就编码长度而言都是5,这里说的两条路就是A的长度可以为4也可以为5,...
  • 详解哈夫曼树和哈夫曼编码

    千次阅读 多人点赞 2021-04-25 11:01:29
    哈夫曼树 并查集是一种用来管理元素分组情况的数据结构,可以高效地进行查询、合并操作,但无法进行分割操作。 1.查询元素a和元素b是否属于同一组 2.合并元素a和元素b所在的组 并查集使用树形结构实现,但不是...
  • 详解哈夫曼编码

    千次阅读 2021-04-29 13:36:36
    详解哈夫曼编码 概述 通常的编码方法有固定长度和不等长度编码两种。 最优编码方案的目的是使总码长度最短。利用字符的使用频率来编码,是不等长编码方法,使得经常使用的字符编码较短,不常使用的字符编码较长。...
  • 【数据结构】哈夫曼树、哈夫曼编码

    千次阅读 多人点赞 2022-05-09 20:38:24
    哈夫曼树是由麻省理工学院的哈夫曼博士于1952年发明,这到底是一颗什么样的树呢? 刚才我们学习了树的带权路径长度(WPL),而哈夫曼树(Huffman Tree)是在叶子结点和权重确定的情况下,带权路径长度最小的二叉树,...
  • 哈夫曼编码C++实现

    千次阅读 2021-11-20 10:37:04
    使用数组存储哈夫曼树进行哈夫曼编码
  • 哈夫曼编码(Huffman Coding)

    千次阅读 2021-01-05 10:53:34
    霍夫曼编码、哈夫曼编码、编码压缩、不等长编码、等长编码
  • 哈夫曼树 哈夫曼树的定义:设二叉树具有 n 个带权值的叶节点,那么从根节点到各个叶节点的路径长度与相应叶节点权值的乘积的和,叫...哈夫曼编码就是规定哈夫曼树中的左分支为 0,右分支为 1,从根节点到每个叶节点所经
  • 哈夫曼树与哈夫曼编码及代码实现

    万次阅读 多人点赞 2020-03-18 12:43:30
    哈夫曼树与哈夫曼编码的理解 数据压缩 含义 通过对数据重新的编码,减少数据占用的空间存储;使用的时候再进行解压缩,恢复数据的原有特性。 类别 无损压缩——压缩过程没有数据丢失,解压得到原有数据特性。 有损...
  • 摘要:作为一种常用的编码方式即哈夫曼编码,很多人在它的原理即应用方面都弄不不清楚,本文主要以哈夫曼编码原理与应用实例及算法流程图俩进一步说明。哈夫曼编码定义哈夫曼编码(Huffman Coding),又称霍夫曼编码,...
  • 按词频从小到大的顺序给出各个字符(不超过30个)的词频,根据词频构造哈夫曼树,给出每个字符的哈夫曼编码,并对给出的语句进行译码。 为确保构建的哈夫曼树唯一,本题做如下限定: (1)选择根结点权值最小的两棵...
  • 问题标题对于香农编码、费诺编码和哈夫曼编码,编码方法惟一的是()。2019-8-15来自ip:15.170.14.227的网友咨询浏览量:533手机版问题补充:题目类型:[填空题] 对于香农编码、费诺编码和哈夫曼编码,编码方法惟一的是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,903
精华内容 1,561
关键字:

哈夫曼编码唯一吗