其它pta数据结构编程题请参见:pta

题目

题目给出一组字母和每个字母的频数,因为哈夫曼编码不唯一,然后给出几组编码,因为哈夫曼编码不唯一,所以让你判断这些编码是否符合是哈夫曼编码的一种。

解题思路:

1、构造哈夫曼树,并求出总代价COST,即各个字母的频数乘以编码长度的和。

2、对于题目给出的每一组编码,判断是否符合哈夫曼编码,即这组编码是否为前缀码,同时代价cost是否等于计算出的哈夫曼树的代价COST。

判断一组编码是否为前缀码的方法:

将这些编码逐个的添加到哈夫曼树中,对于每一个编码字符串,字符串中的每一个字符也逐个扫描,如果是0则向左构造树,1则向右构造树。如果已扫描到某节点为叶子节点但字符串还未结束,或者字符串已扫描结束但还当前节点非空,那么就不是前缀码。

需要注意的点:

最小堆数组中的元素类型ElementType为HuffmanTree型。

 #include <iostream>
#include <string>
#include <map>
using namespace std; /*----------哈夫曼树定义---------*/
typedef struct HuffmanNode *HuffmanTree;
struct HuffmanNode
{
int weight;
HuffmanTree left, right;
};
/*----------最小堆定义-----------*/
#define minData -1;
typedef HuffmanTree ElementType;
typedef struct HeapNode* minHeap;
struct HeapNode
{
ElementType *data;
int size;
};
/*----------最小堆相关操作--------*/
minHeap buildHeap(int N);
void percDown(minHeap H, int p);
void insert(minHeap H, HuffmanTree x);
HuffmanTree deleteMin(minHeap H);
/*----------哈夫曼树相关操作------*/
HuffmanTree huffman(int N);
HuffmanTree initHuffmanNode(int weight);
bool cmp(HuffmanTree a, HuffmanTree b);
void getLength(HuffmanTree T, int& total, int length);
/*----------其它操作--------------*/
bool valid(int N, int total);
HuffmanTree insertHuffman(HuffmanTree T, string s, int n, bool& judge);
map<string, int> mapp;
/*--------------------------------*/ int main()
{
int N, M, i;
cin >> N;
HuffmanTree T = huffman(N); //构造哈夫曼树
int total = ; //总哈夫曼编码长度
getLength(T, total, );
cin >> M;
for (i = ; i < M; i++)
{
if (valid(N, total)) cout << "Yes" << endl;
else cout << "No" << endl;
}
return ;
} HuffmanTree initHuffmanNode(int weight)
{
HuffmanTree T = new HuffmanNode;
T->weight = weight;
T->left = T->right = NULL;
return T;
} minHeap buildHeap(int N)
{
minHeap H = new HeapNode;
H->data = new ElementType[N + ];
H->size = ;
H->data[] = initHuffmanNode(-);//哨兵 string c;
int i, t;
for (i = ; i <= N; i++)
{
cin >> c >> t;
mapp[c] = t;
H->data[i] = initHuffmanNode(t);
}
H->size = N; /* 调整堆中的元素 */
for (i = H->size / ; i > ; i--)
percDown(H, i);
return H;
} void percDown(minHeap H, int p)
{ /* 下滤:将H中以H->Data[p]为根的子堆调整为最小堆 */
int parent, child;
ElementType X = H->data[p];
for (parent = p; parent * <= H->size; parent = child)
{
child = parent * ;
if (child != H->size && cmp(H->data[child], H->data[child + ]))
child++;
if (!cmp(X, H->data[child])) break;
else
H->data[parent] = H->data[child];
}
H->data[parent] = X;
} void insert(minHeap H, HuffmanTree x)
{
int i;
for (i = ++H->size; cmp(H->data[i / ], x); i /= )
H->data[i] = H->data[i / ];
H->data[i] = x;
} HuffmanTree deleteMin(minHeap H)
{
HuffmanTree minItem = H->data[];
ElementType x = H->data[H->size--];
int parent, child;
for (parent = ; parent * <= H->size; parent = child)
{
child = parent * ;
if (child != H->size && cmp(H->data[child], H->data[child + ]))
child++; //将两个子节点中较小的一个和x比较
if (!cmp(x, H->data[child])) break;
else
H->data[parent] = H->data[child];
}
H->data[parent] = x;
return minItem;
} HuffmanTree huffman(int N)
{
HuffmanTree T;
minHeap H = buildHeap(N); while (H->size > )
{
T = new HuffmanNode;
T->left = deleteMin(H);
T->right = deleteMin(H);
T->weight = T->left->weight + T->right->weight;
insert(H, T);
}
T = deleteMin(H);
return T;
} bool cmp(HuffmanTree a, HuffmanTree b)
{
return a->weight > b->weight;
} void getLength(HuffmanTree T, int& total, int length)
{
if (!T) return;
if (!T->left && !T->right) //叶子节点
total += length * T->weight;
getLength(T->left, total, length + );
getLength(T->right, total, length + );
} bool valid(int N, int total)
{
string c, s;
bool isValid = true;
int i, sum = ;
HuffmanTree T = initHuffmanNode();
for (i = ; i < N; i++)
{
cin >> c >> s;
sum += s.size() * mapp[c];
if (!isValid) continue;
if (s[] == '')
T->left = insertHuffman(T->left, s, , isValid);
else
T->right = insertHuffman(T->right, s, , isValid);
}
if (!isValid || sum != total) return false;
else return true;
} HuffmanTree insertHuffman(HuffmanTree T, string s, int n, bool& judge)
{
if (!T)
T = initHuffmanNode();
else
{ if (n + == s.size()) judge = false;//当前节点非空且为字符串最后一个字符
else if (!T->left && !T->right)//当前节点为叶子节点且字符串还未结束
judge = false;
}
if (n + < s.size())
{
if (s[n + ] == '')
T->left = insertHuffman(T->left, s, n + , judge);
else
T->right = insertHuffman(T->right, s, n + , judge);
}
return T;
}

