DS|哈夫曼编码及应用

题目一:DS树 -- 赫夫曼树的构建与编码

题目描述:

给定n个权值,根据这些权值构造huffman树,并进行huffman编码

注意数组访问是从位置1开始

要求:赫夫曼的构建中,默认左孩子权值不大于右孩子权值

输入要求:

第一行先输入n,表示有n个权值,即有n个叶子

第二行输入n个权值,权值全是小于1万的正整数

输出要求:

逐行输出每个权值对应的编码,格式如下:权值-编码
即每行先输出1个权值,再输出一个短划线,再输出对应编码

接着下一行输出下一个权值和编码,以此类推

输入样例:

5
15 4 4 3 2

输出样例:

15-1
4-010
4-011
3-001
2-000

代码示例:

#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;#define MAXCODELEN	15
#define MAXHUFFMANCODENO 10
#define MAXCODESTRINGLEN 100typedef struct {int weight;int parent, lChild, rChild;char code[MAXCODELEN];
} HTNode, * HumffanTree;HTNode HT[2 * MAXHUFFMANCODENO];void Select(int pos, int* s1, int* s2) {int w1, w2, i;w1 = w2 = 100010;*s1 = *s2 = 0;for (i = 1; i <= pos; i++) {if (HT[i].weight < w1 && HT[i].parent == 0) {w2 = w1;*s2 = *s1;w1 = HT[i].weight;*s1 = i;}else if (HT[i].weight < w2 && HT[i].parent == 0) {w2 = HT[i].weight;*s2 = i;}}
}void CreateHuffmanTree(int n, int* w) {int m, s1, s2;m = 2 * n - 1;//为Huffman树的叶子结点赋值for (int i = 1; i <= n; i++) {HT[i].weight = w[i - 1];HT[i].parent = 0;HT[i].lChild = HT[i].rChild = 0;}//为Huffman的内部节点赋值for (int i = n + 1; i <= m; i++) {HT[i].weight = 0;HT[i].parent = HT[i].lChild = HT[i].rChild = 0;}for (int i = n + 1; i <= m; i++) {Select(i - 1, &s1, &s2);HT[s1].parent = i; HT[s2].parent = i;HT[i].lChild = s1; HT[i].rChild = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}void HuffmanCoding(int n){int j, m, c, f, start;// 存放每个字符的编码序列char cd[MAXCODELEN];m = MAXCODELEN;// 编码结束符cd[m - 1] = 0;for (int i = 1; i <= n; i++) {// 编码结束符位置start = m - 1;//从叶子到根逆向求每个字符的编码for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) {if (HT[f].lChild == c) cd[--start] = '0';else cd[--start] = '1';}//将每个字符的Huffman编码存放起来for (j = 0; j < m - start; j++) HT[i].code[j] = cd[start + j];HT[i].code[j] = 0;}
}int main() {int n;cin >> n;int* array = new int[n];for (int i = 0; i < n; i++) cin >> array[i];CreateHuffmanTree(n, array);HuffmanCoding(n);for (int i = 1; i <= n; i++) {cout << HT[i].weight << "-" << HT[i].code << endl;}return 0;
}

题目二:DS树 -- 赫夫曼树解码

题目描述:

已知赫夫曼编码算法和程序,在此基础上进行赫夫曼解码

可以增加一个函数:int  Decode(const string codestr, char txtstr[]);//输入编码串codestr,输出解码串txtstr

该方法如果解码成功则返回1,解码失败则返回-1,本程序增加宏定义ok表示1,error表示-1

赫夫曼解码算法如下:

定义指针p指向赫夫曼树结点,指针i指向编码串,定义ch逐个读取编码串的字符

初始操作包括读入编码串str,设置p指向根结点,i为0表示指向串首,执行以下循环:

1)取编码串的第i个字符放入ch

2)如果ch是字符0,则p跳转到左孩子;如果ch是字符1,则p跳转到右孩子;如果ch非0非1,表示编码串有错误,报错退出

3)如果p指的结点是叶子,输出解码字符,p跳回根结点,i++,跳步骤1

4)如果p指的结点不是叶子且i未到编码串末尾,i++,跳步骤1

5)如果p指的结点不是叶子且i到达编码串末尾,报错退出

当i到达编码串末尾,解码结束。

输入要求:

第一行先输入n,表示有n个叶子

第二行输入n个权值,权值全是小于1万的正整数
第三行输入n个字母,表示与权值对应的字符
第四行输入k,表示要输入k个编码串
第五行起输入k个编码串

