HuffMan编码C语言实现

实现了一种编码方式,和两种解码方式。
解码一种使用的是叶子回溯根。
一种使用了从根遍历过程。

代码:

HuffManEncoding

//
// Created by Zza on 2022/4/23.
//#ifndef DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREEENCODING_H
#define DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREEENCODING_H#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include "../../Chapter4/String.h"typedef struct node{char tar;int freq;
} node;#ifndef ELEM
#define ELEM
typedef node ELEMENT_TYPE;
#endif#include "../Binary Tree/BinaryTree_Array.h"typedef struct HuffManTree{//    实际上这里应该自己再重新设置一个Bin_Tree_Arr trees;int curTop;int treeNums;int* roots;bool encoded;
}HuffManTree;typedef struct InitDataPackage{int n;node* init;
} pkg;bool DisplayHuffManStruct(HuffManTree*);__attribute__((unused)) bool PkgDestruct(pkg*);__attribute__((unused)) bool Init_HuffMan(HuffManTree* tar, pkg* info);__attribute__((unused)) bool HuffManEncoding(HuffManTree* tar);bool HuffManDestruct(HuffManTree *tar);//======================================================================================================================bool _find_two_min_tree(HuffManTree* tar, int *min1, int *min2);bool _tree_merge(HuffManTree* tar, int root1, int root2);//======================================================================================================================__attribute__((unused)) bool HuffManEncoding(HuffManTree* tar){int timer = tar->treeNums - 1;int cur_tree_l, cur_tree_r;while (timer--){//        找到最小的两个树,在roots中的位置_find_two_min_tree(tar,&cur_tree_l,&cur_tree_r);
//        认为左结点会比右结点小,将树拼接,然后结点坐标存在roots的右边_tree_merge(tar,cur_tree_l,cur_tree_r);}return true;
}__attribute__((unused)) bool Init_HuffMan(HuffManTree* tar, pkg* info){tar->trees = (Binary_Tree_Array*)malloc(sizeof(Binary_Tree_Array));BinStaticTree_init(tar->trees, 2*info->n-1);tar->treeNums = tar->curTop = tar->trees->cur =info->n;tar->roots = (int*) malloc(sizeof(int)*info->n);for(int i=0;i<info->n;i++){tar->trees->elems[i].data = info->init[i];tar->trees->elems[i].left = tar->trees->elems[i].right = -1;tar->roots[i]=i;}tar->encoded = false;return true;
}//======================================================================================================================bool _find_two_min_tree(HuffManTree* tar, int *min1, int *min2){//    由于我们算法的设计,我们认为,0号位置一定会在交归纳中是最后一个树的根,用这个来预设*min1 = *min2 = 0;int temp;
//    root负责记录是树根的结点位置for(int i=1, j=0;i < tar->treeNums;i++){temp = tar->roots[i];if(temp>=0){temp = tar->trees->elems[temp].data.freq;if(temp <= tar->trees->elems[tar->roots[*min2]].data.freq){if(temp < tar->trees->elems[tar->roots[*min1]].data.freq){*min2 = *min1;*min1 = i;} else{*min2 = i;}}}}return true;
}bool _tree_merge(HuffManTree* tar, int root_l, int root_r){node l, r, cur;l = tar->trees->elems[tar->roots[root_l]].data;r = tar->trees->elems[tar->roots[root_r]].data;tar->trees->elems[tar->roots[root_l]].parent = tar->trees->elems[tar->roots[root_r]].parent = tar->curTop;//    printf("merge %d,%d at %d,%d\n",root_l,root_r,tar->roots[root_l],tar->roots[root_r]);
//    printf("with char: %c,%c\n",l.tar,r.tar);
//    printf("with freq: %d,%d\n",l.freq,r.freq);_StaticNode temp = {{'s',l.freq + r.freq},tar->roots[root_l], tar->roots[root_r]};tar->trees->elems[tar->curTop] = temp;tar->roots[root_l] = tar->curTop;tar->roots[root_r] = -1;tar->curTop++;return true;
}bool HuffManDestruct(HuffManTree *tar){BinStaticTree_destruct(tar->trees);free(tar->trees);free(tar->roots);
}#endif //DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREEENCODING_H

HuffManDecoding

