目录

哈夫曼编码(最优二叉树)

一、优势:缩短电文长度

二、思想:

三、过程:

四、图解实现过程:

五、总代码


哈夫曼编码(最优二叉树)

一、优势:缩短电文长度

二、思想:

获取每个字符出现的频率,用一个大小为[256]的数组保存(因为ASCII码是256个),最后作为每个字符的权重权重越大,意味着出现频率越大,希望它的码长越短,这样总体电文最小。最后把这些字符(不重复部分)、权重依次放入结点中,把这些结点作为一个个元素,从小到大依次组成哈夫曼树。

三、过程:

先统计出字符出现的频率,作为其权重。
编码保存:把每个不重复的字符频率作为权重,用二叉树进行排序,二叉树上面的字符权重大(出现频率高),编码的码长短,下面的字符权重小(出现频率低),编码码长长。
编码:输入字符,遍历整个二叉树,对比是否和叶子结点相同,是则保存编码。(左0右1)
译码:输入二进制码,在二叉树中走一遍,走到叶子结点即为需要保存的编码。(左0右1)

(向左走为0,向右走为1)

四、图解实现过程:

五、总代码

//哈夫曼编码
//优势:缩短电文长度
//先统计出字符出现的频率,作为其权重。
//编码保存:把每个不重复的字符作为权重,用二叉树进行排序,二叉树上面的字符权重高(出现频率高),编码的码长短,
//下面的字符权重小(出现频率低),编码码长长
//编码:输入字符,遍历整个二叉树,对比是否和叶子结点相同,是则保存编码
//译码:输入二进制码,在二叉树中走一遍,走到叶子结点即为需要保存的编码。
#include<iostream>
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
using namespace std;#define MAXSIZE 100char str[MAXSIZE];                       //要编码保存的电文
char str_en[MAXSIZE];                   //编码时输入的电文
char str_de[MAXSIZE];                   //解码时输出的电文
int code_de[MAXSIZE];               //解码时存储
int frequency[256] = { 0 };            //统计各字符出现频率
int flag_c[256] = { 0 };                   //只存储一次,判断是否第一次出现
int length = 0;                                //数组总长度
int LENGTH = 0;                            //叶子结点长度
int sumFrequency = 0;                  //权重之和
int index_s = 0;                           //字符串数组
int code[64];                               //编码
int index_c = -1;                          //编码数组
int step = 0;                                  //编码/译码步数(从哈夫曼树的根往后下走)
int sumCode[4 * MAXSIZE];           //总编码
int flag_exit = 0;                         //退出符号
int index = 0;                             //译码数组
int decode_length;                      //译码数组长度//树元素
typedef struct Tnode
{char data;                                 //存放数据int frequency;                            //权重(出现的频率)struct Tnode* lchild, * rchild;   //左右孩子int code[64];                         //每个字符的哈夫曼码int code_length;                     //编码长度
}Tnode;
Tnode T[MAXSIZE];                       //存放各结点
Tnode* hfmTree;                         //哈夫曼根结点
Tnode* Pre;                                 //存放前一个结点//输入字符串
void Input()
{cout << "请输入需要编码并保存编码的电文:\n";gets_s(str, 100);
}//输入待编码数组
void Encode_Input()
{cout << "请输入需要编码的电文:\n";getchar();gets_s(str_en, MAXSIZE);
}//输出编码后的数组
void Encode_Output()
{int i = 0;//下标for (i = 0; i <= index_c; i++){cout << sumCode[i];}cout << endl;
}//输入待译码数组
void Decode_Input()
{int i = 0;char ch = ' ';step = 0;cout << "请输入需要译码的二进制码:\n";index = 0;getchar();                                   //吸收空格//读取每位字符,挨个化整存入整形数组while (ch != '\n')                       //把每位字符保存到数组(换行退出){ch = getchar();                       //读取一位字符if (ch != '\n')code_de[i++] = ch - 48;    //字符化整}decode_length = i;                  //译码数组长度
}//获取权重
void GetFrequency()
{int i = 0;//统计字符频率for (i = 0; i < strlen(str); i++){frequency[str[i]]++;                  //频率表中对应字符出现数值+1}
}//创建树节点
void CreateTnode()
{int i = 0, count = 0;//添加字符和频率到树结构体数组中for (i = 0; i < strlen(str); i++){if (flag_c[str[i]] == 0)             //首次出现{flag_c[str[i]] = 1;                 //标志出现过T[count].data = str[i];T[count].frequency = frequency[str[i]];T[count].lchild = NULL;T[count].rchild = NULL;sumFrequency += T[count].frequency;        //计算叶子结点总权重count++;}}LENGTH = count;length = count;
}//获取最小值                        /***********注:要整体替换,否则后面会出现混乱**********/
Tnode Getmin()
{int i, j, max = 0;Tnode temp;//选择排序(权重从高到低)(最后的一个最小)for (i = 0; i < length; i++){max = i;for (j = i; j < length; j++){if (T[j].frequency > T[max].frequency)max = j;}if (max != i){temp = T[i];                              //整体替换T[i] = T[max];T[max] = temp;}}return T[--length];           //取出最后一个结点(最小权重)
}//遍历
void Traverse(Tnode* N)
{int i = 0;if (N != NULL){Traverse(N->lchild);if (N->lchild == NULL && N->rchild == NULL)                    //叶子结点{printf("%c结点权值:%d\t编码:", N->data, N->frequency);for (i = 0; i < N->code_length; i++){cout << N->code[i];}cout << endl;}Traverse(N->rchild);}
}//初始化哈夫曼树
void Init_hfmTree()
{hfmTree = (Tnode*)malloc(sizeof(Tnode));          //创建哈夫曼树hfmTree->lchild = NULL;hfmTree->rchild = NULL;Pre = hfmTree;                                                       //前一个结点
}//创建哈夫曼树
Tnode Create_hfmTree()
{int len;Tnode* N = (Tnode*)malloc(sizeof(Tnode));while (N->frequency != sumFrequency){N = (Tnode*)malloc(sizeof(Tnode));N->lchild = (Tnode*)malloc(sizeof(Tnode));           //左孩子N->rchild = (Tnode*)malloc(sizeof(Tnode));         //右孩子if (length != -1)*N->lchild = Getmin();elseN->lchild = NULL;                                              //地址设为空if (length != -1)*N->rchild = Getmin();elseN->rchild = NULL;                                                //地址设为空N->data = '#';                                                         //表示空N->frequency = N->lchild->frequency + N->rchild->frequency;       //求权重之和T[length++] = *N;                                                 //放入数组}return *N;
}//结点编码(初始存档编码)
void NodeEncode(Tnode* N)
{int i = 0;if (N != NULL){//向左走if (Pre->lchild == N){code[step++] = 0;                //向左走}else if (Pre->rchild == N){code[step++] = 1;              //向右走}Pre = N;                                 //保存上一结点if (N->lchild != NULL && N->rchild != NULL)     //未到达叶子结点{NodeEncode(N->lchild);step--;                                      //向回走Pre = N;                                  //保存上一结点NodeEncode(N->rchild);step--;                                        //向回走}else                                              //到达叶子结点{for (i = 0; i < step; i++)N->code[i] = code[i];          //记录编码N->code_length = step;            //记录码长}}
}//编码
void Encode(Tnode* N)
{int i = 0;if (flag_exit)return;if (N != NULL && str[index_s] != '\0')             //到达叶子结点或者字符串到尾{if (N->lchild != NULL && N->rchild != NULL)     //未到达叶子结点{Encode(N->lchild);Encode(N->rchild);}else                                                       //找到叶子结点{if (N->data == str_en[index_s])       //是要找的叶子结点{flag_exit = 1;                          //退出标志for (i = 0; i < N->code_length; i++){sumCode[++index_c] = N->code[i];          //编码存入}}}}
}//译码
void Decode(Tnode* N)
{int i = 0;if (N != NULL){if (N->lchild != NULL || N->rchild != NULL)                 //没有查找到叶子结点{if (code_de[index] == 0)          //向左走{index++;step++;Decode(N->lchild);step--;                           //弹出来}else if (code_de[index] == 1)   //向右走{index++;step++;Decode(N->rchild);step--;                           //弹出来}}else                 //查找到叶子结点{cout << N->data;         //输出译码结果}}
}int main()
{int choice;int i;Input();                      //输入字符GetFrequency();       //获取字符串//叶子结点的创建与排序CreateTnode();           //创建树节点//哈夫曼树的初始化与创建Init_hfmTree();*hfmTree = Create_hfmTree();//结点编码step = 0;NodeEncode(hfmTree);while (1){system("cls");cout << "请选择需要的服务:\n";cout << "1、查找所有已保存的结点编码和权\n";cout << "2、整体编码\n";cout << "3、整体译码\n";cout << "0、退出\n";cout << "请选择您需要的服务:\n";cin >> choice;//选项switch (choice){//0、退出case 0:exit(0);break;//1、遍历所有叶子结点case 1:Traverse(hfmTree);               //查找所有编码和权break;case 2:index_s = 0;Encode_Input();                 //编码输入//逐字符编码while (str_en[index_s] != '\0'){flag_exit = 0;Encode(hfmTree);index_s++;}Encode_Output();                    //编码输出break;//3、译码case 3://输入译码数组Decode_Input();index = 0;while (index < decode_length){//译码step = 0;Decode(hfmTree);          //译码并输出}cout << endl;break;default:cout << "无此选项!" << endl;break;}system("pause");}return 0;
}

数据结构与算法(6-5)二叉树的应用--哈夫曼树与哈夫曼编码相关推荐

  1. 数据结构与算法--死磕二叉树

    死磕二叉树 近一年都比较关注算法相关的知识,也刷了不少题,之前的文章中大多也是算法相关的文章,但是感觉每次遇到树相关的题型都不能应对自如,因此还是有必要在相关知识上下功夫,因此有此次总结,以下是所有树 ...

  2. 【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

    1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R ...

  3. 【数据结构与算法基础】哈夫曼树与哈夫曼编码(C++)

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  4. 数据结构与算法(陈越版)第五讲 (树下)树的应用——集合及其运算

    数据结构与算法(陈越版)第五讲 (树下)树的应用--集合及其运算 一.集合的表示 1.1.集合的表示 1.2.集合的储存 二.集合的运算 2.1查找以及普通并 2.2按照秩的合并算法 2.3路径压缩优 ...

  5. 【Java数据结构与算法】第十二章 哈夫曼树和哈夫曼编码

    第十二章 哈夫曼树和哈夫曼编码 文章目录 第十二章 哈夫曼树和哈夫曼编码 一.哈夫曼树 1.基本术语 2.构建思路 3.代码实现 三.哈夫曼编码 1.引入 2.介绍 3.代码实现哈夫曼编码综合案例 一 ...

  6. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  7. 【数据结构】-哈夫曼树以及哈夫曼编码

    哈夫曼树的几个定义 哈夫曼树又叫最优二叉树:特点是带权路径最短 带权路径长度:该结点到根结点的路径长度乘以该结点的权值. 树的带权路径长度(WPL):所有叶子结点到根结点的带全路径长度之和. 最优二叉 ...

  8. Python数据结构11:树的实现,树的应用,前中后序遍历,二叉查找树BST,平衡二叉树AVL树,哈夫曼树和哈夫曼编码

    1.概念 树一种基本的"非线性"数据结构. 相关术语: 节点Node:组成树的基本部分.每个节点具有名称,或"键值",节点还可以保存额外数据项,数据项根据不同的 ...

  9. 数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)

    目录 什么是哈夫曼树 哈夫曼树的定义 哈夫曼树的构造 图解操作 代码实现 代码解析 哈夫曼树的特点 哈夫曼编码 不等长编码 二叉树用于编码 哈夫曼编码实例 什么是哈夫曼树 我们先举个例子: 要将百分制 ...

  10. 【数据结构】【哈夫曼树】哈夫曼树、赫夫曼树(Huffman Tree)C语言实现

    目录 一.哈夫曼树定义与原理 二.构建哈夫曼树 三.哈夫曼编码 完整代码: 前言:章末含c语言实现完整代码 一.哈夫曼树定义与原理 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树.所谓树的带权 ...

最新文章

  1. ASP.NET 5系列教程 (二):Hello World
  2. 前端构建工具之争——Webpack vs Gulp 谁会被拍死在沙滩上
  3. 一条代码解决各种IE浏览器兼容性问题
  4. 从微软一站式代码库中学到的--跨域之间的session共享
  5. php开发api数据加密,php-app开发接口加密
  6. Enterprise Vault 2007 软硬件兼容性
  7. JAVA的cell设置行间距_iOS设置tableView的cell之间的间距
  8. bzoj 3357: [Usaco2004]等差数列(DP+map)
  9. (转)Uncaught TypeError: Cannot set property 'innerHTML' of null
  10. SpringBoot中调用第三方接口的三种方式
  11. 微信群打卡小程序_微信群不好管理?这几款小程序帮你管理微信群
  12. 国内外20多个科研论文下载神器(科研小白成长记 番外篇)
  13. 中国余数定理c语言pta,密码学基础——辗转相除法,费马小定理,欧拉定理,裴蜀定理,中国剩余定理...
  14. 百练noi21:二维数组右上左下遍历,24:蛇形填充数组
  15. 悬浮窗java_Android悬浮窗示例(floatingwindow)
  16. Redis源码阅读笔记 ----数据结构部分 sds
  17. Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operat
  18. 老司机的奇怪noip模拟T3-zhugeliang
  19. xstring invalid null pointer
  20. Java后端开发常考面试题大全

热门文章

  1. Android Studio 引入aar文件
  2. 常用的监听事件(android)
  3. js中定义变量之②var let const的区别
  4. (multi)set的某些操作
  5. Beta阶段总结博客(麻瓜制造者)
  6. Linux命令行与命令
  7. sqlserver trigger
  8. hdu1160FatMouse's Speed(DP)
  9. 【学习笔记】Silverlight框架:Jounce(4)——事件通信
  10. Tile Racer — 3D 赛车游戏