哈夫曼编码及哈负面编码的C语言程序
c语言 哈夫曼树哈夫曼编码
c语言哈夫曼树哈夫曼编码哈夫曼树(Huffman Tree)和哈夫曼编码(Huffman Coding)是由戴维·哈夫曼在1952年为数据压缩应用而发明的。
哈夫曼编码是一种前缀编码,即任何字符的编码都不是另一个字符的编码的前缀。
在编码学中,哈夫曼编码是一种可变长度编码,其中较常见或较频繁的字符使用较短的编码,而较少见或较不频繁的字符使用较长的编码。
这种编码是由哈夫曼树生成的,哈夫曼树是一种特殊的二叉树,其每个节点的权重等于其左子树和右子树的权重之和。
在C语言中实现哈夫曼树和哈夫曼编码可能涉及以下步骤:1、定义哈夫曼树的节点结构。
每个节点可能包括字符,权重(或频率),以及左孩子和右孩子的指针。
ctypedef struct huffman_node {char character;unsigned int frequency;struct huffman_node *left, *right;} huffman_node;2、创建哈夫曼树。
首先,你需要计算每个字符的频率,然后根据这些频率创建一个哈夫曼树。
这个过程可能涉及使用优先队列(最小堆)来找出频率最小的两个节点,然后将它们合并为一个新的节点,新节点的频率是这两个节点的频率之和。
然后,将新节点放回队列中,重复这个过程直到队列中只剩下一个节点,这个节点就是你的哈夫曼树的根节点。
3、使用哈夫曼树生成哈夫曼编码。
从根节点开始,对于每个字符,左子树代表0,右子树代表1。
你可以遍历哈夫曼树,为每个字符生成其对应的哈夫曼编码。
4、实现解码。
给定一个哈夫曼编码,你可以通过遍历哈夫曼树来解码它。
对于每个位,如果是0,你跟随左子树,如果是1,你跟随右子树。
当你到达一个叶节点时,你就找到了对应的字符。
以上只是一个大致的步骤,具体的实现可能会根据你的需求和具体情况有所不同。
哈夫曼树及哈夫曼编码的算法实现c语言
哈夫曼树及哈夫曼编码的算法实现c语言1.引言1.1 概述哈夫曼树及哈夫曼编码是数据压缩和编码中常用的重要算法。
哈夫曼树由大卫·哈夫曼于1952年提出,用于根据字符出现的频率构建一种最优的前缀编码方式。
而哈夫曼编码则是根据哈夫曼树构建的编码表将字符进行编码的过程。
在现代通信和计算机领域,数据传输和存储中往往需要大量的空间。
为了有效利用有限的资源,减少数据的存储和传输成本,数据压缩成为一个重要的技术。
而哈夫曼树及哈夫曼编码正是数据压缩中常用的技术之一。
哈夫曼树的概念及原理是基于字符的频率和概率进行构建的。
在哈夫曼树中,字符出现频率越高的节点越接近根节点,出现频率越低的节点离根节点越远。
这种构建方式保证了哈夫曼树的最优性,即最小化编码的总长度。
哈夫曼编码的算法实现是根据哈夫曼树构建的编码表进行的。
编码表中,每个字符都与一段二进制编码相对应。
在进行数据压缩和解压缩时,通过查表的方式将字符转化为相应的二进制编码,或将二进制编码解析为原始字符。
本文旨在介绍哈夫曼树及哈夫曼编码的概念和原理,并通过C语言实现算法。
通过深入理解哈夫曼树及哈夫曼编码的实现过程,可以更好地理解数据压缩和编码的原理,为后续的研究和应用提供基础。
接下来,我们将首先介绍哈夫曼树的概念和原理,然后详细讲解哈夫曼编码的算法实现。
最后,我们将总结哈夫曼树及哈夫曼编码的重要性,并提出对哈夫曼树和哈夫曼编码进一步研究的方向。
让我们一起深入探索哈夫曼树及哈夫曼编码的奥秘吧!1.2 文章结构文章结构部分的内容可以包括以下内容:文章结构部分主要介绍了本文的组织结构和各个章节的内容概述,以帮助读者更好地理解全文的逻辑结构和内容安排。
首先,本文包括引言、正文和结论三个部分。
引言部分主要对哈夫曼树及哈夫曼编码的算法实现进行了概述,包括相关的概念、原理和目的。
正文部分则深入介绍了哈夫曼树的概念和原理,以及哈夫曼编码的算法实现。
最后,结论部分对本文的主要内容进行了总结,并提出了对哈夫曼树和哈夫曼编码的进一步研究方向。
C语言数据压缩哈夫曼编码和LZW算法
C语言数据压缩哈夫曼编码和LZW算法C语言数据压缩——哈夫曼编码与LZW算法在计算机科学中,数据压缩是一种重要的技术,它可以有效地减少数据的存储空间和传输带宽。
本文将介绍两种常用的数据压缩算法,分别是哈夫曼编码和LZW算法,并给出它们在C语言中的实现方法。
一、哈夫曼编码1. 哈夫曼编码的原理哈夫曼编码是一种前缀编码方法,它根据字符出现的频率构建一棵表示编码的二叉树,频率越高的字符离根节点越近。
通过将二叉树的左、右分支分别标记为0和1,可以得到每个字符的唯一编码。
2. 实现哈夫曼编码的步骤(1)统计字符频率:遍历待压缩的数据,统计每个字符出现的频率。
(2)构建哈夫曼树:根据字符频率构建哈夫曼树,使用优先队列或堆来实现。
(3)生成哈夫曼编码表:通过遍历哈夫曼树,从根节点到各个叶子节点的路径上的0、1序列构建编码表。
(4)进行编码:根据生成的哈夫曼编码表,将待压缩数据转换为对应的编码。
(5)进行解码:利用哈夫曼树和生成的哈夫曼编码表,将编码解析为原始数据。
二、LZW算法1. LZW算法的原理LZW算法是一种字典压缩算法,它不需要事先进行字符频率统计,而是根据输入数据动态构建一个字典。
将输入数据中的序列与字典中的条目逐一匹配,若匹配成功则继续匹配下一个字符,若匹配失败则将当前序列加入字典,并输出该序列的编码。
2. 实现LZW算法的步骤(1)初始化字典:将所有可能的单字符作为字典的初始条目。
(2)读入输入数据:依次读入待压缩的数据。
(3)匹配字典:将读入的字符与字典中的条目逐一匹配,直到无法匹配成功。
(4)输出编码:将匹配成功的条目对应的编码输出。
(5)更新字典:若匹配失败,则将当前序列添加到字典中,并输出前一个匹配成功的条目对应的编码。
(6)重复步骤(3)至(5),直到输入数据全部处理完毕。
三、C语言实现1. 哈夫曼编码的C语言实现```c// TODO:哈夫曼编码的C语言实现```2. LZW算法的C语言实现```c// TODO:LZW算法的C语言实现```四、总结本文介绍了C语言中两种常用的数据压缩算法——哈夫曼编码和LZW算法。
哈夫曼信源编码c语言程序代码
哈夫曼信源编码c语言程序代码哈夫曼编码的C语言实现编码原理程序步骤的分析:哈夫曼码是用概率匹配方法进行信源编码。
编程时应该注意:1,概率大的符号对应于短码,概率小的对应于长码,充分利用短码;2缩减信源的最后二个码字,总是最后一位不同,保证了哈夫曼码是即时码。
程序步骤:(见信息论课本p88页内容)(l)将信号源的符号按照出现概率递减的顺序排列。
(2)将两个概率最小的字母分别配以0和1两个码元,并将这两个概率相加作为一个新字母的概率(3)重排后的两个概率最小符号重复步骤(2)过程。
(4)不断继续上述过程,直到最后两个符号配以0和1为止(5)从最后一级开始向前返回各个信源符号所对应的码元序列,及相应的码字。
根据以上规则编码可知:哈夫曼编码实际上构造了一个码树,码树从最上层的端点开始构造,到树根结束,最后得到一个横放的码树,所以编出的码是即时码。
哈夫曼编码概率大的符号对应于短码,概率小的符号对应于长码,使平均码长最小。
每次对概率最小的两个符号求概率之和形成缩减信源时,构造出两个树枝,由于给两个树枝赋码元时是任意的,因此编出的码字不惟一。
程序源代码如下;#include stdio.h#include malloc.h #include conio.h #include string.h #include stdlib.h #define HuffmanTree HF #define HuffmanCode HMC typedef struct {unsigned int weight; unsigned int parent,lchild,rchild; } HTNode,*HF; typedef char **HMC; typedef struct { unsigned int s1; unsigned int s2; } MinCode; void Error(char *message); HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n); MinCode Select(HF HT,unsigned int n); void Error(char *message) { fprintf(stderr,“Error:%s\n",message); exit(1); } HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n) { unsigned int i,s1=0,s2=0; HF p; char *cd; unsigned int f,c,start,m; MinCode min; if(n=1) Error("Code too small!"); m=2*n-1;HT=(HF)malloc((m+1)*sizeof(HTNode)); for(p=HT,i=0;ii++,p++,w++) { p-weight=*w; p-parent=0; p-lchild=0; p-rchild=0; } for(;ii++,p++) { p-weight=0; p-parent=0; p-lchild=0; p-rchild=0; } for(i=n+1;ii++){ min=Select(HT,i-1); s1=min.s1; s2=min.s2;HT[s1].parent=i; HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight; } printf("HT List:\n");printf("Number\t\tweight\t\tparent\t\tlchild\t\trchild\n"); for(i=1;ii++) printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);HC=(HMC)malloc((n+1)*sizeof(char *)); cd=(char *)malloc(n*sizeof(char *)); cd[n-1]='\0'; for(i=1;ii++) { start=n-1;for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) if(HT[f].lchild==c) cd[--start]='0'; else cd[--start]='1'; HC[i]=(char *)malloc((n-start)*sizeof(char *)); strcpy(HC[i],cd[start]); } free(cd); return HC; } void main() {MinCode Select(HF HT,unsigned int n); HF HT=NULL; HuffmanCode HC=NULL; unsigned int *w=NULL; unsigned int i,n; printf("请输入节点个数n:"); scanf("%d", w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *));w=0; printf("请输入权重:\n"); for(i=1;ii++) { printf("w[%d]=",i);scanf("%d",w[i]); } HC=HuffmanCoding(HT,HC,w,n); printf("HMC:\n");printf("Number\t\tWeight\t\tCode\n"); for(i=1;ii++)printf("%d\t\t%d\t\t%s\n",i,w[i],HC[i]); } MinCode Select(HF HT,unsigned int n) { unsigned int min,secmin; unsigned int temp; unsigned int i,s1,s2,tempi; MinCode code;s1=1;s2=1; for(i=1;ii++) if(HT[i].parent==0) { min=HT[i].weight; s1=i; break; } tempi=i++; for(;ii++) if(HT[i].weightminHT[i].parent==0){ min=HT[i].weight; s1=i; } for(i=tempi;ii++) if(HT[i].parent==0i!=s1){ secmin=HT[i].weight; s2=i; break; } for(i=1;ii++)if(HT[i].weightsecmini!=s1HT[i].parent==0) { secmin=HT[i].weight; s2=i; } if(s1s2){ temp=s1; s1=s2; s2=temp; } code.s1=s1; code.s2=s2; return code; } 运行结果如下:请输入节点个数n:5请输入权重:w=2 w=3 w=1 w=1 w=3 Number Weight Code 1 2 00 2 3 10 3 1 010 4 1 011 5 3 11 Press any key to continue编程感想及总结:正如事物均具有两面性,哈夫曼编码也具有优点和缺点,比如哈夫曼编码可以取得较好的荣誉压缩效果,使得输出码元概率均匀化。
哈夫曼编解码 完整c程序代码
哈夫曼编解码完整c程序代码Huffman 编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据进行预先编码,在接收端进行解码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/解码系统。
2)要求:一个完整的huffman编解码系统应该具有以下功能:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立Huffman 树,并将它存入hfmTree 中。
编码(Encoding)。
利用已经建好的Huffman树(如果不在内存,则应从文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
解码(Decoding)。
利用已经建立好的Huffman树将文件CodeFile中的代码进行解码,结果存入TextFile中。
打印代码文件(Print)。
将文件CodeFile以紧凑的格式显示在终端上,每行50 个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
打印Huffman树(Tree Printing)。
将已经在内存中的Huffman树以直观的形式(树或者凹入的形式)显示在终端上,同时将此字符形式的Huffman 树写入文件TreePrint中。
3) 测试数据: 用下表给出的字符集和频度的实际统计数据建立Huffman树,并对以下报文进行编码和译码:“THIS PROGRAM IS MY FAVORITE”。
字符 A B C D E F G H I J K L M 频度1866413223210321154757153220 字符 N O P Q R S T U V W X Y Z 频度5763151485180238181161 完整代码如下:#include<stdio、h>#include<iostream>#include<string>#define N100int*w;char *c,stack[N],code[N][N];int s1,s2;typedef struct HuffmanTree{int weight;int parent;int lchild;int rchild;}HuffmanTree,*Huff;void menu(void); voidSelect(struct HuffmanTree HT[],int i); voidHuffmanTree(Huff &HT,int *w,int n);void visite(HuffHT,int i,int flag,int rear);void translatef(char*scource,char *save,int n);bool uncodef(FILE *fp1,FILE*fp2,Huff HT,int n);int inputHuff();void screanio(int n);void fileio(int n);int initHuff();void Print_tree(int n,Huff HT);void Convert_tree(Huff HT,unsigned charT[100][100],int tt[100][100],int s,int *i,int j);void decoding(int n);void coding(int n);void main(){intn=0;menu();Huff HT;char state;do{std::cout<<"input:\n";std::cin>>state;fflush(stdin); //读取状态switch(state){ caseI:n=inputHuff();HuffmanTree(HT,w,n);st d::cout<<"\nHuffmanTree 初始化完毕\n";break;caseC:coding(n);break; caseD:decoding(n);break;caseP:Print_tree(n,HT);break;caseQ:break;}}while(state!=Q);}void menu()//显示菜单函数{std::cout<<"===========HuffmanCoding===========\n"; std::cout<<"input \t\t do\n";std::cout<<"I\t\tInit_HUffTree\n"; //初始化huffmantreestd::cout<<"C \t\tCoding\n"; //对ToBeTran、txt文件中的字符进行编码到CodeFile、txt中std::cout<<"D \t\tUnCoding\n"; //对CodeFile、txt中的01序列进行解码到TextFile、txtstd::cout<<"P \t\tPrintTree\n"; //打印哈夫曼树std::cout<<"Q \t\tquit\n";std::cout<<"请初始化哈夫曼树再执行后面的操作\n";}int inputHuff()//输入各个字母及其权值{int i=1,n=0;int ww[28];char cc[28];while(1){std::cout<<"input the letter(input # to stop):";cc[i]=std::cin、get();fflush(stdin);if(cc[i]==#)break;std::cout<<"inputtheweight:";std::cin>>ww[i];fflush(stdin);n++;i++;}w=(int *)malloc(sizeof(int)*(n+1));c=(char*)malloc(sizeof(char)*(n+1));for(i=0;i<n+1;i++){w[i]=ww[i ];c[i]=cc[i];}return n;}void HuffmanTree(Huff &HT,int*w,int n)//初始化哈夫曼树{int m,i;m=n*2-1;HT=(struct HuffmanTree *)malloc(sizeof(structHuffmanTree)*(m+1));HT[0]、lchild=0;HT[0]、parent=0;HT[0]、rchild=0;HT[0]、weight=0;for(i=1;i<m;i++){HT[i]、weight=i<=n?w[i]:0;HT[i]、lchild=HT[i]、rchild=HT[i]、parent=0;}for(i=n+1;i<=m;i++){ Select(HT,i);HT[i]、lchild=s1;HT[i]、rchild=s2;HT[i]、weight=HT[s1]、weight+HT[s2]、weight;HT[s1]、parent=HT[s2]、parent=i;}}void Select(struct HuffmanTree HT[],int i) //在HT[1、、i-1]中选择parent为0且weight为最小的两个结点{ int j;for(j=1;j<i;j++){if(HT[j]、parent==0){s1=j;s2=j;goto flag;}}flag:for(j=s1+1;j<i;j++){if(HT[j]、parent==0){if(HT[s1]、weight >=HT[j]、weight){s2=s1;s1=j;}if(HT[s2]、weight>HT[j]、weight&&j!=s1)s2=j;if(s1==s2)s2=j;}}}void Print_tree(int n,Huff HT)//以凹入法的形式打印树{ unsigned char T[100][100];int tt[100][100]; int i,j,m=0; FILE *fp;Convert_tree(HT,T,tt,0,&m,2*n-1); //将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中if((fp=fopen("treeprint、txt","wb+"))==NULL)printf("Open file treeprint、txt error!\n");printf("\n以凹凸表形式打印已建好的赫夫曼树:\n");for(i=1;i<=2*n-1;i++){ for (j=0;T[i][j]!=0;j++){ if(T[i][j]== ){printf(" ");fputc(T[i][j],fp);} else{printf("%d",tt[i][j]);fprintf(fp,"%d\n\n\n",tt[i][j]);} } printf("\n"); } fclose(fp); printf("\n此字符形式的哈夫曼树已写入文件treeprint、txt中、\n\n"); printf("\n文件treeprint、txt的打开方式要为写字板,若打开方式为记事本,则无法显示凹凸表的形式\n"); } void Convert_tree(HuffHT,unsigned char T[100][100],int tt[100][100],int s,int*i,int j)//将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中{ int k,l; l=++(*i); for(k=0;k<s;k++)T[l][k]= ; T[l][k]=#; tt[l][k]=HT[j]、weight;if(HT[j]、lchild)Convert_tree(HT,T,tt,s+1,i,HT[j]、lchild); if(HT[j]、rchild)Convert_tree(HT,T,tt,s+1,i,HT[j]、rchild);T[l][++k]=\0; } void coding(int n)//对文件ToBeTran、txt编码到CodeFile、txt{ FILE*fp1;Huff HT;HuffmanTree(HT,w,n);visite(HT,2*n-1,2,0);fflush(stdin);translatef("ToBeTran、txt","CodeFile、txt",n);fp1=fopen("CodeFile、txt","r");printf("\n编码已写入文件treeprint、txt中、\n");fclose(fp1);}void decoding(int n)//对CodeFile、txt中的01序列进行解码到TextFile、txt{FILE *fp1,*fp2;HuffHT;HuffmanTree(HT,w,n);fp1=fopen("CodeFile、txt","r");fp2=fopen("TextFile、txt","w");while(uncodef(fp1,fp2,HT,2*n-1));printf("\n");printf("\n解码已写入文件TextFile、txt 中、\n");fclose(fp1);fclose(fp2);}void visite(Huff HT,int i,int flag,int rear)//通过递归调用visite()函数,得到各个字母的编码,存储于全局变量code[][]中{intj=0,k=0;if(flag==0){ stack[rear]=0;rear++;}elseif(flag==1){stack[rear]=1;rear++;}if(HT[i]、lchild==0){for(j=0;j<rear;j++){code[i][j]=stack[j];}code[ i][j]=#;rear--;return;}visite(HT,HT[i]、lchild,0,rear);visite(HT,HT[i]、rchild,1,rear);k=rear;for(j=0;j<k;j++){code[i][j]=stack[j ];}code[i][j]=#;rear--;return;}void translatef(char*scource,char *save,int n)//读取文件中的字母序列,并根据code[][]将其转换成01序列输出{FILE *fp1,*fp2;char p= ;int i=0,j=0,k=0;fp1=fopen(scource,"r");fp2=fopen(save,"w");p= fgetc(fp1);printf("\n得到的编码为:\n");while(p!=EOF){for(i=0;i<=n;i++){if(c[i]==p){for(j =0;j<N&&code[i][j]!=#;j++){fputc(code[i][j],fp2);putchar( code[i][j]);k++;if(k>=50){k=0;putchar(\n);}}}}p=fgetc(fp1 );}fclose(fp1);fclose(fp2);}bool uncodef(FILE *fp1,FILE *fp2,Huff HT,int n)//通过对树的访问,把文件中01序列转换成一个字母输出。
C++实现哈夫曼编码完整代码
C++实现哈夫曼编码完整代码#include <iostream>#include <queue>#include <vector>#include <map>#include <string>using namespace std;class Node {public:char c; //表示字符int frequency; //表示该字符出现的次数或频率Node *left;Node *right;Node(char _c, int f, Node *l = NULL, Node *r = NULL):c(_c), frequency(f), left(l), right(r) { }bool operator<(const Node &node) const { //重载<运算法以至于在加入优先队列的时候决定如何处理结点位置return frequency > node.frequency;}};void initNode(priority_queue<Node> &q, int nodeNum) {char c;int frequency;for (int i = 0; i < nodeNum; i++) {cout << "输入字符和结点出现的次数: ";cin >> c >> frequency;Node node(c, frequency);q.push(node);}}void showNode(priority_queue<Node> q) {while (!q.empty()) {Node node = q.top(); q.pop();cout << node.c << ", " << node.frequency << endl;}}//构造哈夫曼树void huffmanTree(priority_queue<Node> &q) {while (q.size() != 1) {Node *left = new Node(q.top()); q.pop();Node *right = new Node(q.top()); q.pop();Node node('R', left->frequency + right->frequency, left, right);q.push(node);}}// 打印哈夫曼编码void huffmanCode(Node *root, string &prefix, map<char, string> &result) { string m_prefix = prefix;if (root->left == NULL)return;//处理左子树prefix += "0";//如果是叶子结点则输出,否则递归打印左子树if (root->left->left == NULL)result[root->left->c] = prefix;//cout << root->left->c << ": " << prefix << endl;elsehuffmanCode(root->left, prefix, result);//还原原来的路径,回溯prefix = m_prefix;//处理右子树prefix += "1";//如果是叶子结点,则输出, 否则递归打印右子树if (root->right->right == NULL)result[root->right->c] = prefix;//cout << root->right->c << ": " << prefix << endl;elsehuffmanCode(root->right, prefix, result);}void testResult(map<char, string> result) {//迭代map容器map<char, string>::const_iterator it = result.begin(); while (it != result.end()) {cout << it->first << ": " << it->second << endl;++it;}}int main() {priority_queue<Node> q;int nodeNum;//初始化字符信息cout << "请输入结点个数: ";cin >> nodeNum;initNode(q, nodeNum);//showNode(q);//构造哈夫曼树huffmanTree(q);//构造哈夫曼编码Node root = q.top();string prefix = "";map<char, string> result;huffmanCode(&root, prefix, result);//检验结果是否正确testResult(result);return 0;}。
用c语言实现哈夫曼编码
用c语言实现哈夫曼编码哈夫曼编码是一种用于无损数据压缩的熵编码算法。
以下是一个简单的使用C语言实现哈夫曼编码的例子。
这个例子只实现了编码过程,没有实现解码过程。
c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>// 节点结构体typedef struct Node {char data;int freq;struct Node *left, *right;} Node;// 创建新节点Node* newNode(char data, int freq) {Node* node = (Node*) malloc(sizeof(Node));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 计算前缀和int getSum(Node* root) {if (!root) return0;return root->freq + getSum(root->left) + getSum(root->right);}// 创建哈夫曼树Node* createHuffmanTree(char data[], int freq[], int size) { if (size == 0) return NULL;Node *left = newNode(data[size-1], freq[size-1]);Node *right = createHuffmanTree(data, freq, size-1);Node *top = newNode(0, getSum(right));top->left = left;top->right = right;return top;}// 打印哈夫曼编码void printHuffmanCode(Node* root, int n, char code[]) {if (!root) return;if (root->data != 0) printf("%c: ", root->data);code[n] = root->data;printHuffmanCode(root->left, n+1, code);printHuffmanCode(root->right, n+1, code);}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data)/sizeof(data[0]);Node* root = createHuffmanTree(data, freq, size);char code[256] = {0}; // 存放哈夫曼编码,初始为空字符串,表示没有编码,对应字符的编码为空字符串。
哈夫曼树编码c语言
以下是C语言实现哈夫曼树编码的示例代码:```c#include <stdio.h>#include <stdlib.h>// 定义结构体表示节点struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;};// 创建新节点struct TreeNode* newNode(int val) {struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));node->val = val;node->left = NULL;node->right = NULL;return node;}// 计算权值和int calculateWeightSum(struct TreeNode* root) {if (root == NULL) {return 0;}return root->val + calculateWeightSum(root->left) + calculateWeightSum(root->right);}// 构建哈夫曼树struct TreeNode* buildHuffmanTree(int** freq, int size) {// 创建频率数组int arr[size];for (int i = 0; i < size; i++) {arr[i] = freq[i][0];}// 构建哈夫曼树struct TreeNode* root = NULL;int index = 0;while (index < size) {int min1 = INT_MAX, min2 = INT_MAX;int min1Index = -1, min2Index = -1;for (int i = 0; i < size; i++) {if (arr[i] < min1 && arr[i] != 0) {min1 = arr[i];min1Index = i;}if (arr[i] < min2 && arr[i] != 0) {min2 = arr[i];min2Index = i;}}// 创建新节点作为左右子树,并加入频率数组中arr[min1Index] = 0;arr[min2Index] = 0;struct TreeNode* left = newNode(min1);struct TreeNode* right = newNode(min2);left->left = right;right->right = left;// 将左右子树作为新的根节点,并更新频率数组和根节点指针if (root == NULL) {root = left;} else {struct TreeNode* parent = root;while (parent->left != NULL) {parent = parent->left;}parent->left = left;left->parent = parent;while (parent->right != NULL) {parent = parent->right;}parent->right = right;right->parent = parent;}index += 2; // 跳过左右子树,继续寻找下一对最小的节点构建子树,直到遍历完所有节点为止。
哈夫曼编码c语言代码
哈夫曼编码c语言代码1.统计数据中每个字符出现的次数。
2.根据每个字符出现的次数建立哈夫曼树。
3.根据哈夫曼树构建每个字符的编码,相同的字符具有不同的编码。
4.用编码替换原数据中的字符。
根据上述步骤,我们可以得到以下的C语言实现。
C语言实现哈夫曼编码在C语言中,我们可以使用结构体来表示哈夫曼树节点及其信息:```ctypedef struct node 。
char content;int freq;struct node某 left;struct node某 right;} node;```其中content表示节点所代表的字符,freq表示该字符在数据中出现的次数,left和right分别指向节点的左右子节点。
我们可以使用一个链表来存储所有的字符及其出现的次数:```ctypedef struct listNode 。
node某 n;struct listNode某 ne某t;} listNode;```这个链表可以通过遍历数据,统计每个字符出现的次数来构建。
我们可以使用一个堆来存储所有的树节点,每次从堆中取出频率最小的两个节点,构建一个新的节点,然后将这个新节点插入堆中。
重复这个过程直到堆中只剩下一个根节点,这个节点就是哈夫曼树的根节点。
```ctypedef struct heap 。
int size;node某某 nodes;} heap;```定义堆的时候,size表示堆中节点的数量,nodes是一个数组,存储所有的节点。
我们可以使用一棵二叉堆来实现堆的操作,即将频率最小的节点放在堆的顶部。
构建好哈夫曼树后,我们可以通过遍历树来给每个字符一个独一无二的编码。
编码的时候,我们可以使用一个栈来存储每个节点的信息,然后倒序输出栈中的内容来得到编码。
最后,我们可以使用编码替换原数据中的字符。
在解码的时候,我们只需要将编码反向遍历树即可还原原始数据。
总结。
哈夫曼编码详解(C语言实现)
哈夫曼编码详解(C语言实现)哈夫曼编码是一种常见的前缀编码方式,被广泛应用于数据压缩和传输中。
它是由大卫·哈夫曼(David A. Huffman)于1952年提出的,用于通过将不同的字符映射到不同长度的二进制码来实现数据的高效编码和解码。
1.统计字符频率:遍历待编码的文本,记录每个字符出现的频率。
2.构建哈夫曼树:根据字符频率构建哈夫曼树,其中出现频率越高的字符位于树的较低层,频率越低的字符位于树的较高层。
3.生成编码表:从哈夫曼树的根节点开始,遍历哈夫曼树的每个节点,为每个字符生成对应的编码。
在遍历过程中,从根节点到叶子节点的路径上的“0”表示向左,路径上的“1”表示向右。
4.进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。
5.进行解码:根据生成的编码表和编码结果,将编码替换为原始字符。
下面是一个用C语言实现的简单哈夫曼编码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>//定义哈夫曼树的节点结构体typedef struct HuffmanNodechar data; // 字符数据int freq; // 字符出现的频率struct HuffmanNode *left; // 左子节点struct HuffmanNode *right; // 右子节点} HuffmanNode;//定义编码表typedef structchar data; // 字符数据char *code; // 字符对应的编码} HuffmanCode;//统计字符频率int *countFrequency(char *text)int *frequency = (int *)calloc(256, sizeof(int)); int len = strlen(text);for (int i = 0; i < len; i++)frequency[(int)text[i]]++;}return frequency;//创建哈夫曼树HuffmanNode *createHuffmanTree(int *frequency)//初始化叶子节点HuffmanNode **leaves = (HuffmanNode **)malloc(256 * sizeof(HuffmanNode *));for (int i = 0; i < 256; i++)if (frequency[i] > 0)HuffmanNode *leaf = (HuffmanNode*)malloc(sizeof(HuffmanNode));leaf->data = (char)i;leaf->freq = frequency[i];leaf->left = NULL;leaf->right = NULL;leaves[i] = leaf;} elseleaves[i] = NULL;}}//构建哈夫曼树while (1)int min1 = -1, min2 = -1;for (int i = 0; i < 256; i++)if (leaves[i] != NULL)if (min1 == -1 , leaves[i]->freq < leaves[min1]->freq) min2 = min1;min1 = i;} else if (min2 == -1 , leaves[i]->freq < leaves[min2]->freq)min2 = i;}}}if (min2 == -1)break;}HuffmanNode *parent = (HuffmanNode*)malloc(sizeof(HuffmanNode));parent->data = 0;parent->freq = leaves[min1]->freq + leaves[min2]->freq;parent->left = leaves[min1];parent->right = leaves[min2];leaves[min1] = parent;leaves[min2] = NULL;}HuffmanNode *root = leaves[min1];free(leaves);return root;//生成编码表void generateHuffmanCode(HuffmanNode *root, HuffmanCode *huffmanCode, char *code, int depth)if (root->left == NULL && root->right == NULL)code[depth] = '\0';huffmanCode[root->data].data = root->data;huffmanCode[root->data].code = strdup(code);return;}if (root->left != NULL)code[depth] = '0';generateHuffmanCode(root->left, huffmanCode, code, depth + 1);}if (root->right != NULL)code[depth] = '1';generateHuffmanCode(root->right, huffmanCode, code, depth + 1);}//进行编码char *encodeText(char *text, HuffmanCode *huffmanCode)int len = strlen(text);int codeLen = 0;char *code = (char *)malloc(len * 8 * sizeof(char));for (int i = 0; i < len; i++)strcat(code + codeLen, huffmanCode[(int)text[i]].code);codeLen += strlen(huffmanCode[(int)text[i]].code);}return code;//进行解码char* decodeText(char* code, HuffmanNode* root) int len = strlen(code);char* text = (char*)malloc(len * sizeof(char)); int textLen = 0;HuffmanNode* node = root;for (int i = 0; i < len; i++)if (code[i] == '0')node = node->left;} elsenode = node->right;}if (node->left == NULL && node->right == NULL) text[textLen] = node->data;textLen++;node = root;}}text[textLen] = '\0';return text;int maichar *text = "Hello, World!";int *frequency = countFrequency(text);HuffmanNode *root = createHuffmanTree(frequency);HuffmanCode *huffmanCode = (HuffmanCode *)malloc(256 * sizeof(HuffmanCode));char code[256];generateHuffmanCode(root, huffmanCode, code, 0);char *encodedText = encodeText(text, huffmanCode);char *decodedText = decodeText(encodedText, root);printf("Original Text: %s\n", text);printf("Encoded Text: %s\n", encodedText);printf("Decoded Text: %s\n", decodedText);//释放内存free(frequency);free(root);for (int i = 0; i < 256; i++)if (huffmanCode[i].code != NULL)free(huffmanCode[i].code);}}free(huffmanCode);free(encodedText);free(decodedText);return 0;```上述的示例代码实现了一个简单的哈夫曼编码和解码过程。
(完整word版)C语言哈夫曼编码、译码器
#include <iostream.h>#include <iomanip.h>#include <string.h>#include <malloc.h>#include <stdio.h>//typedef int TElemType;const int UINT_MAX = 1000;typedef struct{int weight;int parent, lchild, rchild;} HTNode, *HuffmanTree;typedef char **HuffmanCode;//-----------全局变量-----------------------HuffmanTree HT;HuffmanCode HC;int *w, i, j, n;char *z;int flag = 0;int numb = 0;// -----------------求赫夫曼编码-----------------------int min(HuffmanTree t, int i){// 函数void select()调用int j, flag;int k = UINT_MAX; // 取k为不小于可能的值for (j = 1; j <= i; j++)if (t[j].weight < k && t[j].parent == 0)k = t[j].weight, flag = j;t[flag].parent = 1;return flag;}//--------------------slect函数----------------------void select(HuffmanTree t, int i, int &s1, int &s2){// s1为最小的两个值中序号小的那个int j;s1 = min(t, i);s2 = min(t, i);if (s1 > s2){j = s1;s1 = s2;s2 = j;}}// --------------算法6.12--------------------------void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){// w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC int m, i, s1, s2, start;//unsigned c,f;int c, f;HuffmanTree p;char *cd;if (n <= 1)return ;//检测结点数是否可以构成树m = 2 * n - 1;HT = (HuffmanTree)malloc((m + 1) *sizeof(HTNode)); // 0号单元未用for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w){p->weight = *w;p->parent = 0;p->lchild = 0;p->rchild = 0;}for (; i <= m; ++i, ++p)p->parent = 0;for (i = n + 1; i <= m; ++i)// 建赫夫曼树{// 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 select(HT, i - 1, s1, s2);HT[s1].parent = HT[s2].parent = i;HT[i].lchild = s1;HT[i].rchild = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}// 从叶子到根逆向求每个字符的赫夫曼编码HC = (HuffmanCode)malloc((n + 1) *sizeof(char*));// 分配n个字符编码的头指针向量([0]不用)cd = (char*)malloc(n *sizeof(char)); // 分配求编码的工作空间cd[n - 1] = '\0'; // 编码结束符for (i = 1; i <= n; i++){// 逐个字符求赫夫曼编码start = n - 1; // 编码结束符位置for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)// 从叶子到根逆向求编码if (HT[f].lchild == c)cd[--start] = '0';elsecd[--start] = '1';HC[i] = (char*)malloc((n - start) *sizeof(char));// 为第i个字符编码分配空间strcpy(HC[i], &cd[start]); // 从cd复制编码(串)到HC}free(cd); // 释放工作空间}//--------------初始化赫夫曼链表---------------------------------void Initialization(){flag = 1;int num;int num2;cout << "下面初始化赫夫曼链表" << endl << "数请输入结点的个n:";cin >> num;n = num;w = (int*)malloc(n *sizeof(int));z = (char*)malloc(n *sizeof(char));cout << "\n请依次输入" << n << "个字符(字符型)\n注意:必须以回车结束:" << endl;char base[2];for (i = 0; i < n; i++){cout << "第" << i + 1 << "个字符:" << endl;gets(base);*(z + i) = *base;for (i = 0; i <= n - 1; i++){cout << setw(6) << *(z + i);}cout << "\n请依次输入" << n << "个权值(\n注意:必须以回车结束):" << endl; for (i = 0; i <= n - 1; i++){cout << endl << "第" << i + 1 << "个字符的权值:";cin >> num2;*(w + i) = num2;}HuffmanCoding(HT, HC, w, n);//------------------------打印编码-------------------------------------------cout << "字符对应的编码为:" << endl;for (i = 1; i <= n; i++){//cout<<"字符"<<*(z+i-1)<<"的编码";puts(HC[i]);}//--------------------------将赫夫曼编码写入文件------------------------cout << "下面将赫夫曼编码写入文件" << endl << "...................." << endl; FILE *htmTree;char r[] =' ', '\0'};if ((htmTree = fopen("htmTree.txt", "w")) == NULL){cout << "can not open file" << endl;return ;}fputs(z, htmTree);for (i = 0; i < n + 1; i++){fprintf(htmTree, "%6d", *(w + i));fputs(r, htmTree);}for (i = 1; i <= n; i++){fputs(HC[i], htmTree);fputs(r, htmTree);}fclose(htmTree);cout << "已将字符与对应编码写入根目录下文件htmTree.txt中" << endl << endl; }//---------------------获取报文并写入文件---------------------------------void InputCode()//cout<<"请输入你想要编码的字符"<<endl;FILE *tobetran;char str[100];if ((tobetran = fopen("tobetran.txt", "w")) == NULL){cout << "不能打开文件" << endl;return ;}cout << "请输入你想要编码的字符" << endl;gets(str);fputs(str, tobetran);cout << "获取报文成功" << endl;fclose(tobetran);}//---------------------编码函数---------------------------------void Encoding(){cout << "下面对目录下文件tobetran.txt中的字符进行编码" << endl; FILE *tobetran, *codefile;if ((tobetran = fopen("tobetran.txt", "rb")) == NULL){cout << "不能打开文件" << endl;}if ((codefile = fopen("codefile.txt", "wb")) == NULL) {cout << "不能打开文件" << endl;}char *tran;i = 99;tran = (char*)malloc(100 *sizeof(char));while (i == 99){if (fgets(tran, 100, tobetran) == NULL){cout << "不能打开文件" << endl;break;}for (i = 0; *(tran + i) != '\0'; i++){for (j = 0; j <= n; j++){if (*(z + j - 1) == *(tran + i)){fputs(HC[j], codefile);if (j > n){cout << "字符错误,无法编码!" << endl;break;}}}}}cout << "编码工作完成" << endl << "编码写入目录下的codefile.txt中" << endl << endl;fclose(tobetran);fclose(codefile);free(tran);}//-----------------译码函数---------------------------------void Decoding(){cout << "下面对根目录下文件codefile.txt中的字符进行译码" << endl;FILE *codef, *txtfile;if ((txtfile = fopen("Textfile.txt", "w")) == NULL){cout << "不能打开文件" << endl;}//txtfile=fopen("Textfile.txt","w");if ((codef = fopen("codefile.txt", "r")) == NULL){cout << "不能打开文件" << endl;}//codef=fopen("codefile.txt","r");char *work, *work2, i2;int i4 = 0, i, i3;unsigned long length = 10000;work = (char*)malloc(length *sizeof(char)); fgets(work, length, codef);work2 = (char*)malloc(length *sizeof(char)); i3 = 2 * n - 1;for (i = 0; *(work + i - 1) != '\0'; i++){i2 = *(work + i);if (HT[i3].lchild == 0){*(work2 + i4) = *(z + i3 - 1);i4++;i3 = 2 * n - 1;i--;}else if (i2 == '0')i3 = HT[i3].lchild;i3 = HT[i3].rchild;}*(work2 + i4) = '\0';fputs(work2, txtfile);cout << "译码完成" << endl << "内容写入根目录下的文件txtfile.txt中" << endl << endl;cout << work2;free(work);free(work2);fclose(txtfile);fclose(codef);}//------------------------打印赫夫曼树的函数-----------------------void coprint(HuffmanTree start, HuffmanTree HT){if (start != HT){FILE *TreePrint;if ((TreePrint = fopen("TreePrint.txt", "a")) == NULL){cout << "创建文件失败" << endl;return ;numb++; //该变量为已被声明为全局变量coprint(HT + start->rchild, HT);cout << setw(5 *numb) << start->weight << endl;fprintf(TreePrint, "%d\n", start->weight);coprint(HT + start->lchild, HT);numb--;fclose(TreePrint);}}void Tree_printing(HuffmanTree HT, int w){HuffmanTree p;p = HT + w;cout << "下面打印赫夫曼树" << endl;coprint(p, HT);cout << "打印工作结束" << endl;}//------------------------主函数------------------------------------void main(){char choice;cout << " 赫夫曼编码解码系统" << endl;cout << "1.要初始化赫夫曼链表请输入'i'" << endl;cout << "2.要编码请输入'e'" << endl;cout << "3.要译码请输入'd'" << endl;cout << "4.要打印编码请输入'p'" << endl;cout << "5.要打印赫夫曼树请输入't'" << endl;cout << "6.要离开请输入'q'" << endl;// if(flag==0)cout<<"\n请先初始化赫夫曼链表,输入'i'"<<endl; cin >> choice;switch (choice){case 'i':Initialization();break;case 'w':InputCode();break;case 'e':Encoding();break;Decoding();break;case 't':Tree_printing(HT, 2 *n - 1);break;case 'q':default:cout << "input error" << endl;}}free(z);free(w);free(HT);}运行结果:赫夫曼编码解码系统1.要初始化赫夫曼链表请输入'i'2.要编码请输入'e'3.要译码请输入'd'4.要打印编码请输入'p'5.要打印赫夫曼树请输入't'6.要离开请输入'q'下面初始化赫夫曼链表数请输入结点的个n:8请依次输入8个字符(字符型)注意:必须以回车结束:第1个字符:a第2个字符:b第3个字符:c第4个字符:d第5个字符:e第6个字符:f第7个字符:g第8个字符:ha b c d e f g h 请依次输入8个权值(注意:必须以回车结束):第1个字符的权值:5第2个字符的权值:29第3个字符的权值:7第4个字符的权值:8第5个字符的权值:14第6个字符的权值:23第7个字符的权值:3第8个字符的权值:11字符对应的编码为:01101011101111110000111010下面将赫夫曼编码写入文件....................已将字符与对应编码写入根目录下文件htmTree.txt中赫夫曼编码解码系统1.要初始化赫夫曼链表请输入'i'2.要编码请输入'e'3.要译码请输入'd'4.要打印编码请输入'p'5.要打印赫夫曼树请输入't'6.要离开请输入'q'i下面初始化赫夫曼链表数请输入结点的个n:27请依次输入27个字符(字符型)注意:必须以回车结束:第1个字符:第2个字符:a第3个字符:b第4个字符:c第5个字符:d第6个字符:第7个字符: f第8个字符: g第9个字符: h第10个字符: i第11个字符: j第12个字符: k第13个字符: l第14个字符: m第15个字符: n第16个字符: o第17个字符: p第19个字符:r第20个字符:s第21个字符:t第22个字符:u第23个字符:v第24个字符:w第25个字符:x第26个字符:y第27个字符:za b c d e f gm n o p q r s t z请依次输入27个权值(第1个字符的权值:186第2个字符的权值:64第3个字符的权值:13第4个字符的权值:22第5个字符的权值:32第6个字符的权值:103第7个字符的权值:21第8个字符的权值:15第9个字符的权值:47第10个字符的权值:57第11个字符的权值:1第12个字符的权值:5第13个字符的权值:32第14个字符的权值:20第15个字符的权值:57第16个字符的权值:63第17个字符的权值:15第18个字符的权值:1第19个字符的权值:48第20个字符的权值:51第21个字符的权值:80第22个字符的权值:23第23个字符的权值:8第24个字符的权值:18第25个字符的权值:1第26个字符的权值:16第27个字符的权值:1字符对应的编码为: 11010101001000001010110010111110100101000001101111011100111101101011111111101111000100110111101110100100011111000011111101011110011110111101001111111011111下面将赫夫曼编码写入文件....................已将字符与对应编码写入根目录下文件htmTree.txt中。
c语言实现哈夫曼编码
c语言实现哈夫曼编码一、概述哈夫曼编码是一种常用的无损数据压缩算法,其原理是基于字符的出现概率来构建编码表,从而实现数据的压缩。
本教程将介绍如何使用C语言实现哈夫曼编码算法。
二、算法原理哈夫曼编码算法的基本思想是:将字符按照出现概率的大小进行排序,然后构建一个树状结构,每个节点代表一个字符,节点的左子节点和右子节点分别代表字符的频率较小和较大的分支。
最终,通过路径进行解码即可还原出原始数据。
三、实现步骤1.统计字符频率,构建字符频率表;2.按照频率从小到大排序,构建哈夫曼树;3.根据哈夫曼树构建编码表,将字符映射为编码;4.实现解码过程,还原出原始数据。
四、代码实现下面是一个简单的C语言实现哈夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<ctype.h>#defineMAX_CHARS1000//最大字符数#defineMAX_FREQ100//最大频率值//字符频率表intfreq[MAX_CHARS+1];//构建哈夫曼树函数structnode{charch;intfreq;structnode*left,*right;};structnode*build_huffman_tree(intfreq[],intn){structnode*root=(structnode*)malloc(sizeof(structnode));root->freq=freq[0];//根节点的频率为最小的频率值root->left=root->right=NULL;for(inti=1;i<=n;i++){if(freq[i]==root->freq){//如果当前字符的频率与根节点的频率相同,则添加到左子树或右子树中if(i<n&&freq[i]==freq[i+1]){//如果当前字符的频率与下一个字符的频率相同,则添加到左子树中root->left=(structnode*)malloc(sizeof(structnode));root->left->ch=i+'a';//左子节点的字符为当前字符的下一个字符(假设所有字符都是小写字母)root->left->left=root->left->right=NULL;//左子树为空树i++;//跳过下一个字符,继续寻找下一个不同的频率值}else{//如果当前字符的频率与下一个字符的频率不相同,则添加到右子树中root->right=(structnode*)malloc(sizeof(structnode));root->right->ch=i+'a';//右子节点的字符为当前字符root->right->left=root->right->right=NULL;//右子树为空树}}elseif(freq[i]<root->freq){//如果当前字符的频率小于根节点的频率,则添加到左子树中root->left=(structnode*)malloc(sizeof(structnode));root->left->ch=i+'a';//左子节点的字符为当前字符的下一个字符(假设所有字符都是小写字母)root->left->left=build_huffman_tree(freq,i);//子树的左孩子为当前字符构成的右子树节点和子哈夫曼树的左孩子合并得到的左孩子节点,这个步骤继续调用本函数,从而继续构建右子树的下一级和再下一级,最终实现三级左右子的嵌套式结构树型哈夫曼编码)注:这种思想并非标准的哈夫曼编码)//子树的右孩子为当前节点(即当前字符)构成的右子树节点和子哈夫曼树的右孩子节点合并得到的右孩子节点)注:这种思想并非标准的哈夫曼编码)//子树的左孩子为空树)注:这种思想并非标准的哈夫曼编码)根节点的频率是根节点的最小频率值(因为构建哈夫曼树的过程中总是从最小的频率值开始)根节点的左子树是构建出的三级左右子的嵌套式结构树型哈夫曼编码根节点的右子树为空树(假设所有字符都是小写字母)在添加左子节点后需要调用本函数构建右子树的下一级和再下一级来得到三级左右子的嵌套式结构。
C语言—哈夫曼树编码器和译码器
C语言—哈夫曼树编码器和译码器#include <stdio.h>#include "stdlib.h"#define MAXBIT 10#define MAXVALUE 10000#define MAXLEAF 100#define MAXNODE MAXLEAF*2-1//定义哈夫曼树编码类型typedef struct {char bit[MAXBIT]; //存放叶子结点字符编码过后的二进制编码int start; //存放叶子结点二进制编码在bit[]数组里的起始数组位置int length; //存放二进制编码的位数}HFMCode;//定义哈夫曼树结点类型typedef struct {char data; //编码字符int weight; //哈夫曼树结点的权值int parent; //哈夫曼树结点的父结点int lchild; //哈夫曼树结点的左孩子int rchild; //哈夫曼树结点的右孩子}HFMNode;//构造哈夫曼树void createHFMTree(HFMNode hfmnode[MAXNODE],int n){int i,j,m1,m2,x1,x2;for(i=0;i<2*n-1;i++){hfmnode[i].weight=0;hfmnode[i].parent=-1;hfmnode[i].lchild=-1;hfmnode[i].rchild=-1;}for(i=0;i<n;i++){getchar();printf("请输入第%d片叶子的字符:",i+1);scanf("%c",&hfmnode[i].data);printf("请输入第%d片叶子的权重:",i+1);scanf("%d",&hfmnode[i].weight);}for(i=0;i<n-1;i++){m1=m2=MAXVALUE; //m1和m2分别用来存储叶子结点权值的最小值和次小值x1=x2=0; //x1和x2分别用来存储m1和m2的位置for(j=0;j<n+i;j++){if(hfmnode[j].weight<m1&&hfmnode[j].parent==-1){m2=m1;x2=x1;m1=hfmnode[j].weight;x1=j;}else if(hfmnode[j].weight<m2&&hfmnode[j].parent==-1){m2=hfmnode[j].weight;x2=j;}}hfmnode[x1].parent=n+i;hfmnode[x2].parent=n+i;hfmnode[n+i].weight=hfmnode[x1].weight+hfmnode[x2].weight;//父结点的权重是左孩子和右孩子的权重之和hfmnode[n+i].lchild=x1;hfmnode[n+i].rchild=x2;}}//显示叶子的编码字符和编码字符对应的二进制编码void showCode(HFMCode hfmcode[MAXNODE],HFMNodehfmnode[MAXNODE],int n){int i,j,k,c,p;HFMCode cd;for(i=0;i<n;i++){hfmcode[i].length=0; hfmcode[i].start=0;k=hfmcode[i].start;cd.start=n-1;c=i;p=hfmnode[c].parent;while(p!=-1){if(hfmnode[p].lchild==c) {cd.bit[cd.start]=0;}else{cd.bit[cd.start]=1;}cd.start--;c=p;p=hfmnode[c].parent;}for(j=cd.start+1;j<n;j++) {hfmcode[i].bit[k]=cd.bit[j];k++;hfmcode[i].length++; //length计算存放的二进制编码的位数}}for(i=0;i<n;i++) //输出每个叶子节点的哈夫曼编码{printf("第%d片叶子的编码是:",i+1);printf("%c\t",hfmnode[i].data);for(j=hfmcode[i].start;j<hfmcode[i].length;j++){printf("%d",hfmcode[i].bit[j]);}printf("\n");}}//输入字符串,得到二进制编码void compileCode(char str[],int n,HFMCode hfmcode[MAXLEAF],HFMNode hfmnode[MAXNODE]){int i,j,k;for(i=0;str[i]!='\0';i++){for(j=0;j<n;j++){if(str[i]==hfmnode[j].data){for(k=hfmcode[j].start;k<hfmcode[j].length;k++){printf("%d",hfmcode[j].bit[k]);}}}}printf("\n\n");}//输入二进制编码得到字符串void decompileCode(char num[],int n,HFMCode hfmcode[MAXLEAF],HFMNode hfmnode[MAXNODE]){int i,j;j=2*n-2; //哈夫曼树根结点的位置for(i=0;num[i]!='\0';i++){if(num[i]=='0'){j=hfmnode[j].lchild;}else if(num[i]=='1'){j=hfmnode[j].rchild;}if(j<n) //j大于等于n表示的都是除叶子结点以外的哈夫曼树结点{printf("%c",hfmnode[j].data);j=2*n-2;}}printf("\n");}//主函数void main(){HFMNode hfmnode[MAXNODE];HFMCode hfmcode[MAXLEAF];char str[100]; //存放输入的需要编译的的字符串char num[100]; //存放输入的需要编译的二进制字符串int n; //输入的叶子结点数//哈夫曼编码器printf("-----------------哈弗曼编码器------------------\n"); printf("请输入叶子结点数:");scanf("%d",&n);createHFMTree(hfmnode,n);showCode(hfmcode,hfmnode,n);//哈夫曼译码器printf("-----------------哈夫曼译码器------------------\n"); printf("请输入编码:\n");scanf("%s",str);compileCode(str,n,hfmcode,hfmnode);printf("请输入需要译码的数字:\n");scanf("%s",num);decompileCode(num,n,hfmcode,hfmnode); }。
数据结构之哈夫曼编码和解码C源代码
玩转算法与数据结构之哈夫曼编码和解码—HIT2000鲁天伟二叉树的一个很重要的应用是生成哈夫曼树来完成哈夫曼编码和解码。
哈夫曼树:假设一个字符串中只有'A','B','C','D','E','F','G'这七个字符,这七个字符出现的权值(也就是出现次数)是3,5,7,6,5,9,8。
我们就以这个字符串作为样本,来进行字符编码,将字符映射成一串二进制码(比如’A’对应000,‘B’对应001),那么最终整个字符串将被编码成一长串二进制码。
我们生成哈夫曼树来进行编码,如下图1所展示就是哈夫曼树最终的模样。
哈夫曼树算法:使用字符数组{'A','B','C','D','E','F','G'},对就权值数组{3,5,7,6,5,9,8};1、我们先从权值数组左边开始,找到数组中未打过使用标记的最小数p和次小数q,以p+q作父结点,p作为左子结点,q作为右子结点。
原则是右子结点权值大于或等于左子结点权值。
把p和q的权值数组位置打标记已使用过,父结点p+q作为新的权值加入到权值数组尾部。
(此例中第一次执行p=3和q=5,对应字符‘A’和‘B’。
把这两个数相加得8,形成新的结点作为父结点。
3作为左子结点,5作为右子结点。
把3和5的权值数组位置打标记已使用过。
父结点权值8作为新的权值加入到权值数组尾部。
)2、重复步骤1,如果叶子结点有N个,那么进行N-1次合并,可以建成哈夫曼树。
图表 1 哈夫曼树编码算法:如上图1所示,所有的字符都出现在叶子结点的位置,从根结点开始遍历,查找每个叶子结点的字符,根到每个叶子结点只有一条路,从根开始向左走标0,向右走标1,根据查找路线,我们可以得出每个叶子结点字符的二进制编码串。
数据结构哈夫曼编码译码c语言
数据结构哈夫曼编码译码c语言哈夫曼编码是一种经典的数据压缩算法。
这种算法可以根据数据中出现频率最高的字符生成一个种类较少的编码表,然后用这个编码表来对数据进行编码,从而达到压缩数据的效果。
哈夫曼编码的核心是生成编码表,生成编码表的过程包括以下几个步骤:1. 统计字符出现频率。
遍历一遍数据,统计每个字符出现的次数。
2. 创建哈夫曼树。
将每个字符出现的次数作为权值,构造一棵哈夫曼树。
构造哈夫曼树需要用到一种优先队列。
3. 生成编码表。
对哈夫曼树进行遍历,当遇到一个叶子节点时,将它的路径上的所有节点转换成一个编码,这个编码就是该节点代表的字符的哈夫曼编码。
4. 对数据进行编码。
按照编码表,将原始数据中的每个字符都替换成对应的哈夫曼编码,得到压缩数据。
哈夫曼编码的解码操作相对简单,只需要根据编码表将每个哈夫曼编码转换成它代表的字符,再将这些字符拼接起来就可以得到原始数据。
以下是C语言实现哈夫曼编码和译码的例子:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_NODE 100typedef struct node {char data;int freq;int parent, lchild, rchild;} Node;int nodes_num;Node* nodes;void build_huffman_tree() {int i, j, min1, min2;for (i = 0; i < nodes_num - 1; i++) {min1 = min2 = -1;for (j = 0; j < nodes_num + i; j++) {if (nodes[j].parent == -1) {if (min1 == -1 || nodes[j].freq < nodes[min1].freq) {min2 = min1;min1 = j;} else if (min2 == -1 || nodes[j].freq < nodes[min2].freq) { min2 = j;}}}nodes[min1].parent = nodes_num + i;nodes[min2].parent = nodes_num + i;nodes[nodes_num + i].lchild = min1;nodes[nodes_num + i].rchild = min2;nodes[nodes_num + i].freq = nodes[min1].freq + nodes[min2].freq;}}nodes_num = 0;nodes = (Node*)malloc(MAX_NODE * sizeof(Node));for (i = 0; i < MAX_NODE; i++) {nodes[i].freq = nodes[i].parent = -1;nodes[i].lchild = nodes[i].rchild = -1;}build_huffman_tree();codes_num = 0;codes = (Code*)malloc(nodes_num * sizeof(Code));printf("src: %s\n", src);return 0;}```上述代码中,我们使用结构体来表示哈夫曼树的节点,其中包括该节点的权值(即字符出现的次数)、父节点、左右孩子节点等信息。
数据结构实验哈夫曼树及哈夫曼编码c语言
数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的1. 理解哈夫曼树及哈夫曼编码的概念和原理;2. 掌握C语言中哈夫曼树及哈夫曼编码的实现方法;3. 分析和讨论哈夫曼编码在实际应用中的优势和不足。
二、实验内容和步骤1. 哈夫曼树的构建1.1 通过C语言实现哈夫曼树的构建算法;1.2 输入一组权值,按哈夫曼树构建规则生成哈夫曼树;1.3 输出生成的哈夫曼树结构,并进行可视化展示。
2. 哈夫曼编码的实现2.1 设计哈夫曼编码的实现算法;2.2 对指定字符集进行编码,生成哈夫曼编码表;2.3 对给定字符串进行哈夫曼编码,并输出编码结果。
三、实验过程及结果1. 哈夫曼树的构建在C语言中,通过定义结构体和递归算法实现了哈夫曼树的构建。
根据输入的权值,依次选择权值最小的两个节点构建新的父节点,直至构建完成整棵哈夫曼树。
通过调试和可视化展示,确认了程序正确实现了哈夫曼树的构建。
2. 哈夫曼编码的实现经过分析和设计,利用哈夫曼树的特点实现了哈夫曼编码的算法。
根据生成的哈夫曼树,递归地生成字符对应的哈夫曼编码,并输出编码结果。
对指定的字符串进行了编码测试,验证了哈夫曼编码的正确性和有效性。
四、实验结果分析1. 哈夫曼编码在数据传输和存储中具有较高的压缩效率和可靠性,能够有效减少数据传输量和存储空间;2. 哈夫曼树及哈夫曼编码在通信领域、数据压缩和加密等方面有着广泛的应用和重要意义;3. 在实际应用中,哈夫曼编码的构建和解码算法需要较大的时间和空间复杂度,对于大规模数据的处理存在一定的局限性。
五、实验总结通过本次实验,深入理解了哈夫曼树及哈夫曼编码的理论知识,并掌握了C语言中实现哈夫曼树及哈夫曼编码的方法。
对哈夫曼编码在实际应用中的优势和局限性有了更深入的认识,这对今后的学习和工作有着积极的意义。
六、参考文献1. 《数据结构(C语言版)》,严蔚敏赵现军著,清华大学出版社,2012年;2. 《算法导论》,Thomas H. Cormen 等著,机械工业出版社,2006年。
用c++写哈夫曼编码
用c++写哈夫曼编码以下是使用C++实现哈夫曼编码的示例代码:c复制代码#include<iostream>#include<queue>#include<string>#include<vector>using namespace std;struct TreeNode {char data;int freq;TreeNode *left, *right;TreeNode(char data, int freq) : data(data), freq(freq), left(NULL), right(NULL) {}};struct cmp {bool operator()(const TreeNode *a, const TreeNode *b) {return a->freq > b->freq;}};void printCodes(TreeNode *root, string code) {if (root == NULL) {return;}if (root->left == NULL && root->right == NULL) {cout << root->data << ": " << code << endl;return;}printCodes(root->left, code + "0");printCodes(root->right, code + "1");}void buildHuffmanTree(const vector<char>& data, const vector<int>& freq) { priority_queue<TreeNode*, vector<TreeNode*>, cmp> pq;for (int i = 0; i < data.size(); i++) {pq.push(new TreeNode(data[i], freq[i]));}while (pq.size() > 1) {TreeNode *left = pq.top();pq.pop();TreeNode *right = pq.top();pq.pop();TreeNode *top = new TreeNode('$', left->freq + right->freq);top->left = left;top->right = right;pq.push(top);}TreeNode *root = pq.top();pq.pop();printCodes(root, "");}int main() {vector<char> data = {'a', 'b', 'c', 'd', 'e', 'f'};vector<int> freq = {5, 9, 12, 13, 16, 45};buildHuffmanTree(data, freq);return0;}在这个示例中,我们首先定义了一个结构体TreeNode,表示哈夫曼树的节点。
哈夫曼编码生成程序
#include <stdio.h>#include <stdlib.h>#define MaxSize 50typedef struct{char c; //代码;int w; //代码权值;char code[MaxSize]; //代码的Huffman编码;}HuffCode[MaxSize];typedef struct{int Weight; //权值;int LChild,RChild,Parent;}HTNode,HuffTree[MaxSize];//===================================================================== ===========void HuffmanTree(HuffTree HT,int length,HuffCode hc); //生成Huffman树;void SelectHTNode(HuffTree HT,int n,int *min1,int *min2); //查找最小和次小序号;void HuffmanCode(HuffTree HT,int len,HuffCode hc); //生成Huffman编码;//===================================================================== ===========int main(void){HuffTree HT; //Huffman树;HuffCode HC; //Huffman编码;int i,len;printf("<<<< Huffman编码生成程序>>>>\t\tby Haroldi.\n\n\n\n\n\n");printf("\n输入代码数量:"); scanf("%d",&len); system("cls");printf("代码数量:%2d\n\n",len);printf("输入代码及权值(e.g.: \"a16[回车]\" ):\n");for(i=1;i <= len;i++){while(getchar() != '\n') NULL;printf("No.%2d:",i);HC[i].c = getchar();scanf("%d",&HC[i].w);}HuffmanTree(HT,len,HC);HuffmanCode(HT,len,HC);printf("\n输出Huffman编码:\n");for(i = 1;i<=len;i++){printf("\n %c :",HC[i].c);puts(HC[i].code);}//测试Huffman树结构;printf("\n\n输出Huffman树结构:");system("pause");printf("\nHT[i]:\t权值\t双亲\t左孩子\t右孩子\n");for(i = 1;i<2*len;i++){if(i <= len) printf("(%c)",HC[i].c);printf("%2d,\t %2d,\t %2d,\t %2d,\t %2d\n",i,HT[i].Weight,HT[i].Parent,HT[i].LChild,HT[i].RChild);}return 0;}void HuffmanTree(HuffTree HT,int length,HuffCode hc) //Huffman树初始化;{int i,min1,min2;HT[0].Weight = 65535;for(i = 1;i <= length;i++){HT[i].Weight = hc[i].w;HT[i].LChild = HT[i].RChild = HT[i].Parent = -1;}for(;i < 2*length;i++) //i初值= length+1;{HT[i].LChild = HT[i].RChild = HT[i].Parent = -1;}for(i = length+1;i < 2*length;i++){SelectHTNode(HT,i,&min1,&min2);HT[min1].Parent = i;HT[min2].Parent = i;HT[i].LChild = min1;HT[i].RChild = min2;HT[i].Weight = HT[min1].Weight + HT[min2].Weight;}}//===================================================================== ===========void SelectHTNode(HuffTree HT,int n,int *min1,int *min2) //查找最小和次小序号;{int i;*min1 = *min2 = 0;for(i = 1;i < n;i++){if(HT[i].Parent == -1){if(HT[*min1].Weight >= HT[i].Weight){*min2 = *min1;*min1 = i;}else if(HT[*min2].Weight > HT[i].Weight) *min2 = i;}}}//===================================================================== ===========void HuffmanCode(HuffTree HT,int len,HuffCode hc) //生成Huffman编码;{int i,j,tc,Stack[MaxSize],top = -1;char flag[MaxSize];HTNode th;for(i = 1;i <= len;i++){top = -1; //栈初始化;j = 0; //hc[i].code串首位置偏移;th = HT[i]; //当前结点th;tc = i; //当前结点标记tc;while(th.Parent != -1){ //当前结点th双亲P入栈,由P的孩子是th,确定flag;确定下次结点标记tc;Stack[++top] = th.Parent;if(HT[th.Parent].LChild == tc) {flag[top] = 'L'; tc = th.Parent;}if(HT[th.Parent].RChild == tc) {flag[top] = 'R'; tc = th.Parent;}th = HT[Stack[top]]; //下一结点;}while(top != -1){if(flag[top] == 'L') hc[i].code[j++] ='0';else hc[i].code[j++] ='1';Stack[top--]; //出栈;}hc[i].code[j] ='\0'; //当前串结束;}}哈夫曼树在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN)树和哈夫曼编码。
哈夫曼编码的C语言实现
哈夫曼编码的C语言实现一、大致思路输入信源符号的概率,构造哈夫曼树,从叶子结点到根结点进行编码二、编码实现#include <stdio.h>#define n 7 //leaf number#define m 2*n-1 //all numbertypedef struct{char ch;double weight;int left;int right;int parent;}Node;typedef struct{char ch;int codeis[50];int start;}Code;void HuffmanTree (Node node[],int number){int i,j,x1=0,x2=0;double m1,m2;for(i=0;i<n-1;i++){ //loop n-1m1=m2=1; //least probability p<1//m1 最小 m2第二小for(j=0;j<n+i;j++){if(node[j].weight <m1 && node[j].parent ==-1){m2=m1;x2=x1;m1=node[j].weight;x1=j;} //是最小的else if(node[j].weight <m2 &&node[j].parent ==-1){m2=node[j].weight;x2=j;}} //找结点node[x1].parent = number+i;node[x2].parent = number+i;node[number+i].weight = node[x1].weight + node[x2].weight;node[number+i].left = x1;node[number+i].right = x2;}//end for}int main(int argc, const char * argv[]) {double x[n]={0};printf("请输入%d个符号的概率",n);int i;for(i=0;i<n;i++){scanf("%lf",&x[i]);}Node node[2*n-1]; // 2*len-1 is the number of all nodefor(i=0;i<2*n-1;i++){node[i].weight = 0;node[i].left = -1;node[i].right = -1;node[i].parent = -1;} //initializefor(i=0;i<n;i++){node[i].weight=x[i];}Code code[n],tempcode; //save the code of leafHuffmanTree(node,n); //创建好了哈夫曼树//编码int p,c,j=0;for(i=0;i<n;i++){c=i;tempcode.start = n-1;p=node[c].parent;while(p!=-1){if(node[p].left == c)tempcode.codeis[tempcode.start] = 1; elsetempcode.codeis[tempcode.start] = 0; tempcode.start--;c=p;p=node[c].parent;} //end whilefor(j=tempcode.start+1;j<n;j++){code[i].codeis[j]=tempcode.codeis[j];}//保存下载刚才的结果code[i].start = tempcode.start;} //end forfor (i=0;i<n;i++){for (j=code[i].start+1;j<n;j++){printf("%d",code[i].codeis[j]);}printf("\n");}getchar();return 0;}三、总结1.创建了哈夫曼树,n是叶子结点数。
c语言如何实现哈夫曼编码与译码
c语言如何实现哈夫曼编码与译码
在电报通讯中,电文是以二进制的0、1序列传送的。
字符集中的字符的使用频率是不同的(比如e和t的使用较之q和z要频繁得多),哈夫曼编码可以使得编码的总长最短,从而相同的位长可以传送更多的信息。
本程序以下面的字符及使用频率为例:
首先建立哈夫曼树:
下面是哈夫曼编码的存储结构:
程序清单如下:
#include《stdio.h》
#define n 5 //叶子数目
#define m (2*n-1)//结点总数
#define maxval 10000.0
#define maxsize 100 //哈夫曼编码的最大位数
typedef struct
{
char ch;
float weight;
int lchild,rchild,parent;
}hufmtree;
typedef struct
{
char bits[n]; //位串
int start; //编码在位串中的起始位置
char ch; //字符
}codetype;。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
long min1=888888,888888;
int j;
for(j=0;j<=i;j++)
{ if(T[j].parent==-1)
{ if(min1>T[j].weight)
{ min1=T[j].weight;
*p1=j;
}
}
}
for(j=0;j<=i;j++)
printf("\n ");
}
{
int i;
printf("\n请输入共有多少个权值(小于100):");
scanf("%d",&n);
for(i=0;i<2*n-1;i++)
{ T[i].weight=0;
T[i].lchild=-1;
T[i].rchild=-1;
T[i].parent=-1;
{
printf("(%d,%d),(%d,%d)\n",T[i].weight,T[i].lchild,T[i].weight,T[i].rchild);
break;
}
}
void hfnode(HT T,int i,int j)
{
j=T[i].parent;
if(T[i].rchild==T[i].weight)
{ if(T[j].parent==-1)
{ if(min2>T[j].weight&&j!=(*p1))
{ min2=T[j].weight;
*p2=j;
}
}
}
}
void CreatHFMT(HT T)
{
int i,p1,p2;
InitHFMT(T);
}
}
void InputWeight(HT T)
{
int w,i;
for(i=0;i<n;i++)
{
printf("输入第%d个权值:",i+1);
scanf("%d",&w);getchar();
T[i].weight=w;
}
}
void SelectMin(HT T,int i,int *p1,int *p2)
#include<stdio.h>
#define MAXLEN 100
typedef struct
{ int weight;
int lchild,rchild,parent;
}HTNode;
typedef HTNode HT[MAXLEN];
int n;
void InitHFMT(HT T)
InputWeight(T);
for(i=n;i<2*n-1;i++)
{ SelectMin(T,i-1,&p1,&p2);
T[p1].parent=T[p2].parent=i;
T[i].lchild=T[p1].weight;
T[i].rchild=T[p2].weight;
printf("1");
else
printf("0");
if(T[j].parent!=-1)
i=j,hfnode(T,i,j);
}
void huffmannode(HT T)
{
int i,j,a;
printf("\n输入的权值的对应哈夫曼编码:");
for(i=0;i<n;i++)
T[i].weight=T[p1].weight+T[p2].weight;
}
}
void PrintHFMT(HT T)
{
int i;
printf("\n哈夫曼树的各边显示:\n");
for(i=0;i<2*n-1;i++)
while(T[i].lchild!=-1)
{ j=0;
a=i;
printf("\n%i的编码为:",T[i].weight);
hfnode(T,i,j);
i=a;
}
}
void main()
{ HT HT;
CreatHFMT(HT);
PrintHFMT(HT);
huffmannode(HT);