pta 编程题14 Huffman Codes的更多相关文章

  1. pta 编程题20 旅游规划

    其它pta数据结构编程题请参见:pta 题目 这个最短路径问题只需要求两点之间的最短路径,因而在Dijikstra算法中当求出目标点的最短路径之后跳出循环即可. #include <iostre ...

  2. pta 编程题21 公路村村通

    其它pta数据结构编程题请参见:pta 题目 这道题考察最小生成树问题,用的是Prim算法. 和Dijkstra算法相比,没有了collect数组,因为dist[v] == 0就代表v被已收录. #i ...

  3. pta编程题19 Saving James Bond 2

    其它pta数据结构编程题请参见:pta 题目 和简单版本不同的是,简单版本只需判断能否到达岸边,而这个版本要求求出最少跳数的路径. 简单版本用dfs实现,而这道题用BFS实现. 注意: 岛半径为7.5 ...

  4. pta 编程题16 Saving James Bond - Easy Version

    其它pta数据结构编程题请参见:pta 题目 主要用到了深度优先搜索. #include <iostream> using namespace std; struct Vertex { i ...

  5. pta 编程题15 列出连通集

    其它pta数据结构编程题请参见:pta 题目 题目要求分别以深度优先搜索和广度优先搜索输出图的连通集. 广度优先搜索要用到队列,先回顾一下循环队列: struct QNode { int* Data; ...

  6. pta 编程题13 File Transfer

    其它pta数据结构编程题请参见:pta 这道题考察的是union-find并查集. 开始把数组中每个元素初始化为-1,代表没有父节点.为了使树更加平衡,可以让每一个连通分量的树根的负值代表这个连通分量 ...

  7. pta 编程题12 堆中的路径

    其它pta数据结构编程题请参见:pta 这道题考察的是最小堆. 堆是一个完全二叉树,因此可用数组表示,一个下标为 i 的结点的父节点下标为 i / 2,子结点下标为 2i 和 2i + 1. 插入元素 ...

  8. pta 编程题10 Root of AVL Tree

    其它pta数据结构编程题请参见:pta 这道题考察平衡二叉查找树的插入. 为了保证二叉查找树的平衡,当一个结点的左右子树的高度差大于1时就要进行调整. 分为以下四种情况: 插入新节点后,以及旋转之后, ...

  9. pta 编程题8 Tree Traversals Again

    其它pta数据结构编程题请参见:pta 这次的作业考察的是树的遍历. 题目的输入通过栈的pop给出了树的中序遍历的顺序.根据push和pop的顺序构造树的方法为:定义一个变量father来确定父节点, ...

随机推荐

  1. 【mybatis 的foreach的用法】

    foreach一共有三种类型,分别为List,[](array),Map三种. foreach属性 属性 描述 item 循环体中的具体对象.支持属性的点路径访问,如item.age,item.inf ...

  2. 事务隔离实现并发控制:MySQL系列之十

    一.并发访问控制 实现的并发访问的控制技术是基于锁: 锁分为表级锁和行级锁,MyISAM存储引擎不支持行级锁:InnoDB支持表级锁和行级锁: 锁的分类有读锁和写锁,读锁也被称为共享锁,加读锁的时候其 ...

  3. [USACO1.4]等差数列 Arithmetic Progressions

    题目描述 一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列. 在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双 ...

  4. HTTP header parsing errors will be logged at DEBUG level

    -- ::-exec-] INFO org.apache.coyote.http11.Http11Processor - Error parsing HTTP request header Note: ...

  5. js千分位处理

    一.去掉千分位 function removeThousands(num) { var x = num.split(','); return parseFloat(x.join("" ...

  6. Spark (Python版) 零基础学习笔记(二)—— Spark Transformations总结及举例

    1. map(func) 将func函数作用到数据集的每个元素,生成一个新的分布式的数据集并返回 >>> a = sc.parallelize(('a', 'b', 'c')) &g ...

  7. beeline连接hive

    beeline -u jdbc:hive2://192.168.1.77:10000 zeppelin default jdbc: jdbc:hive2://nn01.ooccpp.com:2181/ ...

  8. 09.Spring Bean 注册 - BeanDefinitionRegistry

    基本概念 BeanDefinitionRegistry ,该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程. 它的接口定义如下: public interface ...

  9. 在HEXO主题中添加数学公式支持

    在markdown中书写数学符号的方式参考Latex常用数学符号 Mathjax 安装 npm uninstall hexo-renderer-marked --save npm install he ...

  10. CentOS 7: ping Name or service not known

    解决方法 cd到/etc/sysconfig/network-scripts/ 修改ifcfg-*(*代表的内容可通过ifconfig查看)中的ONBOOT=yes reboot ifcfg-ens3 ...