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来确定父节点, ...
随机推荐
- 常见的web漏洞及其防范
原文地址:http://blog.csdn.net/u013777676/article/details/52124298 一.SQL注入漏洞 SQL注入攻击(SQL Injection),简称注入攻 ...
- Redis学习笔记(一):基础数据结构
一. 引言 <Redis设计与实现>一书主要分为四个部分,其中第一个部分主要讲的是Redis的底层数据结构与对象的相关知识. Redis是一种基于C语言编写的非关系型数据库,它的五种基本对 ...
- c#中ToString("yyyyMMdd") 与ToString("yyyymmdd")区别
string a= DateTime.Now.ToString("yyyyMMdd") ; string b=DateTime.Now.ToString("yyyymmd ...
- luogu3224 永无乡(动态开点,权值线段树合并)
luogu3224 永无乡(动态开点,权值线段树合并) 永无乡包含 n 座岛,编号从 1 到 n ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 n 座岛排名,名次用 1 到 n 来表示.某些 ...
- 2017-10-23 NOIP模拟赛
叉叉 题目描述 现在有一个字符串,每个字母出现的次数均为偶数.接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现的和六次出现的字母a连一条线.. ...
- xml 的使用和解析 及解析工具
xml 一.xml简介 1. 什么是xml XML:Extensiable Markup Language,可扩展标记语言.和HTML有语法相似之处,也有作用上的不同: 和html相似: 都是由一堆标 ...
- IDEA开发Spark的漫漫摸索(二)
1 新建Maven项目 特别提醒,Maven项目中有GropId和ArtifactId.GroupId是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构.一般Gru ...
- [SCOI2010]连续攻击游戏 BZOJ1854 二分图匹配
题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...
- 【补档】Pycharm的一些配置
新建和创建文件就不必说了吧~ 运行这里原本是灰色的,我们点旁边的三角形 点绿色+号,python Name:随便写 Script:选择一个py文件~,然后OK,就可以运行了
- 【Linux】Linux查看程序端口占用情况
使用命令查询8880端口的占用信息: netstat -naop|grep 查询结果: 发现8880端口被PID为4518的进程占用 使用命令查询所有的进程和端口使用情况: netstat –apn ...