输出要求:

每行输出解码后的字符串,如果解码失败直接输出字符串“error”,不要输出部分解码结果

输入样例:

5
15 4 4 3 2
A B C D E
3
11111
10100001001
00000101100

输出样例:

AAAAA
ABEAD
error

代码示例:

#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;#define MAXCODELEN	15
#define MAXHUFFMANCODENO 10
#define MAXCODESTRINGLEN 100typedef struct {char ch;int weight;int parent, lChild, rChild;char code[MAXCODELEN];
} HTNode, * HumffanTree;HTNode HT[2 * MAXHUFFMANCODENO];void Select(int pos, int* s1, int* s2) {int w1, w2, i;w1 = w2 = 100010;*s1 = *s2 = 0;for (i = 1; i <= pos; i++){if (HT[i].weight < w1 && HT[i].parent == 0){w2 = w1;*s2 = *s1;w1 = HT[i].weight;*s1 = i;}else if (HT[i].weight < w2 && HT[i].parent == 0){w2 = HT[i].weight;*s2 = i;}}
}void CreateHuffmanTree(int n, char* c, int* w) {int m, s1, s2;m = 2 * n - 1;//为Huffman树的叶子结点赋值for (int i = 1; i <= n; i++) {HT[i].ch = c[i - 1];HT[i].weight = w[i - 1];HT[i].parent = 0;HT[i].lChild = HT[i].rChild = 0;}//为Huffman的内部节点赋值for (int i = n + 1; i <= m; i++) {HT[i].weight = 0;HT[i].parent = HT[i].lChild = HT[i].rChild = 0;}for (int i = n + 1; i <= m; i++) {Select(i - 1, &s1, &s2);HT[s1].parent = i; HT[s2].parent = i;HT[i].lChild = s1; HT[i].rChild = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}void HuffmanCoding(int n)
{int j, m, c, f, start;// 存放每个字符的编码序列char cd[MAXCODELEN];m = MAXCODELEN;// 编码结束符cd[m - 1] = 0;for (int i = 1; i <= n; i++) {// 编码结束符位置start = m - 1;//从叶子到根逆向求每个字符的编码for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) {if (HT[f].lChild == c) cd[--start] = '0';else cd[--start] = '1';}//将每个字符的Huffman编码存放起来for (j = 0; j < m - start; j++) HT[i].code[j] = cd[start + j];HT[i].code[j] = 0;}
}int ShowHuffmanDecode(int n, string str, string& st)
{int c, Root;Root = 2 * n - 1;c = Root;for (int i = 0; i < str.size(); i++) {if (str[i] == '0')c = HT[c].lChild;elsec = HT[c].rChild;if ((HT[c].lChild == 0) && (HT[c].rChild == 0)) {st += HT[c].ch;c = Root;}}if (HT[c].parent != 0) return 0;else return 1;
}int main() {int n;cin >> n;char* arr = new char[n];int* array = new int[n];for (int i = 0; i < n; i++) cin >> array[i];for (int i = 0; i < n; i++) cin >> arr[i];CreateHuffmanTree(n, arr, array);HuffmanCoding(n);int t;cin >> t;while (t--) {string s, st = "";cin >> s;if (!ShowHuffmanDecode(n, s, st)) cout << "error" << endl;else cout << st << endl;}return 0;
}

题目三:DS树 -- 带权路径和

题目描述:

二叉树的创建使用含空树表示的先序遍历序列,计算一棵二叉树的带权路径总和,即求赫夫曼树的带权路径和。

已知一棵二叉树的叶子权值,该二叉树的带权路径和WPL等于叶子权值乘于根节点到叶子的分支数,然后求总和。

如下图中,叶子都用大写字母表示,权值对应为:A-7,B-6,C-2,D-3

树的带权路径和 = 7*1 + 6*2 + 2*3 + 3*3 = 34

输入要求:

第一行输入一个整数t,表示有t个二叉树

第二行输入一棵二叉树的先序遍历结果,空树用字符‘0’表示,注意输入全是英文字母和0,其中大写字母表示叶子

第三行先输入n表示有n个叶子,接着输入n个数据表示n个叶子的权值,权值的顺序和前面输入的大写字母顺序对应

以此类推输入下一棵二叉树

输出要求:

输出每一棵二叉树的带权路径和

输入样例:

2
xA00tB00zC00D00
4 7 6 2 3
ab0C00D00
2 10 20

输出样例:

34
40

代码示例:

#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;struct BNode {char data;BNode* lChild;BNode* rChild;
};class BTree {
public:BNode* root;BTree() :root(NULL) {}BNode* creatBTree() {BNode* tmp;char ch;cin >> ch;if (ch == '0') tmp = NULL;else {tmp = new BNode;tmp->data = ch;tmp->lChild = creatBTree();tmp->rChild = creatBTree();}return tmp;}void CountWeight(BNode* cur, int level, int& sum) {int weight;if (cur != NULL) {if (cur->data >= 'A' && cur->data <= 'Z') {cin >> weight;sum += weight * level;}else{level++;CountWeight(cur->lChild, level, sum), CountWeight(cur->rChild, level, sum);}}}
};int main() {int t;cin >> t;while (t--) {int count = 0;BTree tree;tree.root = tree.creatBTree();int n;cin >> n;int sum = 0;tree.CountWeight(tree.root, 0, sum);cout << sum << endl;}return 0;
}

