其它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. 第一个Python工程

    创建你的第一个Python程序 如果你曾经很熟悉visual studio的工作方式.可能对python不习惯. 工程通常只与你使用的IDLE有关系.这些工具习惯将文档,编译,测试集成一体.所以就存在 ...

  2. jquery对象访问

    jquery对象访问 方法名 说明 语法 (callback 执行的函数,object指定元素的对象.) each() 用于以当前jQuery对象匹配到的每个元素作为上下文来遍历执行指定的函数 jQu ...

  3. Haproxy+Keepalived高可用配置

    基本实验 参考文档 博文地址 环境拓扑 下面使我们要实现的负载均衡集群图示 主节点地址: 92.0.0.11 从节点地址: 92.0.0.12 共享虚拟地址:92.0.0.8 下面是负载均衡集群可能出 ...

  4. 采用DCT进行图像压缩

    一.实验目的:熟悉变换编码的图像压缩方法 二.实验内容:以所给图像为例,采用dct进行图像压缩编码,通过改变模板矩阵中非零元素的个数,得到不同缩编码图像, 根据公式 ,编写程序计算原图像和dct变换后 ...

  5. 萌新在线模板--keyboarder_zsq

    好像马上就要出去打铁了QAQ,所以是不是要做个模板带过去也玩一玩? 那就做吧... 标题就设为萌新模板吧...各种萌新讲解对吧.... 图论 拓扑排序 最短路 最小生成树 二分匹配 强连通Tarjan ...

  6. 799C(xjb)

    题目链接: http://codeforces.com/problemset/problem/799/C 题意: 有c, d两种货币, 有 n 个货物, 可以用 c 货币或者 d 货币购买, 现在需要 ...

  7. C#网络编程学习(5)---Tcp连接中出现的粘包、拆包问题

    本文参考于CSDN博客wxy941011 1.疑问 我们使用第四个博客中的项目. 修改客户端为:连接成功后循环向服务器发送从1-100的数字.看看服务器会不会正常的接收100次数据. 可是我们发现服务 ...

  8. Go入门基础手记

    1. 配置环境变量(临时) export GOPATH=yourpath 2. 跨平台交叉编译 env GOOS=linux GOARCH=amd64 go build 3. test写法 // 首先 ...

  9. codeforces round 474 pathwalks

    题目传送门http://codeforces.com/contest/960/problem/F 4月25号期中考,答应过年级组长要考年排前3的,所以25号以前我就不搞竞赛了,期中考要考好. 有很多大 ...

  10. mysql中 if语句的使用

    Mysql的if既可以作为表达式用,也可在存储过程中作为流程控制语句使用,如下是做为表达式使用: IF(expr1,expr2,expr3) IF表达式 代码如下: 如果 expr1 是TRUE (e ...