//
// Created by Zza on 2022/4/23.
//#ifndef DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREEDECODING_H
#define DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREEDECODING_H#include "./HuffManTreeEncoding.h"
#include <stdio.h>#define HUFFMAN_CODE_NUMS 26
#define HUFFMAN_CODE_BASE_CHAR 'a'typedef struct ResContainer{char* res[HUFFMAN_CODE_NUMS];
}ResContainer;bool ContainerDestruct(ResContainer*);bool DisplayContainer(ResContainer*);__attribute__((unused)) bool HuffManDecode_Display_Stack(HuffManTree* tar, int root);bool HuffManDecode_Reverse(HuffManTree* tar, ResContainer*);#ifndef TREE_STK
#define TREE_STK
typedef int tNode;
#endifbool DisplayAct(char*, int, char);// 我们应当好好利用哈夫曼树是一个完全二叉树的性质来进行解码
__attribute__((unused)) bool HuffManDecode_Display_Stack(HuffManTree* tar, int root){Bin_Tree_Arr obj = tar->trees;
//    设置两个栈,一个栈用来存我们的行动路径,一个栈拿来存上一个根节点char* routine = (char*) malloc(sizeof(char)*obj->cur);int* nodes = (int*) malloc(sizeof(int)*obj->cur);char act;int i = 0, n = tar->treeNums;
//    总共访问n个叶子while (n){//        向左下搜索到最下方printf("-----------------------\n""left searching, start root %d l:%d r:%d\n",root,obj->elems[root].left,obj->elems[root].right);while (root>=0 && obj->elems[root].left >= 0){printf("%d-",root);nodes[i] = root;routine[i++] = '0';root = obj->elems[root].left;}
//        显示当前编码路径DisplayAct(routine,i,obj->elems[root].data.tar);n--;//        向上退栈
// 首先,我们在路径栈中,存放的是我们以什么方式来到这个节点
// 如果我们是由向右操作,进入节点的话,说明我们已经访问过这个根的子树,应当再次向上do {if(!i)break;root = nodes[--i];act = routine[i];//            printf("trace back,act:%c, cur root %d l:%d r:%d\n",act,root,obj->elems[root].left,obj->elems[root].right);//            每次路径退栈,也是反映我们是从左还是右回溯进入根的}while (act == '1');
//        当我们一直向上走,如果我们是从左进入根时,认为左树遍历完成,我们就会退出循环,去访问右边
//        向右移动一次root = obj->elems[root].right;nodes[i] = root;routine[i++] = '1';//        printf("right move, cur root %d l:%d r:%d\n",
//               root,obj->elems[root].left,obj->elems[root].right);}return true;
}bool HuffManDecode_Reverse(HuffManTree* tar, ResContainer* container){int cur,temp,base;for(int i=0;i<tar->treeNums;i++){cur = i;container->res[i] = (char*) malloc(sizeof(char)*tar->treeNums);base = tar->treeNums;container->res[i][--base] = '\0';while (tar->trees->elems[cur].parent){temp = tar->trees->elems[cur].parent;container->res[i][--base] = (cur==tar->trees->elems[temp].left)?'0':'1';cur = temp;}container->res[i][0] = (char)--base;}return true;
}bool DisplayAct(char* tar, int len, char type){printf("huffman code %c:",type);for(int i=0;i<len;i++){printf("%c",*tar);tar++;}printf("\n");
}bool ContainerDestruct(ResContainer* tar){for (int i = 0; i < HUFFMAN_CODE_NUMS; ++i) {free(tar->res[i]);}return true;
}bool DisplayContainer(ResContainer* tar){for (int i = 0; i < HUFFMAN_CODE_NUMS; ++i) {printf("%c: %s\n",i+HUFFMAN_CODE_BASE_CHAR,&(tar->res[i][(tar->res[i][0])+1]));}return true;
}#endif //DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREEDECODING_H

HuffMan Wrapper

//
// Created by Zza on 2022/4/25.
//#ifndef DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREE_H
#define DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREE_H#include "HuffManTreeEncoding.h"
#include "HuffManTreeDecoding.h"
#include <stdio.h>bool CalcCharFreq(const char* tar, pkg* res){int map[HUFFMAN_CODE_NUMS];for(int i=0;i<HUFFMAN_CODE_NUMS;i++){map[i] = 0;}while (*tar){map[(int)*tar-HUFFMAN_CODE_BASE_CHAR]++;tar++;}res->init = (node*)malloc(sizeof(node)*HUFFMAN_CODE_NUMS);res->n = HUFFMAN_CODE_NUMS;for(int i=0;i<HUFFMAN_CODE_NUMS;i++){res->init[i].tar = (char)(i+HUFFMAN_CODE_BASE_CHAR);res->init[i].freq = map[i];}return true;
}__attribute__((unused)) bool PkgDestruct(pkg* tar){free(tar->init);return true;
}bool HuffManDisplay(const char* tar){pkg info;CalcCharFreq(tar,&info);HuffManTree obj;Init_HuffMan(&obj,&info);HuffManEncoding(&obj);DisplayHuffManStruct(&obj);ResContainer container;HuffManDecode_Reverse(&obj, &container);DisplayContainer(&container);HuffManDecode_Display_Stack(&obj, obj.curTop-1);ContainerDestruct(&container);HuffManDestruct(&obj);PkgDestruct(&info);return true;
}bool DisplayHuffManStruct(HuffManTree* tar){for(int i=0;i<tar->curTop;i++){_StaticNode temp = tar->trees->elems[i];printf("id: %d\t""char: %c\t""freq: %d\t""left: %d\t""right: %d\t""parent: %d\n",i,temp.data.tar,temp.data.freq,temp.left,temp.right,temp.parent);}return true;
}#endif //DATASTRUCTUREIMPLEMENTINGC_HUFFMANTREE_H