题目四:DS树 -- 二叉树之最大路径

题目描述:

给定一颗二叉树的逻辑结构(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构

二叉树的每个结点都有一个权值,从根结点到每个叶子结点将形成一条路径,每条路径的权值等于路径上所有结点的权值和。编程求出二叉树的最大路径权值。如下图所示,共有4个叶子即有4条路径,

路径1权值=5 + 4 + 11 + 7 = 27        路径2权值=5 + 4 + 11 + 2 = 22

路径3权值=5 + 8 + 13 = 26              路径4权值=5 + 8 + 4 + 1 = 18

可计算出最大路径权值是27。

该树输入的先序遍历结果为ABCD00E000FG00H0I00,各结点权值为:

A-5,B-4,C-11,D-7,E-2,F-8,G-13,H-4,I-1

输入要求:

第一行输入一个整数t,表示有t个测试数据

第二行输入一棵二叉树的先序遍历,每个结点用字母表示

第三行先输入n表示二叉树的结点数量,然后输入每个结点的权值,权值顺序与前面结点输入顺序对应

以此类推输入下一棵二叉树

输出要求:

每行输出每棵二叉树的最大路径权值,如果最大路径权值有重复,只输出1个

输入样例:

2
AB0C00D00
4 5 3 2 6
ABCD00E000FG00H0I00
9 5 4 11 7 2 8 13 4 1

输出样例:

11
27

代码示例:

#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;struct BNode {char data;int weight;BNode* lChild;BNode* rChild;
};class BTree {
public:BNode* root;BTree() :root(NULL) {}BNode* creatBTree() {BNode* tmp;char ch;cin >> ch;if (ch == '0') tmp = NULL;else {tmp = new BNode;tmp->data = ch;tmp->lChild = creatBTree();tmp->rChild = creatBTree();}return tmp;}void Preorder(BNode* cur) {int weight;if (cur != NULL) {cin >> weight;cur->weight = weight;Preorder(cur->lChild), Preorder(cur->rChild);}}void addWeight(BNode* cur, int curWeight, int& maxWeight) {if (cur != NULL) {curWeight += cur->weight;if (cur->lChild == NULL && cur->rChild == NULL) maxWeight = max(maxWeight, curWeight);addWeight(cur->lChild, curWeight, maxWeight), addWeight(cur->rChild, curWeight, maxWeight);}}
};int main() {int t;cin >> t;while (t--) {int count = 0;BTree tree;tree.root = tree.creatBTree();int n;cin >> n;int maxWeight = 0;tree.Preorder(tree.root);tree.addWeight(tree.root, 0, maxWeight);cout << maxWeight << endl;}return 0;
}

题目五:DS树 -- 二叉树镜面反转

题目描述:

假设二叉树用二叉链表存储,用含空子树遍历的先序序列结果创建。空子树用字符#表示

输入二叉树的先序序列,请你先创建二叉树,并对树做个镜面反转,再输出反转后的二叉树的先序遍历、中序遍历、后序遍历和层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。

输入要求:

测试次数t

每组测试数据是一个二叉树的先序遍历序列,#表示空树

输出要求:

对每棵二叉树,输出镜面反转后的先序、中序、后序和层次遍历序列。如果空树,输出四个NULL(后面不加空格,每个NULL独自一行,中间没有空行)。如下:

NULL

NULL

NULL

NULL

输入样例:

3
41#32###65##7##
AB#C##D##
AB##C##

输出样例:

4 6 7 5 1 3 2 
7 6 5 4 3 2 1 
7 5 6 2 3 1 4 
4 6 1 7 5 3 2 
A D B C 
D A C B 
D C B A 
A D B C 
A C B 
C A B 
C B A 
A C B 

