哈夫曼树

  • 哈夫曼树与哈夫曼编码的定义
  • 建立哈夫曼树
  • 哈夫曼树编码
  • 通过译码求输入的序列
  • 具体题目与完整代码:
    • 建哈夫曼树,求哈夫曼编码,求解译码
    • 带权路径长度

哈夫曼树与哈夫曼编码的定义

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;
}

具体的数据结构采用优先队列(堆)每次出队都是最小的数据,满足哈夫曼树的定义.

关于哈夫曼树与编码,带权路径长度相关推荐

  1. 创建哈夫曼树并求带权路径长度

    创建哈夫曼树并求带权路径长度 [问题描述]根据给定的权重,构造哈夫曼树,输出其带权路径长度. [输入形式]输入权重,空格作为分隔,回车结束,权重个数小于10. [输出形式]哈夫曼树的带权路径长度. [ ...

  2. 计算WPL·哈夫曼树构建及带权路径长计算

    计算WPL·哈夫曼树构建及带权路径长计算 题目信息 输入 输出 测试样例 解答 想法 题目信息 Huffman编码是通信系统中常用的一种不等长编码,它的特点是:能够使编码之后的电文长度最短. 输入 第 ...

  3. 让人头疼的哈夫曼树与编码

    哈夫曼树(Huffman Tree): 给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树.哈夫曼树是带权路径长度最短的树,权值较大 ...

  4. 哈夫曼树建树编码解码

    提示:昼短苦夜长,何不秉烛游! 文章目录 一.哈夫曼解析 1.手写哈夫曼树 2.为什么这样构成哈夫曼树? 路径 路径长度: 带权路径长度 树的最带权路径长度 哈夫曼树 二.构建哈夫曼树 三.哈夫曼树编 ...

  5. 优先级队列实现哈夫曼树的编码和译码

    //优先级队列实现的哈夫曼树的编码和译码 #include<iostream> #include<queue> #include<string> using nam ...

  6. 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, ...

  7. c语言赫夫曼树的编码与译码,哈夫曼树与编码译码实现

    一.哈弗曼树的基本概念. 哈夫曼树,又称最优树,是一类带权路径长度最短的树.下面有几个概念: (1)路径. 树中一个结点到另一个结点之间的分支构成这两个结点之间的路径. (2)路径长度. 路径上的分枝 ...

  8. java哈夫曼树编码_哈夫曼树的编码实验

    Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 建树,造树,编码,解码 一.哈夫曼树编码介绍 1.哈夫曼树: (1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子 ...

  9. 【数据结构】赫夫曼树与编码

    赫夫曼树与赫夫曼编码 前言 赫夫曼树 存储结构 初始化树 构建树 赫夫曼编码 初始化编码 构建编码 前言 (概念) 路径:从一个节点到另一个节点的分支 路径长度:从一个节点到另一个节点的分支总数 节点 ...

最新文章

  1. Windows搭建wnmp
  2. 让textarea完全显示文章并且不滚动、不可拖拽、不可编辑
  3. .如何实现浏览器内多个标签页之间的通信?
  4. 从网上批量下载图片并重命名
  5. leetcode161. 相隔为 1 的编辑距离
  6. 三十而已,工程师如何做好职业成长?
  7. TX2017秋招笔试题之编码
  8. 重磅,企业实施大数据的路径
  9. 给linux默认mysql设置root密码
  10. 勤哲web配置教程_勤哲Excel服务器新手教程
  11. kylo添加登录权限module
  12. ios 打包证书.p12 .mobileprovision 制作详细流程
  13. 通往诺贝尔奖之路:盘点10个著名的科学家族
  14. 不改变像素尺寸怎么压缩图片
  15. 无插件播放之http-flv
  16. 笔记本电脑亮度调节按钮不起作用
  17. [blender]常用按键操作以及新手失误教程
  18. 目标跟踪(1)基于OpenCV实现单目标跟踪
  19. 一起来看看SpringBoot蓝天幼儿园管理系统(详解)
  20. Python爬虫实例(3)--BeautifulSoup的CSS选择器

热门文章

  1. 转:VC实现http上传文件
  2. Xyplayer X3 正式版
  3. 中秋节+国庆节,抓住Niushop“中国节”钜惠活动,错过就没有啦!
  4. html代码input,HTML oninput用法及代码示例
  5. Linux OOM机制详解
  6. TDD测试驱动开发入门实践
  7. 跨平台c开发库tbox:内存库使用详解
  8. 创建 /dev/video0 节点
  9. Cloudways是什么?Cloudways可以装WordPress吗?Cloudways怎么注册?Cloudways多少钱?
  10. [转载]面试官你也伤不起啊!