关于哈夫曼树与编码,带权路径长度
哈夫曼树
- 哈夫曼树与哈夫曼编码的定义
- 建立哈夫曼树
- 哈夫曼树编码
- 通过译码求输入的序列
- 具体题目与完整代码:
- 建哈夫曼树,求哈夫曼编码,求解译码
- 带权路径长度
哈夫曼树与哈夫曼编码的定义
typedef char** HuffmanCode;
typedef struct
{int weight;int parent;int LChild;int RChild;
}HTNode, HuffmanTree[10001];
建立哈夫曼树
建树前需要对树进行初始化,若有n个元素,则哈夫曼树一共会有2 * n - 1个元素,对1~n个位置置入对应的权值,剩下的全部置为0;同时还需要编写一个选择函数,选出当前情况下最小的两个数,总体思路是从下往上建树。
void select(HuffmanTree ht, int n, int &s1, int &s2)
{int min, _min;//min是最小值,_min是第二小的值,分别赋给左,右子树for (int i = 1; i <= n ;i++){if (ht[i].parent == 0) {min = i; break;}}for (int i = min+1; i <= n; i++){if (ht[i].weight < ht[min].weight && ht[i].parent == 0) {min = i;}}s1 = min;for (int i = 1; i <= n; i++){if (ht[i].parent == 0 && i != s1) {_min = i;break;}}for (int i = _min + 1; i <= n; i++){if (ht[i].weight < ht[_min].weight && i != s1 && ht[i].parent == 0) {_min = i;}}s2 = _min;
}
void CreHuffmanTree(HuffmanTree &ht, int w[], int n)
{for (int i = 1; i <= n; i++) ht[i] = { w[i],0,0,0 };int m = 2 * n - 1;for (int i = n + 1; i <= m; i++) ht[i] = { 0,0,0,0 };for (int i = n + 1; i <= m ; i++){int s1, s2;select(ht, i - 1, s1, s2);ht[i].weight = ht[s1].weight + ht[s2].weight;ht[s1].parent = ht[s2].parent = i;ht[i].LChild = s1, ht[i].RChild = s2;}
}
哈夫曼树编码
由于编码是从上到下,但是遍历是从下到上,所以思路是先开一个指针做数组用,从后往前写,然后用strcpy函数复制到编码区里
void CreHuffmanCode(HuffmanTree &ht, HuffmanCode &hc, int n)
{hc = (char**)malloc(sizeof(char*) * n + 1);char* code = (char*)malloc(sizeof(char) * n);code[n - 1] = '\0';for (int i = 1; i <= n; i++){int start = n - 1;int c = i;int p = ht[i].parent;while (p){if (ht[p].LChild == c) code[--start] = '0';else code[--start] = '1';c = p;p = ht[c].parent;}hc[i] = (char*)malloc((n - start) * sizeof(char));strcpy(hc[i], &code[start]);}free(code);
}
记得free释放空间
通过译码求输入的序列
本来我是准备直接硬着匹配的,但是时间复杂度和空间复杂度都太高了,最后是用哈夫曼树的特性来求,从树顶开始向下走,如果是0就走左边,是1就走右边,走到叶子节点为结束:
void code(HuffmanTree ht, int n, string s)
{int i = 0;while (i<(signed)s.size()){int cur = 2 * n - 1;while (ht[cur].LChild != 0 && ht[cur].RChild != 0){if (s[i] == '0') {cur = ht[cur].LChild;}else if (s[i] == '1') {cur = ht[cur].RChild;}i++;}char ch = 'a' + cur - 1;cout << ch;}
}
具体题目与完整代码:
建哈夫曼树,求哈夫曼编码,求解译码
问题描述】读入n个字符所对应的权值,自底向上构造一棵哈夫曼树,自顶向下生成每一个字符对应的哈夫曼编码,并依次输出。另,求解某字符串的哈夫曼编码,求解某01序列的译码。
【输入形式】输入的第一行包含一个正整数n,表示共有n个字符需要编码。其中n不超过100。第二行中有n个用空格隔开的正整数,分别表示n个字符的权值,依次按照abcd…的默认顺序给出。然后是某字符串和某01序列。
【输出形式】前n行,每行一个字符串,表示对应字符的哈夫曼编码。然后是某字符串的哈夫曼编码,某01序列的译码。
【注意】保证每次左子树比右子树的权值小;如出现相同权值的,则先出现的在左子树,即下标小的在左子树。
【样例输入】
8
5 29 7 8 14 23 3 11
aabchg
00011110111111001
【样例输出】
0001
10
1110
1111
110
01
0000
001
000100011011100010000
acdef
#include <bits/stdc++.h>
using namespace std;
typedef char** HuffmanCode;
typedef struct
{int weight;int parent;int LChild;int RChild;
}HTNode, HuffmanTree[10001];
void select(HuffmanTree ht, int n, int &s1, int &s2)
{int min, _min;//min是最小值,_min是第二小的值,分别赋给左,右子树for (int i = 1; i <= n ;i++){if (ht[i].parent == 0) {min = i; break;}}for (int i = min+1; i <= n; i++){if (ht[i].weight < ht[min].weight && ht[i].parent == 0) {min = i;}}s1 = min;for (int i = 1; i <= n; i++){if (ht[i].parent == 0 && i != s1) {_min = i;break;}}for (int i = _min + 1; i <= n; i++){if (ht[i].weight < ht[_min].weight && i != s1 && ht[i].parent == 0) {_min = i;}}s2 = _min;
}
void CreHuffmanTree(HuffmanTree &ht, int w[], int n)
{for (int i = 1; i <= n; i++) ht[i] = { w[i],0,0,0 };int m = 2 * n - 1;for (int i = n + 1; i <= m; i++) ht[i] = { 0,0,0,0 };for (int i = n + 1; i <= m ; i++){int s1, s2;select(ht, i - 1, s1, s2);ht[i].weight = ht[s1].weight + ht[s2].weight;ht[s1].parent = ht[s2].parent = i;ht[i].LChild = s1, ht[i].RChild = s2;}
}
void CreHuffmanCode(HuffmanTree &ht, HuffmanCode &hc, int n)
{hc = (char**)malloc(sizeof(char*) * n + 1);char* code = (char*)malloc(sizeof(char) * n);code[n - 1] = '\0';for (int i = 1; i <= n; i++){int start = n - 1;int c = i;int p = ht[i].parent;while (p){if (ht[p].LChild == c) code[--start] = '0';else code[--start] = '1';c = p;p = ht[c].parent;}hc[i] = (char*)malloc((n - start) * sizeof(char));strcpy(hc[i], &code[start]);}free(code);
}
void code(HuffmanTree ht, int n, string s)
{int i = 0;while (i<(signed)s.size()){int cur = 2 * n - 1;while (ht[cur].LChild != 0 && ht[cur].RChild != 0){if (s[i] == '0') {cur = ht[cur].LChild;}else if (s[i] == '1') {cur = ht[cur].RChild;}i++;}char ch = 'a' + cur - 1;cout << ch;}
}int main()
{int n, w[10001];cin >> n;for (int i = 1; i <= n; i++){cin >> w[i];}HuffmanTree ht;CreHuffmanTree(ht, w, n);HuffmanCode hc;CreHuffmanCode(ht, hc, n);for (int i = 1; i <= n; i++){cout << hc[i] << endl;}string sample;cin >> sample;for (int i = 0; i < sample.size(); i++){int temp = sample[i] - 96;cout << hc[temp];}cout << endl;string s;cin >> s;code(ht, n, s);
}
带权路径长度
有两种方式求解,第一是求出每个叶子结点然后用权值乘以这个结点到树顶的长度,这种方法太麻烦。另一种方式是求所有非叶子结点权值的和,这里写第二种写法,这种办法甚至不需要建一颗哈夫曼树
#include <bits/stdc++.h>
using namespace std;
int main()
{int n, x;cin >> n;int temp1, temp2, sum = 0, y;priority_queue<int, vector<int>, greater<int> > q;while (!q.empty()){q.pop();}for (int i = 1; i <= n; i++){cin >> x;q.push(x);}for (int i = 2; i <= n; i++){temp1 = q.top();q.pop();temp2 = q.top();q.pop();y = temp1 + temp2;sum = sum + y;q.push(y);}cout << sum;return 0;
}
具体的数据结构采用优先队列(堆)每次出队都是最小的数据,满足哈夫曼树的定义.
关于哈夫曼树与编码,带权路径长度相关推荐
- 创建哈夫曼树并求带权路径长度
创建哈夫曼树并求带权路径长度 [问题描述]根据给定的权重,构造哈夫曼树,输出其带权路径长度. [输入形式]输入权重,空格作为分隔,回车结束,权重个数小于10. [输出形式]哈夫曼树的带权路径长度. [ ...
- 计算WPL·哈夫曼树构建及带权路径长计算
计算WPL·哈夫曼树构建及带权路径长计算 题目信息 输入 输出 测试样例 解答 想法 题目信息 Huffman编码是通信系统中常用的一种不等长编码,它的特点是:能够使编码之后的电文长度最短. 输入 第 ...
- 让人头疼的哈夫曼树与编码
哈夫曼树(Huffman Tree): 给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树.哈夫曼树是带权路径长度最短的树,权值较大 ...
- 哈夫曼树建树编码解码
提示:昼短苦夜长,何不秉烛游! 文章目录 一.哈夫曼解析 1.手写哈夫曼树 2.为什么这样构成哈夫曼树? 路径 路径长度: 带权路径长度 树的最带权路径长度 哈夫曼树 二.构建哈夫曼树 三.哈夫曼树编 ...
- 优先级队列实现哈夫曼树的编码和译码
//优先级队列实现的哈夫曼树的编码和译码 #include<iostream> #include<queue> #include<string> using nam ...
- 20172305 2018-2019-1 蓝墨云班课实验--哈夫曼树的编码
20172305 2018-2019-1 蓝墨云班课实验--哈夫曼树的编码 实验要求 设有字符集:S={a,b,c,d,e,f,g,h,i,j,k,l,m,n.o.p.q,r,s,t,u,v,w,x, ...
- c语言赫夫曼树的编码与译码,哈夫曼树与编码译码实现
一.哈弗曼树的基本概念. 哈夫曼树,又称最优树,是一类带权路径长度最短的树.下面有几个概念: (1)路径. 树中一个结点到另一个结点之间的分支构成这两个结点之间的路径. (2)路径长度. 路径上的分枝 ...
- java哈夫曼树编码_哈夫曼树的编码实验
Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 建树,造树,编码,解码 一.哈夫曼树编码介绍 1.哈夫曼树: (1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子 ...
- 【数据结构】赫夫曼树与编码
赫夫曼树与赫夫曼编码 前言 赫夫曼树 存储结构 初始化树 构建树 赫夫曼编码 初始化编码 构建编码 前言 (概念) 路径:从一个节点到另一个节点的分支 路径长度:从一个节点到另一个节点的分支总数 节点 ...
最新文章
- Windows搭建wnmp
- 让textarea完全显示文章并且不滚动、不可拖拽、不可编辑
- .如何实现浏览器内多个标签页之间的通信?
- 从网上批量下载图片并重命名
- leetcode161. 相隔为 1 的编辑距离
- 三十而已,工程师如何做好职业成长?
- TX2017秋招笔试题之编码
- 重磅,企业实施大数据的路径
- 给linux默认mysql设置root密码
- 勤哲web配置教程_勤哲Excel服务器新手教程
- kylo添加登录权限module
- ios 打包证书.p12 .mobileprovision 制作详细流程
- 通往诺贝尔奖之路:盘点10个著名的科学家族
- 不改变像素尺寸怎么压缩图片
- 无插件播放之http-flv
- 笔记本电脑亮度调节按钮不起作用
- [blender]常用按键操作以及新手失误教程
- 目标跟踪(1)基于OpenCV实现单目标跟踪
- 一起来看看SpringBoot蓝天幼儿园管理系统(详解)
- Python爬虫实例(3)--BeautifulSoup的CSS选择器