pta 编程题14 Huffman Codes
其它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的更多相关文章
- pta 编程题20 旅游规划
其它pta数据结构编程题请参见:pta 题目 这个最短路径问题只需要求两点之间的最短路径,因而在Dijikstra算法中当求出目标点的最短路径之后跳出循环即可. #include <iostre ...
- pta 编程题21 公路村村通
其它pta数据结构编程题请参见:pta 题目 这道题考察最小生成树问题,用的是Prim算法. 和Dijkstra算法相比,没有了collect数组,因为dist[v] == 0就代表v被已收录. #i ...
- pta编程题19 Saving James Bond 2
其它pta数据结构编程题请参见:pta 题目 和简单版本不同的是,简单版本只需判断能否到达岸边,而这个版本要求求出最少跳数的路径. 简单版本用dfs实现,而这道题用BFS实现. 注意: 岛半径为7.5 ...
- pta 编程题16 Saving James Bond - Easy Version
其它pta数据结构编程题请参见:pta 题目 主要用到了深度优先搜索. #include <iostream> using namespace std; struct Vertex { i ...
- pta 编程题15 列出连通集
其它pta数据结构编程题请参见:pta 题目 题目要求分别以深度优先搜索和广度优先搜索输出图的连通集. 广度优先搜索要用到队列,先回顾一下循环队列: struct QNode { int* Data; ...
- pta 编程题13 File Transfer
其它pta数据结构编程题请参见:pta 这道题考察的是union-find并查集. 开始把数组中每个元素初始化为-1,代表没有父节点.为了使树更加平衡,可以让每一个连通分量的树根的负值代表这个连通分量 ...
- pta 编程题12 堆中的路径
其它pta数据结构编程题请参见:pta 这道题考察的是最小堆. 堆是一个完全二叉树,因此可用数组表示,一个下标为 i 的结点的父节点下标为 i / 2,子结点下标为 2i 和 2i + 1. 插入元素 ...
- pta 编程题10 Root of AVL Tree
其它pta数据结构编程题请参见:pta 这道题考察平衡二叉查找树的插入. 为了保证二叉查找树的平衡,当一个结点的左右子树的高度差大于1时就要进行调整. 分为以下四种情况: 插入新节点后,以及旋转之后, ...
- pta 编程题8 Tree Traversals Again
其它pta数据结构编程题请参见:pta 这次的作业考察的是树的遍历. 题目的输入通过栈的pop给出了树的中序遍历的顺序.根据push和pop的顺序构造树的方法为:定义一个变量father来确定父节点, ...
随机推荐
- 【关于msyql5.6创建存储过程的一些记录】
-- 秒杀执行存储过程DELETE $$ -- console的结束符号由;转换成 $$-- in输入参数:out:输出参数-- ROW_COUNT():返回上条dml影响的条数: 小于0:sql语句 ...
- C#面向对象三大特性之二:继承
面向对象的三大特性之一的封装,解决了将对同一对象所能操作的所有信息放在一起,实现统一对外调用,实现了同一对象的复用,降低了耦合. 但在实际应用中,有好多对象具有相同或者相似的属性,比如有一个对象 果树 ...
- Linux中常用压缩命令
.zip格式压缩 zip 压缩文件名 源文件 压缩文件 zip -r 压缩文件名 源目录 压缩目录 .zip格式解压缩 unzip 压缩文件 解压.zip文件 .gz格式压缩 gzip 源文件 压缩为 ...
- 洛谷P3116 [USACO15JAN]约会时间Meeting Time
P3116 [USACO15JAN]约会时间Meeting Time 题目描述 Bessie and her sister Elsie want to travel from the barn to ...
- JavaWeb:Cookie处理和Session跟踪
JavaWeb:Cookie处理和Session跟踪 Cookie处理 什么是Cookie Cookie 是存储在客户端计算机上的文本文件,保留了各种跟踪信息.因为HTTP协议是无状态的,即服务器不知 ...
- Stream流、方法引用
Stream流.方法引用 Stream流.方法引用 Stream流.方法引用 Stream流.方法引用 Stream流.方法引用 ... ...
- HDU2050 折线分割平面
题目:acm.hdu.edu.cn/showproblem.php?pid=2050 递推: 从直线入手,第n条直线,最多和平面上的直线有n-1个交点,多出(n-1)+1个部分 序号 1 2 3 .. ...
- 洛谷P3195||bzoj1010 [HNOI2008]玩具装箱TOY
洛谷P3195 bzoj1010 设s数组为C的前缀和 首先$ans_i=min_{j<i}\{ans_j+(i-j-1+s_i-s_j-L)^2\}$ (斜率优化dp)参考(复读)https: ...
- 在SpringBoot中使用Docker(利用dockerfile-maven-plugin插件)
周末在家做了一个实验: 将Docker通过插件的方式集成到SpringBoot中 然后通过Maven命令根据项目中的Dockerfile自动生成Docker镜像,同时将镜像推送到远程Linux服务器( ...
- 非递归遍历二叉树Java版的实现代码(没写层次遍历)
直接上代码呵呵,里面有注解 package www.com.leetcode.specificProblem; import java.util.ArrayList; import java.util ...