HuffMan编码C语言实现相关推荐

  1. huffman编码压缩c语言,用Huffman编码对文件进行压缩的C语言实现

    本文介绍了采用Huffman编码对ASCII码文件进行压缩的基本原理,并用C语言程序实现了这个压缩过程.文中给出了比较完整的C语言程序代码,可以直接用于调试实验. 福 建电 脑 21 0 2年第 1期 ...

  2. huffman编码译码器用c语言,基于哈弗曼编码的数据压缩C语言实现

    haod 摘要 数据压缩技术是一项重要实用的信息技术.信息时代的到来,信息量迅速增长,使得数据压缩也显得越来越重要.数据压缩有多种编码方法,大致可分为无损压缩编码和有损压缩编码.其中,Huffman ...

  3. Huffman 编码的实现(C语言)

    Huffman 编码 具体原理及定义请百度,下面直接进行实现.具体实现过程是: 统计若干字符出现的频率,将其按频率(权重)升序存放进队列中,每次从队列中取两个结点合成一颗二叉树,这两个结点的根节点是取 ...

  4. 基于Huffman编码的C语言解压缩文件程序

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h>//极大 ...

  5. 数据压缩实验三:用c语言实现Huffman编码和压缩效率分析

    实验原理: 1.Huffman编码 Huffman编码是一种无失真的编码方式,是可变字长编码(VLC)的一种. Huffman编码基于信源的概率统计模型,它的基本思路是: 出现概率大的信源符号编长码, ...

  6. Huffman编码的C语言实现

    实验原理 Huffman 编码 (1) Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman 编码是可变字长编码(VLC)的一种. (2)Huffman 编码基于信源 ...

  7. Huffman 编码的编程与实现 C语言

    一 .目的: 1.    掌握Huffman树的概念.存储结构: 2.    掌握建立Huffman树和Huffman编码的方法: 二 .环境: operating system version:Wi ...

  8. huffman图像编码C语言,Huffman编码 数据结构 C语言

    为解决广大童鞋的数据结构实验问题写下本文:(只做参考哦.) 实验要求: Huffman编码(二叉树) l实验目的:熟练掌握二叉树应用(Huffman编码)的基本算法实现. l实现功能:对输入的一串电文 ...

  9. 采用Huffman编码进行数据压缩

    文章目录 问题 实验环境 程序组成 实现思路 如何用二进制0/1表示字符 '0' / '1' 源代码下载 程序运行和结果: 总结 问题 利用哈夫曼编码将英文文献进行压缩 注:哈夫曼算法及原理见博客ht ...

最新文章

  1. HDU 2040:亲和数
  2. C++trie树的多重搜索算法的实现(附完整源码)
  3. mysql command line client闪一下消失
  4. PostgreSQL 10.1 手册_部分 III. 服务器管理_第 24 章 日常数据库维护工作_24.3. 日志文件维护...
  5. 如何优雅地(用TeX)写AI论文
  6. html5页面签字,html5 canvas实现的手机端签字板
  7. MATLAB数字图像处理(一)图像的基本操作
  8. Python学习第二课-----绘制股票K线图(不使用mpl_finance包)
  9. 在Excel中查找/替换时使用换行符
  10. 银河麒麟 安装PL2303GC USB转串口驱动
  11. 2022-2028全球与中国体脂秤市场现状及未来发展趋势
  12. iOS三句话实现文本转语音:AVSpeechSynthesizer
  13. 强烈推荐 10 本我私藏的数据库书单,附读书方法
  14. 贤者之路, Caffe转TensorRT
  15. 3D立体显示技术原理与游戏应用历程简介 【转】
  16. linux查看图形化系统版本,查看 Linux 系统版本信息
  17. 百度地图添加自定义点标记、文本标注、点标记
  18. 用tflearn构建分类器
  19. cms 结构_构建CMS:结构和样式
  20. 帝国CMS7.5仿《当下软件园》整站源码/帝国CMS软件下载类网站模板

热门文章

  1. 国内研发!适用于安卓应用程序的 Word文档功能开发组件来啦!
  2. 支付宝app支付对接1
  3. JAVA常见面试题及解答
  4. python tkinter treeview制作_python-3.x – Tkinter Treeview标题样式
  5. 推荐两款好用的企业级内网穿透软件
  6. C#_深入理解Unity容器
  7. 教女朋友用Python快速绘制图表
  8. 而立之年——那些从一线城市退到二三线的程序员,现在过的怎么样了?
  9. 串口工具Kermit
  10. 问题:C-Kermitc Sorry, you must SET LINE or SET HOST first