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. 修改Moodle的日期显示改英文为中文
  2. 总结H3CNE学习过程和其他
  3. oracle+创建序列自增,oracle序列详解和建立自增主键
  4. 在.Net 模板页中使用CSS样式
  5. 收集19个前端开发人员的必备工具
  6. jquery 实现 点击把数据移动右侧 点击再次移回到左侧
  7. php动态获取函数参数
  8. python列表切片和推导式思维导图_Python列表推导式使用
  9. oracle 切割字符串加引号_oracle存储过程中单引号及字符串拼接处理
  10. 「leetcode」90.子集II【回溯算法】详细图解!
  11. 思必驰重磅发布AI芯片,同时推出产业破局战略
  12. 11款企业网络运维监控软件汇总介绍-行云管家
  13. 跨省市跳槽,社保公积金处理办法
  14. 微软五笔调出,中英文切换快捷键
  15. linux搭建wordpress运行环境,Centos 6.x配置基于nginx的wordpress运行环境 | 旺旺知识库...
  16. 大数据杂谈篇:认识大数据生态(个人心得分享)
  17. Eclipse SVN文件对比详解
  18. html 中写注释吗,html 注释
  19. 苹果手机的隐藏功能分享
  20. Association, Aggregation, Composition, Abstraction, Generalization, Realization, Dependency

热门文章

  1. Qt for winrt结合Winrt API开发
  2. Word文档怎样添加图片?技巧分享!怎么在Word文档中加入图片?
  3. eclipse java转class_Eclipse中的Java项目:无法解析java.lang.Object类型。 它是从所需的.class文件间接引用的...
  4. python编程入门读书笔记1
  5. 【懒懒的Python学习笔记七】
  6. 数字图像处理100问—03二值化(Thresholding)
  7. ff14服务器延迟滑步,ff14 5.0黑魔怎么玩_最终幻想14 5.0黑魔输出手法
  8. 小红书java算法难吗_Java面试系列之记一次小红书之旅
  9. 毕业设计 单片机心率检测器设计与实现 - stm32
  10. mysql5717开发设置怎么调回来_mysql5.7.17安装配置图文教程