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来确定父节点, ...
随机推荐
- 【创建maven-web项目-eclipse-jee-mars-2-win32-x86_64-jdk1.8】
需要注意的是:创建的mavenweb项目是没有java源文件夹的需要手动添加: 创建项目完成以后,项目会报错,如下: 因为项目中没有添加servlet依赖解决jsp报错问题:添加依赖: <dep ...
- JsonParse类
using System.Data; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; using Syst ...
- Exception异常处理
1.java异常类: 都是Throwable的子类: 1.Exception(异常) :是程序本身可以处理的异常. 2.Error(错误): 是程序无法处理的错误.这些错误表示故障发生于虚拟机自身.或 ...
- python字符串和日期相互转换
- 倍增lca-ZJOI2012 灾难
一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边.这个图没有环.图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存: 而有连出边的点代表的都是 ...
- sys_guid()
create extension "uuid-ossp"; create or replace function sys_guid() returns uuid as $$sele ...
- 黑马SSM项目练习中的Oracle操作
- Java基础笔记(七)—— 成员变量、静态变量、局部变量
public class Test { int c; //成员变量(实例变量) static int s1; //静态变量(类变量)(全局变量) public static void main(Str ...
- springboot 简单自定义starter - dubbo
首先需要引入pom 这里使用nacos注册中心 所以引入了nacos-client 使用zookeeper注册中心的话需要引入其相应的client <dependency> <gro ...
- SaltStack自动化安装配置haproxy
准备环境node1:192.168.217.149 (saltstack master)node2:192.168.217.150(saltstack minion)下载haproxy1.6.2.ta ...