代码示例:

#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;struct BNode {char data;BNode* lChild;BNode* rChild;
};class BTree {
public:BNode* root;BTree() :root(NULL) {}BNode* creatBTree() {BNode* tmp;char ch;cin >> ch;if (ch == '#') tmp = NULL;else {tmp = new BNode;tmp->data = ch;tmp->lChild = creatBTree();tmp->rChild = creatBTree();}return tmp;}void Preorder(BNode* cur) {if (cur != NULL) {cout << cur->data << " ";Preorder(cur->lChild), Preorder(cur->rChild);}}void Inorder(BNode* cur) {if (cur != NULL) {Inorder(cur->lChild);cout << cur->data << " ";Inorder(cur->rChild);}}void Postorder(BNode* cur) {if (cur != NULL) {Postorder(cur->lChild), Postorder(cur->rChild);cout << cur->data << " ";}}void levelDFSTree(BNode* cur) {queue<BNode*> Q;BNode* p = cur;if (p) Q.push(p);while (!Q.empty()) {p = Q.front();Q.pop();if (p) {cout << p->data << " ";Q.push(p->lChild), Q.push(p->rChild);}}}void Reverse(BNode* cur) {if (cur != NULL) {swap(cur->lChild, cur->rChild);Reverse(cur->lChild), Reverse(cur->rChild);}}
};int main() {int t;cin >> t;while (t--) {BTree tree;tree.root = tree.creatBTree();if (tree.root == NULL) {cout << "NULL" << endl << "NULL" << endl << "NULL" << endl << "NULL" << endl;}else{tree.Reverse(tree.root);tree.Preorder(tree.root);cout << endl;tree.Inorder(tree.root);cout << endl;tree.Postorder(tree.root);cout << endl;tree.levelDFSTree(tree.root);cout << endl;}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/600633.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

淘宝商品详情API接口(item_get-获得淘宝商品详情)主图,属性,sku,价格,搜索商品列表

淘宝开放平台提供了API接口&#xff0c;允许开发者获取淘宝商品的相关信息。为了获取商品详情&#xff0c;您可以使用 item_get API接口。以下是如何使用此API接口来获取商品的主图、属性、SKU、价格以及搜索商品列表的简要说明&#xff1a; 公共参数 名称类型必须描述keyStr…

PromptCast:基于提示学习的时序预测模型!

目前时序预测的SOTA模型大多基于Transformer架构&#xff0c;以数值序列为输入&#xff0c;如下图的上半部分所示&#xff0c;通过多重编码融合历史数据信息&#xff0c;预测未来一定窗口内的序列数值。 受到大语言模型提示工程技术的启发&#xff0c;文章提出了一种时序预测新…

Redis小计(3)

目录 redis为什么是单线程模型和为什么不推荐使用"keys *"指令 redis为什么是单线程模型和为什么不推荐使用"keys *"指令 单线程模型可以避免线程安全问题&#xff0c;即并发访问导致的数据冲突。当大量客户端发来请求时&#xff0c;redis服务器只能一个一…

排序之冒泡排序

冒泡排序是一种简单的排序算法&#xff0c;它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是说该数列已经排序完成。 思路&#xff1a; 左边大于右边交…

Mobileperf:优化移动应用性能的关键工具

引言&#xff1a; 随着移动设备的普及和功能的不断增强&#xff0c;移动应用在人们的日常生活中扮演着越来越重要的角色。然而&#xff0c;由于移动设备资源有限&#xff0c;如处理器、内存和电池等&#xff0c;移动应用的性能问题也日益突出。为了提高用户体验和满足用户需求&…

单机部署Rancher

上次已经安装完毕了k8s了&#xff0c;但是想要界面化的管理&#xff0c;离不开界面工具&#xff0c;首推就是rancher&#xff0c;本文介绍安装rancher的安装&#xff0c;也可以将之前安装的k8s管理起来。 已经安装完毕docker和docker-ce的可以直接从第三部分开始。 一、基础准…

【数据库原理】(10)数据定义功能

SQL 数据定义功能包括定义模式、定义表、定义索引和定义视图,其语句如表所示。 一.创建、删除模式 1.创建模式 (Create Schema) 用途&#xff1a;创建模式是为了在数据库中定义一个新的命名空间&#xff0c;它可以包含多个数据库对象。 语法&#xff1a; CREATE SCHEMA &…

json.stringify()详解

json.stringify()详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;让我们一同深入探讨在JavaScript中常用的JSON处理方法——JSON.stringify()&…

数据库期末重点

第一章&#xff1a; 1.数据库发展的三个阶段 第一代数据库系统、第二代数据库系统、新一代数据库系统 2.数据库系统发展的三个里程碑 IMS系统、DBTG报告、关系数据库系统 3.数据管理技术三个阶段 人工管理阶段(40年代中-50年代中) 文件系统阶段(50年代末-60年代中) 数据…

选择排序!!!基础排序详解 C语言版

目录 1.什么是选择排序 2.选择排序源代码 3.优化代码 1.什么是选择排序 这是一个选择排序的流程图&#xff0c;其实很简单&#xff0c;就是每次挑选数字中最小的作为第一个 &#xff0c;直到整个数据有序就结束了 顾名思义&#xff0c;选择&#xff0c;那就是选取&#xff0c…

打造私域流量的知识付费小程序saas租户平台

当今信息爆炸的时代&#xff0c;知识管理已经成为了每个人必须面对的问题。然而&#xff0c;市面上的知识付费平台大多数都是通用的&#xff0c;无法满足个性化需求。 因此&#xff0c;明理信息科技提供了一款专属定制的适合个人的知识付费平台。核心产品能力如下&#xff1a;…

Visual Studio Code可以做到这一点:提示和技巧:Build 2018

Visual Studio Code火了。每个人都喜欢这个意想不到的文本编辑器&#xff0c;而且理由很充分&#xff1a;它可以做很多事情。它可以动态编译JavaScript模板&#xff0c;内联执行JavaScript&#xff0c;管理Mongo DB实例等等&#xff01;在这个部分&#xff0c;我们将看到Visual…

数据结构OJ实验15-插入排序与交换排序

A. DS内排—直插排序 题目描述 给定一组数据&#xff0c;使用直插排序完成数据的升序排序。 --程序要求-- 若使用C只能include一个头文件iostream&#xff1b;若使用C语言只能include一个头文件stdio 程序中若include多过一个头文件&#xff0c;不看代码&#xff0c;作0分…

ubuntu 安装 anaconda

ubuntu 安装 anaconda 下载 wget https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh安装 bash Anaconda3-2023.09-0-Linux-x86_64.sh2.1 回车继续 2.2 许可协议 输入 q 退出阅读许可协议 2.3 输入 yes 接受 许可协议 2.4 设置 anaconda 安装位置 如不需…

聚观早报 |谷歌起草“机器人宪法”;极越与福耀集团达成合作

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 1月6日消息 谷歌起草“机器人宪法” 极越与福耀集团达成合作 三星电子宣布与现代汽车集团合作 OpenAI下周将推GP…

18款Visual Studio实用插件(更新)

前言 俗话说的好工欲善其事必先利其器&#xff0c;安装一些Visual Studio实用插件对自己日常的开发和工作效率能够大大的提升&#xff0c;避免996从选一款好的IDE实用插件开始。以下是我认为比较实用的Visual Studio插件希望对大家有用&#xff0c;大家有更好的插件推荐可在文…

TSINGSEE青犀智能分析网关V4在智慧园区车辆违停检测场景中的应用

一、背景与需求 园区作为企业办公、生产制造的重要场所&#xff0c;主要道路车辆违停等违规行为会对园区的安全造成隐患&#xff0c;并且在上下班高峰期内&#xff0c;由于发现不及时&#xff0c;车辆违停行为会造成出入口拥堵现象&#xff0c;这也成为园区管理的棘手问题。为了…

“编程界的隐形斗篷:C语言作用域与生命周期的喜怒哀乐”

少年们&#xff0c;大家好。我是博主那一脸阳光。 前言&#xff1a;理解C语言作用域与生命周期&#xff0c;犹如掌握了变量在程序中的“活动地带”与“存活时刻”&#xff0c;有助于避免数据冲突、优化内存使用、提升代码质量和模块化程度&#xff0c;增强程序稳定性和安全性…

php-ffmpeg运用 合并视频,转码视频

下载 官网 windows 版本 添加环境变量 合并视频 public function test_that_true_is_true(): void{ini_set(memory_limit,-1); //没有内存限制set_time_limit(0);//不限制执行时间//ffmpeg配置$path [ffmpeg.binaries > D:\soft\ffmpeg\bin/ffmpeg.exe,ffprobe.binaries…

AlarmManager使用详解

AlarmManager使用详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;让我们一起深入探讨在Android开发中常用的时间调度工具——AlarmManager的使…