C语言哈夫曼编码代码
c语言实现哈夫曼算法
c语言实现哈夫曼算法以下是C语言实现哈夫曼算法的示例代码:```cinclude <>include <>include <>// 定义哈夫曼树节点结构体typedef struct HuffmanNode {char data; // 节点存储的数据int freq; // 节点出现的频率struct HuffmanNode left, right; // 左右子树指针} HuffmanNode;// 定义创建哈夫曼树函数HuffmanNode createNode(char data, int freq) { HuffmanNode node =(HuffmanNode)malloc(sizeof(HuffmanNode));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 定义比较函数,用于按照频率从小到大排序int compare(const void a, const void b) {return ((HuffmanNode)b)->freq - ((HuffmanNode)a)->freq; }// 定义构建哈夫曼树函数HuffmanNode buildHuffmanTree(char data[], int freq[], int size) { if (size == 1) {return createNode(data[0], freq[0]);} else {HuffmanNode nodes[size]; // 存储所有节点指针的数组for (int i = 0; i < size; i++) {nodes[i] = createNode(data[i], freq[i]);}qsort(nodes, size, sizeof(HuffmanNode), compare); // 按频率从小到大排序return mergeNodes(nodes, size); // 合并两个最小的节点,直到只剩下一个节点}}// 定义合并两个最小节点函数HuffmanNode mergeNodes(HuffmanNode nodes[], int size) {if (size == 0) return NULL; // 空节点返回NULL指针if (size == 1) return nodes[0]; // 只剩下一个节点直接返回该节点指针 HuffmanNode root = createNode('$', nodes[0]->freq + nodes[1]->freq); // 创建根节点,频率为左右子树频率之和root->left = mergeNodes(nodes+1, size-1); // 递归合并剩余节点,左子树指向左子树数组中除第一个节点外的所有节点指针,右子树指向右子树数组中除最后一个节点外的所有节点指针return root; // 返回根节点指针}```。
哈夫曼编码器-源代码
#include <stdio.h>#include <string.h>#include <stdlib.h>typedef struct{char data;int weight;int parent;int lchild;int rchild;}HTNode;HTNode ht[30];typedef struct{char cd[30];int start;}HCode;HCode hcd[30];void CreateHT( HTNode ht[] , int n ) {int i , k , lnode, rnode ;int min1 , min2 ;for ( i = 0 ; i < 2*n-1 ; i++ ){ht[i].parent = ht[i].lchild = ht[i].rchild = 0;}for ( i = n ; i < 2*n-1 ; i++ ){min1 = min2 = 32767;lnode = rnode = 0;for ( k=0 ; k <= i-1; k++)if ( ht[k].parent == 0) {if (ht[k].weight < min1){min2 = min1;min1 = ht[k].weight;rnode = lnode;lnode = k;}else if ( ht[k].weight < min2){min2 = ht[k].weight;rnode = k;}}ht[lnode].parent = i;ht[rnode].parent = i;ht[i].weight = ht[lnode].weight + ht[rnode].weight;ht[i].lchild = lnode;ht[i].rchild = rnode;}}void CreateHCode( HTNode ht[] , HCode hcd[] , int n ){int i , f , c;HCode hc;for( i = 0 ; i < n; i++){hc.start = n;c = i;f = ht[i].parent;while (f != 0){if( ht[f].lchild == c){hc.cd[hc.start--] = '0';}else{hc.cd[hc.start--] = '1';}c=f ;f=ht[f].parent;}hc.start++;hcd[i] = hc;}}void CodeInput(int n,HTNode ht[]){int i;char ch[30];scanf( "%s" , ch );for ( i=0 ; i<n ; i++ ){scanf( "%ld" , &ht[i].weight );}printf("######################################- \n"); }void CodeOutput( int n , HCode hcd[] ){int i , j ;printf (" 所有字符的哈弗曼编码为:");for ( i = 0 ; i < n ; i++ ){for( j=hcd[i].start ; j<=n ; j++ ){printf( "%lc" , hcd[i].cd[j] );}}printf("\n");for ( i=0 ; i<n ; i++ ){printf( " 序号%d : " , i );for( j = hcd[i].start ; j <= n ; j++ ){printf( "%lc" , hcd[i].cd[j] );}printf( "\n" );}}void save( int n ){int i ;FILE *fp;if( ( fp = fopen ( "c:\\data.txt" , "w" ) ) == NULL ) {printf( " can't open this file !!! " ) ;exit(0) ;}else{for ( i = 1 ; i <= n ; i++ ){fprintf( fp , " %ld ", ht[i].weight );}printf(" You have saved it successful !!!");}fclose (fp) ;}void main(){ int num ;char flag ='y';while( flag == 'y' || flag == 'Y' ){system( "cls" );printf(" ################################ \n");printf(" 欢迎使用哈夫曼编码系统\n ");printf(" ################################ \n");printf(" ######## 1. 生成哈夫曼树#########\n");printf(" ######### 2. 哈夫曼编码######### \n");printf(" ######### 3.哈夫曼权值存储######### \n");printf(" ######## 4. 退出########\n");printf(" ##############################\n");printf(" 请选择操作类型( 1 - 4 ) : " );scanf( " %d" , &num );printf("############################################ \n");switch(num){case 1 :int n , i ;printf(" 请输入要输入的字符数量n为: ");if((scanf(" %ld", &n ))&&(n!=0)){printf("\n 请输入%d 个字符和%d 个对应权值<先将所有字符输入再输对应权值> \n 在此输入: " , n , n );CodeInput( n , ht );CreateHT( ht , n );printf(" 对应的权值为:\n");for( i = 0 ; i < n ; i++ ){printf( " %d : %ld " , i , ht[i].weight );if((i+1) % 4 == 0){printf("\n");}}}printf("\n######################################- \n");break;case 2 :CreateHCode( ht , hcd , n );CodeOutput( n , hcd );printf("##############################################-");break;case 3 :save(n);printf("#######################################");break;case 4 :printf("############# **感谢使用本程序** ############### \n ");exit(1);printf("########################################");break;default :printf(" Error ! You must put the number between <1 -- 4> ");printf("\n#####################################\n");}printf(" \n 继续或退出(y or n) : ");getchar() ;flag=getchar();}}。
c语言哈夫曼树的构造及编码
c语言哈夫曼树的构造及编码一、哈夫曼树概述哈夫曼树是一种特殊的二叉树,它的构建基于贪心算法。
它的主要应用是在数据压缩和编码中,可以将频率高的字符用较短的编码表示,从而减小数据存储和传输时所需的空间和时间。
二、哈夫曼树的构造1. 哈夫曼树的定义哈夫曼树是一棵带权路径长度最短的二叉树。
带权路径长度是指所有叶子节点到根节点之间路径长度与其权值乘积之和。
2. 构造步骤(1) 将待编码字符按照出现频率从小到大排序。
(2) 取出两个权值最小的节点作为左右子节点,构建一棵新的二叉树。
(3) 将新构建的二叉树加入到原来排序后队列中。
(4) 重复上述步骤,直到队列只剩下一个节点,该节点即为哈夫曼树的根节点。
3. C语言代码实现以下代码实现了一个简单版哈夫曼树构造函数:```ctypedef struct TreeNode {int weight; // 权重值struct TreeNode *leftChild; // 左子节点指针struct TreeNode *rightChild; // 右子节点指针} TreeNode;// 构造哈夫曼树函数TreeNode* createHuffmanTree(int* weights, int n) {// 根据权值数组构建节点队列,每个节点都是一棵单独的二叉树TreeNode** nodes = (TreeNode**)malloc(sizeof(TreeNode*) * n);for (int i = 0; i < n; i++) {nodes[i] = (TreeNode*)malloc(sizeof(TreeNode));nodes[i]->weight = weights[i];nodes[i]->leftChild = NULL;nodes[i]->rightChild = NULL;}// 构建哈夫曼树while (n > 1) {int minIndex1 = -1, minIndex2 = -1;for (int i = 0; i < n; i++) {if (nodes[i] != NULL) {if (minIndex1 == -1 || nodes[i]->weight < nodes[minIndex1]->weight) {minIndex2 = minIndex1;minIndex1 = i;} else if (minIndex2 == -1 || nodes[i]->weight < nodes[minIndex2]->weight) {minIndex2 = i;}}}TreeNode* newNode =(TreeNode*)malloc(sizeof(TreeNode));newNode->weight = nodes[minIndex1]->weight + nodes[minIndex2]->weight;newNode->leftChild = nodes[minIndex1];newNode->rightChild = nodes[minIndex2];// 将新构建的二叉树加入到原来排序后队列中nodes[minIndex1] = newNode;nodes[minIndex2] = NULL;n--;}return nodes[minIndex1];}```三、哈夫曼编码1. 哈夫曼编码的定义哈夫曼编码是一种前缀编码方式,它将每个字符的编码表示为二进制串。
哈夫曼编码程序代码
#include<iostream.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fstream.h>typedef struct{char ch;int weight;int parent,lchild,rchild;}htnode,*hfmtree;typedef char **hfmcode;void Select(hfmtree &HT,int a,int *p1,int *p2){int i,j,x,y;for(j=1;j<=a;++j){if(HT[j].parent==0){x=j;break;}}for(i=j+1;i<=a;++i){if(HT[i].weight<HT[x].weight&&HT[i].parent==0){x=i;}}for(j=1;j<=a;++j) {if(HT[j].parent==0&&x!=j){y=j;break;}}for(i=j+1;i<=a;++i){if(HT[i].weight<HT[y].weight&&HT[i].parent==0&&x!=i){y=i;}}if(x>y){*p1=y;*p2=x;}else{*p1=x;*p2=y;}}void hfmcoding(hfmtree &HT,hfmcode &HC,int n) {int i,start,c,f,m,w;int p1,p2;char *cd,z;if(n<=1){return;}m=2*n-1;HT=(hfmtree)malloc((m+1)*sizeof(htnode));for(i=1;i<=n;++i){printf("请输入第%d字符信息和权值:",i);scanf("%c%d",&z,&w);while(getchar()!='\n'){continue;}HT[i].ch=z;HT[i].weight=w;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for(;i<=m;++i){HT[i].ch='0';HT[i].weight=0;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for(i=n+1;i<=m;++i){Select(HT,i-1,&p1,&p2);HT[p1].parent=i;HT[p2].parent=i;HT[i].lchild=p1;HT[i].rchild=p2;HT[i].weight=HT[p1].weight+HT[p2].weight;}HC=(hfmcode)malloc((n+1)*sizeof(char *));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';}else{cd[--start]='1';}}HC[i]=(char*)malloc((n-start)*sizeof(char));strcpy(HC[i],&cd[start]);}free(cd);}int main(){char code[100],h[100],hl[100];int n,i,j,k,l;ifstream input_file;ofstream output_file;char choice,str[100];hfmtree HT;hfmcode HC;cout<<"\n";while(choice!='Q'&&choice!='q'){cout<<" "<<"*************************赫夫曼编码/译码器*************************\n";cout<<" "<<"I.Init"<<" "<<"E.Encoding"<<" "<<"D.Decoding"<<" "<<"Q.Exit\n";cout<<"请输入您要操作的步骤:";cin>>choice;if(choice=='I'||choice=='i'){cout<<"请输入字符个数:";cin>>n;hfmcoding(HT,HC,n);for(i=1;i<=n;++i){cout<<HT[i].ch<<":"<<HC[i]<<endl;}output_file.open("hfmTree.txt");if(!output_file){cout<<"can't oen file!"<<endl;return 1;}for(i=1;i<=n;i++){output_file<<"("<<HT[i].ch<<HC[i]<<")";}output_file.close();cout<<"赫夫曼树已经创建完毕,并且已经放入hfmTree.txt文件中!"<<endl; }else if(choice=='E'||choice=='e'){printf("请输入字符:");gets(str);output_file.open("ToBeTran.txt");if(!output_file){cout<<"can't oen file!"<<endl;return 1;}output_file<<str<<endl;output_file.close();output_file.open("CodeFile.txt");if(!output_file){cout<<"can't oen file!"<<endl;return 1;}for(i=0;i<strlen(str);i++){for(j=0;j<=n;++j){if(HT[j].ch==str[i]){output_file<<HC[j];break;}}}output_file.close();cout<<"\n";cout<<"编码完毕,并且已经存入CodeFile.txt文件!\n";input_file.open("CodeFile.txt");if(!input_file){cout<<"can't oen file!"<<endl;return 1;}input_file>>code;cout<<"编码码值为:"<<code<<endl;input_file.close();}else if(choice=='D'||choice=='d'){input_file.open("CodeFile.txt");if(!input_file){cout<<"can't oen file!"<<endl;return 1;}input_file>>h;input_file.close();output_file.open("Textfile.txt");if(!output_file){cout<<"can't oen file!"<<endl;return 1;}k=0;while(h[k]!='\0') {for(i=1;i<=n;i++){l=k;for(j=0;j<strlen(HC[i]);j++,l++){hl[j]=h[l];}hl[j]='\0';if(strcmp(HC[i],hl)==0){output_file<<HT[i].ch;k=k+strlen(HC[i]);break;}}}output_file.close();input_file.open("Textfile.txt");if(!input_file){cout<<"can't oen file!"<<endl;return 1;}input_file>>h;cout<<h<<endl;input_file.close();cout<<"译码结束,字符已经存入Textfile.txt文件中!"<<endl;}else if(choice=='Q'||choice=='q') \{exit(0);}else{cout<<"您没有输入正确的步骤,请重新输入!"<<endl;}cout<<endl;}return 0;}。
哈夫曼编码代码
哈夫曼编码代码哈夫曼编码代码 1因为哈夫曼树的特点是:叶子结点权值越大的,离根越近。
又因为构造不等长编码的原则是:字符使用频率越高,编码越短,故采用哈夫曼树进行编码可以得到最优前缀编码。
约定左分支标记为0, 右分支标记为 1哈夫曼编码代码 2为不浪费存储空间,动态分配一个长度为n(字符编码长度一定小于n) 的一维数组cd, 用来临时存放当前正在求解的第i 个字符的编码,当第i个字符的编码求解完毕后,根据数组cd的字符串长度分配HC[i]的空间,然后将数组cd中的编码复制到HC[i]中。
依照上一篇文章的哈夫曼树:哈夫曼编码表HC:注意:由于哈夫曼树不唯一,故哈夫曼编码也不唯一。
代码如下:#include<stdio.h>#include<iostream>typedefstruct{int weight;int parent, lchild,rchild;}HTNode,*HuffmanTree;voidSelect(HuffmanTree&HT,int n,int&s1,int&s2){int min;for(int i =1; i <= n; i++){if(HT[i].parent ==0){min = i;break;}}for(int i =1; i <= n;i++){if(HT[i].parent ==0){if(HT[i].weight <HT[min].weight){min = i;}}}s1 = min;for(int i =1; i <= n;i++){if(HT[i].parent ==0&& i != s1){min = i;break;}}for(int i =1; i <= n;i++){if(HT[i].parent ==0&& i != s1){if(HT[i].weight < HT[min].weight){min = i;}}}s2 = min;}voidprintln(HuffmanTree &HT,intm){printf("==============================\n");for(inti =1; i <= m; i++){printf("%d, ", i);printf("%d ", HT[i].weight);printf("%d ", HT[i].parent);printf("%d ", HT[i].lchild);printf("%d \n",HT[i].rchild);printf("---------------------------\n");}}voidCreateHuffmanTree(HuffmanTree &HT,intn,int*ht){int i, m =2* n -1, s1, s2;if(n <=1)return;HT =new HTNode[m +1];for(i =1; i <= m;++i){HT[i].parent =0;HT[i].lchild =0;HT[i].rchild =0;}for(i =1; i <= n;++i){HT[i].weight = ht[i -1];}printf("\nHT的初态\n");println(HT, m);for(int i = n +1; i <=m;++i){Select(HT, i -1, s1, 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("\nHT的终态\n");println(HT, m);}typedefchar**HuffmanCode;char*cd;intstart;voidCreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC,int n){int i, c, f;HC =newchar*[n +1];cd =newchar[n];cd[n -1]='\0';for(i =1; i <= n;++i){start = n -1;c = i;f = HT[i].parent;while(f !=0){if(HT[f].lchild == c) cd[--start]='0';else cd[--start]='1';c = f;f = HT[f].parent;}HC[i]=newchar[n -start];strcpy(HC[i],&cd[start]);printf("第%d组--->", i);for(int j = start; j <= n -1;++j){printf("%c ",cd[j]);}printf("\n");}delete cd;}intmain(){HuffmanTree HT;HuffmanCode HC;int n =8;intht[8]={5,29,7,8,14,23,3,11};CreateHuffmanTree(HT, n, ht);CreatHuffmanCode(HT, HC, n);}运行结果:。
哈夫曼树及哈夫曼编码的算法实现c语言
哈夫曼树及哈夫曼编码的算法实现c语言1.引言1.1 概述哈夫曼树及哈夫曼编码是数据压缩和编码中常用的重要算法。
哈夫曼树由大卫·哈夫曼于1952年提出,用于根据字符出现的频率构建一种最优的前缀编码方式。
而哈夫曼编码则是根据哈夫曼树构建的编码表将字符进行编码的过程。
在现代通信和计算机领域,数据传输和存储中往往需要大量的空间。
为了有效利用有限的资源,减少数据的存储和传输成本,数据压缩成为一个重要的技术。
而哈夫曼树及哈夫曼编码正是数据压缩中常用的技术之一。
哈夫曼树的概念及原理是基于字符的频率和概率进行构建的。
在哈夫曼树中,字符出现频率越高的节点越接近根节点,出现频率越低的节点离根节点越远。
这种构建方式保证了哈夫曼树的最优性,即最小化编码的总长度。
哈夫曼编码的算法实现是根据哈夫曼树构建的编码表进行的。
编码表中,每个字符都与一段二进制编码相对应。
在进行数据压缩和解压缩时,通过查表的方式将字符转化为相应的二进制编码,或将二进制编码解析为原始字符。
本文旨在介绍哈夫曼树及哈夫曼编码的概念和原理,并通过C语言实现算法。
通过深入理解哈夫曼树及哈夫曼编码的实现过程,可以更好地理解数据压缩和编码的原理,为后续的研究和应用提供基础。
接下来,我们将首先介绍哈夫曼树的概念和原理,然后详细讲解哈夫曼编码的算法实现。
最后,我们将总结哈夫曼树及哈夫曼编码的重要性,并提出对哈夫曼树和哈夫曼编码进一步研究的方向。
让我们一起深入探索哈夫曼树及哈夫曼编码的奥秘吧!1.2 文章结构文章结构部分的内容可以包括以下内容:文章结构部分主要介绍了本文的组织结构和各个章节的内容概述,以帮助读者更好地理解全文的逻辑结构和内容安排。
首先,本文包括引言、正文和结论三个部分。
引言部分主要对哈夫曼树及哈夫曼编码的算法实现进行了概述,包括相关的概念、原理和目的。
正文部分则深入介绍了哈夫曼树的概念和原理,以及哈夫曼编码的算法实现。
最后,结论部分对本文的主要内容进行了总结,并提出了对哈夫曼树和哈夫曼编码的进一步研究方向。
哈夫曼编码完整版
//哈夫曼编码不唯一!!!!!//只有当哈夫曼树建好之后编码才固定!!!#include<stdio.h>#include<string.h>#include<stdlib.h>typedef struct{int weight;int parent,Lchild,Rchlid;}HamNode,*HamTree;typedef char* *HamCode;void select(HamTree *ht,int n,int *s1,int *s2) {int k= 0,temp= 0;for(int i=1;i<= n;i++)if( (*ht)[i].parent == 0){k=(*ht)[i].weight;break;}for(i=1;i<= n;i++){if( (*ht)[i].parent == 0){if( k>= (*ht)[i].weight ){k= (*ht)[i].weight;(*s1)= i;}}}for(i=1;i<= n ;i++)if( (*ht)[i].parent == 0){if(i==(*s1))continue;k=(*ht)[i].weight;break;}for(i=1;i<= n ;i++){if( (*ht)[i].parent == 0 && i!= (*s1)){if( k>= (*ht)[i].weight ){k= (*ht)[i].weight;(*s2)= i;}}}}void CrtTree(HamTree *ht, HamCode *hc,int *w,int n) {int m= 0,s1= 0,s2= 0,start= 0,c= 0,p= 0;char *cd= NULL;m=2*n-1;(*ht)=(HamTree)malloc( (m+1)* sizeof( HamNode)); for (int i=1;i<= n; i++){(*ht)[i].weight= w[i];(*ht)[i].parent= 0;(*ht)[i].Lchild= 0;(*ht)[i].Rchlid= 0;}for (i=n+1; i<=m ;i++){(*ht)[i].weight= 0;(*ht)[i].parent= 0;(*ht)[i].Lchild= 0;(*ht)[i].Rchlid= 0;}for(i=n+1 ;i<=m ;i++){select(ht,i-1,&s1,&s2);(*ht)[s1].parent=i;(*ht)[s2].parent=i;(*ht)[i].Lchild=s1;(*ht)[i].Rchlid=s2;(*ht)[i].weight= (*ht)[s1].weight+ (*ht)[s2].weight; }*hc= (HamCode)malloc((n+1)* sizeof(char * ));cd= (char *)malloc(n* sizeof(char));cd[n-1]= '\0';for (i= 1;i<=n ;i++ ){start= n-1;for(c= i,p=(*ht)[i].parent ;p!= 0 ;c= p,p= (*ht)[p].parent) if( (*ht)[p].Lchild== c)cd[--start]= '0';elsecd[--start]= '1';(*hc)[i]= (char *)malloc( (n-start)*sizeof(char) );strcpy( (*hc)[i], &cd[start]);}free(cd);}void visit( HamCode *hc ,int n){for(int i=1;i<=n ;i++){printf("\n%s", (*hc)[i]);}}#define N 7void main(){HamTree ht;HamCode hc;int w[N+1];printf("请输入权值:\n");for(int i=1;i<= N;i++){printf("请输入权值[%d]:\n",i);scanf("%d", &w[i]);}CrtTree(&ht, &hc,w,N);visit(&hc,N);}。
哈夫曼树的构造c语言代码
哈夫曼树的构造c语言代码哈夫曼树是一种特殊的二叉树,常被用于数据压缩中。
它的构造过程非常重要,接下来我将用c语言展示如何构造哈夫曼树。
首先,我们需要定义一个结构体作为节点:```struct Node{int weight;//权重int parent;//父节点在数组中的下标int lchild;//左子节点在数组中的下标int rchild;//右子节点在数组中的下标};```然后,我们需要读入数据,计算每个数据的权重,随后用一个数组存储节点信息:```int n;//数据个数int W[maxn];//存储每个数据的权重Node tree[maxn*2-1];//哈夫曼树```接下来,我们需要编写一个函数用来选择权值最小的两个节点,然后将它们合并成一个节点。
```int select_min(Node*tree,int n){int res=-1;int min=INT_MAX;for(int i=0;i<n;i++){if(tree[i].parent!=-1)continue;//跳过已经合并的节点if(tree[i].weight<min){min=tree[i].weight;res=i;}}return res;}void merge_node(Node*tree,int a,int b,int i){tree[a].parent=i;tree[b].parent=i;tree[i].weight=tree[a].weight+tree[b].weight;tree[i].lchild=a;tree[i].rchild=b;}```接下来,我们就可以开始构造哈夫曼树了。
我们先初始化每个节点,将它们都看成一个独立的树,然后选择最小的两个节点进行合并,直到最后只剩下一个树为止。
```void build_tree(Node*tree,int n,int*W){for(int i=0;i<n;i++){tree[i].weight=W[i];tree[i].parent=-1;tree[i].lchild=-1;tree[i].rchild=-1;}for(int i=n;i<(n<<1)-1;i++) {int a=select_min(tree,i);int b=select_min(tree,i);merge_node(tree,a,b,i);}}```最后,我们可以调用build_tree函数来构造哈夫曼树。
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语言实现哈夫曼编码的示例代码:```cinclude <>include <>include <>define MAX_TREE_HT 100struct MinHeapNode {char data;unsigned freq;struct MinHeapNode left, right;};struct MinHeap {unsigned size;unsigned capacity;struct MinHeapNode array;};struct MinHeapNode newNode(char data, unsigned freq) {struct MinHeapNode temp = (structMinHeapNode)malloc(sizeof(struct MinHeapNode));temp->left = temp->right = NULL;temp->data = data;temp->freq = freq;return temp;}struct MinHeap createMinHeap(unsigned capacity) {struct MinHeap minHeap = (struct MinHeap)malloc(sizeof(struct MinHeap));minHeap->size = 0;minHeap->capacity = capacity;minHeap->array = (struct MinHeapNode)malloc(minHeap->capacity sizeof(struct MinHeapNode));return minHeap;}void swapMinHeapNode(struct MinHeapNode a, struct MinHeapNode b) {struct MinHeapNode t = a;a = b;b = t;}void minHeapify(struct MinHeap minHeap, int idx) {int smallest = idx;int left = 2 idx + 1;int right = 2 idx + 2;if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) {smallest = left;}if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) {smallest = right;}if (smallest != idx) {swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);minHeapify(minHeap, smallest);}}int isSizeOne(struct MinHeap minHeap) {return (minHeap->size == 1);}void insertMinHeap(struct MinHeap minHeap, struct MinHeapNode minHeapNode) {minHeap->size++;int i = minHeap->size - 1;while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {minHeap->array[i] = minHeap->array[(i - 1) / 2];i = (i - 1) / 2;}minHeap->array[i] = minHeapNode;}struct MinHeapNode extractMin(struct MinHeap minHeap) { struct MinHeapNode root = minHeap->array[0];minHeap->array[0] = minHeap->array[minHeap->size - 1]; --minHeap->size;minHeapify(minHeap, 0);return root;}void buildMinHeap(struct MinHeap minHeap) {int n = minHeap->size - 1;int i;for (i = (n - 1) / 2; i >= 0; --i) {minHeapify(minHeap, i);}}void printArr(int arr[], int n) {int i;for (i = 0; i < n; ++i) {printf("%d", arr[i]);if (i < n - 1) {printf(" ");} else {printf("\n");}}}int isLeaf(struct MinHeapNode root) {return !(root->left) && !(root->right);}void printCodes(struct MinHeapNode root, int arr[], int top) {if (root->left) {arr[top] = 0; // left branch -> 0 in binary tree representation.! So first bit of code for root will be '0'! So, '0' is the prefix for all left branches! Therefore, '。
哈夫曼编码与解码C语言知识讲解
哈夫曼编码与解码C语言#include "stdio.h" /*I/O函数*/#include"stdlib.h" /*其他库函数声明*/int num;/*记录结点数*/int codenum=0;/*已经获得的编码个数*/char filename[20]=""; /*存储文件名*/typedef struct /*哈夫曼结点存储结构*/{char ch; /*结点字符*/int w; /*结点权值*/int lchild,rchild; /*左右孩子的数组下标*/}HafuNode,*HafuTree;HafuTree ht;/*声明一个指向树结点到指针*/typedef struct{char ch; /*叶子结点字符*/char codestr[20]; /*字符编码*/}HafuCode;HafuCode code[27];/*用于存放对应字符到哈夫曼编码*/void InitHafuArry(){ /*导入文件计算权值,生成只含有叶子结点的HafuNode数组*/int j,i,k;HafuNode tmpht;FILE *fp; /*定义一指向打开文件的指针*/char ch;/*用于存储一个字母*/char location[30]="D:\\";ht=(HafuTree)malloc(53*sizeof(HafuNode)); /*为哈夫曼数分配内存空间*/ if(ht==NULL) return ;for(i=0;i<53;i++) /*初始化所以的数据单元,每个单元自成一棵树*/ {ht[i].w=0; /*权值初始化为0*/ht[i].lchild=ht[i].rchild=-1; /*左右子为空*/}num=0;printf("File name:");scanf("%s",filename);strcat(location,filename);fp=fopen(location,"r");if(!fp) /*返回1时即存在文件*/{printf("Open Error");return;}while(!feof(fp))/*没到结尾时返回0*/{ch=fgetc(fp);if(ch==' '||ch<='z'&&ch>='a'||ch<='Z'&&ch>='A'){printf("%c",ch);if(ch==' ') ch='#';for(j=0;j<num;j++){if(ht[j].ch==ch){break;}}if(j==num) /*找到新字符*/{ht[num].ch=ch; /*将新字符存入并将权值加1*/ht[num].w++;num++;}else{ht[j].w++; /*将已有字符权值加1*/}}}fclose(fp);printf("\n");for(i=0;i<num;i++) /*对叶子结点按权值进行升序排序*/{k=i;for(j=i+1;j<num;j++){if(ht[j].w<ht[k].w)/*如果后面发现权值比i小的则将其下标记录下来,循环完之后找到最小的*/k=j;}if(k!=i) /*如果权值最小的不是第i个元素则交换位置,将小的放到前面*/ {tmpht=ht[i];ht[i]=ht[k];ht[k]=tmpht;}}}int CreateHafuman(HafuTree ht){ /*在数组ht中生成哈夫曼数,返回根节点下标*/int i,k,j,root;HafuNode hfnode;codenum=0;for(i=0;i<num-1;i++){ /*需生成num-1个结点*/k=2*i+1; /*每次取最前面两个结点,其权值必定最小*/hfnode.w=ht[k].w+ht[k-1].w;hfnode.lchild=k-1;hfnode.rchild=k;for(j=num+i;j>k;j--) /*将新结点插入有序数组中*/{if(ht[j].w>hfnode.w){ht[j+1]=ht[j];}else break;}ht[j]=hfnode;root=j;/*一直跟随新生成的结点,最后新生成的结点为根结点*/}return root;}void GetHafuCode(HafuTree ht,int root,char *codestr){ /*ht是哈夫曼树,root是根结点下标,codestr是来暂时存放叶子结点编码的,一开始为空*/FILE *out;int len,i;FILE *fp; /*定义一指向打开文件的指针*/char ch;/*用于存储一个字母*/char location[30]="D:\\";if(ht[root].lchild==-1){/*遇到递归终点是叶子结点记录叶子结点的哈夫曼编码*/code[codenum].ch=ht[root].ch;strcpy(code[codenum].codestr,codestr);codenum++;}else /*不是终点则继续递归*/{len=strlen(codestr);codestr[len]='0'; /*左分支编码是0*/codestr[len+1]=0; /*向左孩子递归之前调整编码序列末尾加0,相当于加了个‘\0’(null)其十进制值是0,以便下次循环时添加字符,否则会被覆盖掉*/GetHafuCode(ht,ht[root].lchild,codestr); /*向左递归*/len=strlen(codestr);codestr[len-1]='1';/*右分支编码为1,想右递归之前末尾编码0改为1*/ GetHafuCode(ht,ht[root].rchild,codestr); /*向右递归*/len=strlen(codestr);codestr[len-1]=0; /*左右孩子递归返回后,删除编码标记末尾*/}strcat(location,filename);fp=fopen(location,"r");if(!fp) /*返回1时即存在文件*/{printf("Open Error");return;}out=fopen("D:\\code.txt","w+") ;if(!out){/*printf("Write Error"); */return;}while(!feof(fp))/*没到结尾时返回0*/{ch=fgetc(fp); /*再打开源文件,对照哈夫曼编码译成编码*/if(ch==' '||ch<='z'&&ch>='a'||ch<='Z'&&ch>='A'){ if(ch==' ') ch='#'; /*如果是空格就用#号代替*/for(i=0;i<codenum;i++){ /*找到字符所对应到哈夫曼编码*/if(ch==code[i].ch){ /*将所得哈夫曼编码输出到文件中*/fputs(code[i].codestr,out);}}}}fclose(fp); /*关闭打开到两个文件*/fclose(out);}void decodeHafuCode(HafuTree ht,int root) /*将哈夫曼编码翻译为明文*/ {FILE *fp2; /*定义一指向打开文件的指针*/char ch;/*用于存储一个字母*/int curr=root;/*当前结点到下标*/char filename2[20]="";/*获得文件名*/char location[30]="D:\\";printf("File name:");scanf("%s",filename);strcat(location,filename);fp2=fopen(location,"r");if(!fp2) /*返回1时即存在文件*/{printf("Open Error2");return;}printf("Code:");while(!feof(fp2))/*没到结尾时返回0*/{ch=fgetc(fp2);if(ch>='0'&&ch<='1')/*将编码过滤出来*/{printf("%c",ch); /*将密文输出显示*/}}printf("\n");rewind(fp2); /*将文件指针位置定位在开头*/while(!feof(fp2))/*没到结尾时返回0*/{ch=fgetc(fp2);if(ch>='0'&&ch<='1')/*将编码过滤出来*/{if(ch=='0') /*如果为0则当前结点向左走*/{if(ht[curr].lchild!=-1){curr=ht[curr].lchild;/*若有左子则去左子*/}else{curr=root; /*没有则返回根结点*/}}if(ch=='1') /*如果为1则当前结点向右走*/{if(ht[curr].rchild!=-1){curr=ht[curr].rchild;/*若有右子则去右子*/}else{curr=root; /*没有则返回根结点*/}}if(ht[curr].lchild==-1&&ht[curr].rchild==-1)/*若为叶子结点则打印输出*/ {printf("%c",ht[curr].ch=='#'?' ':ht[curr].ch);curr=root; /*回到根结点继续索引*/}}}fclose(fp2);}void main(){ int root;int i;char codestr[20]="";int control;/*显示菜单可选择编码、译码还是退出*/printf("================Menu==============\n");printf("chose 1:encode\n");printf("chose 2:decode\n");printf("chose 3:exit\n");scanf("%d",&control);while(control!=3) /*只有没有选择退出就一直循环*/{if(control==1) /*选择编码选项*/{FILE *output;char ch;InitHafuArry(); /*初始化结点*/root=CreateHafuman(ht); /*造一棵哈夫曼树*/GetHafuCode(ht,root,codestr);/*根据哈夫曼树将明文译成密码*/ printf("Code:");output=fopen("D:\\CODE.TXT","r");if(!output) /*返回1时即存在文件*/{printf("Open Error3");continue;}while(!feof(output))/*没到结尾时返回0*/{ch=fgetc(output);if(ch>='0'&&ch<='1')/*将编码过滤出来*/{printf("%c",ch); /*将密文输出显示*/}}fclose(output);/*将打开文件关闭*/}if(control==2) /*如果选择译码,则调用译码函数*/{decodeHafuCode(ht,root);}if(control==3) /*如果选择3则退出程序*/{exit(0);}/*若没有退出则继续打印菜单提示供选择*/printf("\n\n================Menu==============\n"); printf("chose 1:encode\n");printf("chose 2:decode\n");printf("chose 3:exit\n");getch();scanf("%d",&control);}}。
哈夫曼编码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语言为例,介绍如何使用哈夫曼编码方法求出编码和平均码长。
1. 哈夫曼编码原理哈夫曼编码是一种前缀编码(Prefix Codes),即任何字符的编码都不是其他字符编码的前缀。
这种编码方式可以保证编码的唯一性,不会出现歧义。
哈夫曼编码的原理是通过构建哈夫曼树来实现对字符的编码,具体步骤如下:1)统计字符出现的频率,并根据频率构建最小堆或优先队列。
2)从频率最低的两个字符中选择一个根节点,频率之和作为其父节点的频率,将父节点重新插入到最小堆或优先队列中。
3)重复以上步骤,直到最小堆或优先队列中只剩下一个节点,即哈夫曼树的根节点。
4)根据哈夫曼树,得到字符的编码。
从根节点开始,左子树标记为0,右子树标记为1,沿途记录路径上的编码即可。
2. C语言实现哈夫曼编码以下是使用C语言实现哈夫曼编码的伪代码:```c#include <stdio.h>#include <stdlib.h>#include <string.h>// 定义哈夫曼树节点typedef struct Node {char data; // 字符数据int freq; // 字符频率struct Node* left;struct Node* right;} Node;// 创建哈夫曼树节点Node* createNode(char data, int freq) {Node* node = (Node*)malloc(sizeof(Node)); node->data = data;node->freq = freq;node->left = NULL;node->right = NULL;return node;}// 构建哈夫曼树Node* buildHuffmanTree(char* data, int* freq, int size) {// 构建最小堆或优先队列// 构建哈夫曼树}// 生成字符编码void generateHuffmanCode(Node* root, char* code, int depth) { // 生成编码}// 输出字符编码void printHuffmanCode(Node* root) {// 输出编码}// 计算平均码长double calculateAvgCodeLength(Node* root, int depth) {// 计算平均码长}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data) / sizeof(data[0]);Node* root = buildHuffmanTree(data, freq, size);char code[100];generateHuffmanCode(root, code, 0);printHuffmanCode(root);double avgCodeLength = calculateAvgCodeLength(root, 0);return 0;}```以上伪代码实现了使用C语言构建哈夫曼树、生成字符编码和计算平均码长的过程。
哈夫曼编码详解(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;```上述的示例代码实现了一个简单的哈夫曼编码和解码过程。
霍夫曼编码c语言
霍夫曼编码c语言霍夫曼编码是一种用于数据压缩的编码技术,它通过重新组织数据中的符号来减少传输或存储数据所需的比特数。
在C语言中实现霍夫曼编码需要掌握数据结构、算法和编码理论的基础知识。
一、霍夫曼编码原理霍夫曼编码的基本原理是利用符号出现的频率来构建一个最优的编码方案,使得编码后的比特率最小。
在霍夫曼图中,每个符号对应一个唯一的路径,路径上的节点表示该符号可能出现的概率。
通过选择概率较大的路径,可以获得较短的编码,从而实现数据压缩。
二、C语言实现霍夫曼编码以下是一个简单的C语言实现霍夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<stdbool.h>//定义霍夫曼树节点结构体typedefstructNode{charsymbol;//符号structNode*left;//左子节点structNode*right;//右子节点intfrequency;//符号频率}Node;//构建霍夫曼树函数Node*buildHuffmanTree(intfrequencies[],intn){//合并相同频率的节点for(inti=0;i<n-1;i++){for(intj=i+1;j<n;j++){if(frequencies[i]==frequencies[j]){ Node*temp=frequencies[i]; frequencies[i]=frequencies[j]; frequencies[j]=temp;mergeNodes(frequencies,i,j);}}}//构建霍夫曼树Node*root=NULL;for(inti=0;i<n;i++){if(root==NULL){root=frequencies[i];}else{Node*child=frequencies[i];child->left=root;root->right=child;root=child;}}returnroot;}//合并两个节点的函数voidmergeNodes(intfrequencies[],inti,intj){frequencies[i]=frequencies[j];//合并节点频率frequencies[j]=NULL;//移除多余节点}//输出霍夫曼编码函数voidprintCodes(Node*root,char*codes[],intindex){if(root==NULL){//如果节点为空,输出编码为空字符串printf("%s",codes[index]);return;}elseif(root->left!=NULL){//如果节点左子节点不为空,输出左子节点的编码作为前缀printCodes(root->left,codes,index*2+1);}elseif(root->right!=NULL){//如果节点右子节点不为空,输出右子节点的编码作为前缀(可用作解码的辅助信息)printCodes(root->right,codes,index*2+2);}else{//如果节点为叶子节点,输出节点的符号作为编码的前缀(去掉重复前缀)并输出当前编码的长度(作为该符号的出现次数)intfreq=root->frequency;//当前符号频率(去掉重复前缀后的频率)while(codes[index]!='\0'){//将前缀放入已使用的字符串数组中以供其他叶子节点使用,重复前缀使用最少的次数(去除重复)并输出当前编码长度和符号本身作为输出结果index--;//指针向后移动一位,直到指针指向'\0'字符为止(已使用的字符串数组)或遇到NULL字符为止(编码数组结束)并返回编码长度和符号本身作为输出结果供其他叶子节点使用和参考。
哈夫曼编解码完整c程序代码
字符
A
B
C
D
E
F
G
H
I
J
K
Lห้องสมุดไป่ตู้
M
频度
186
64
13
22
32
103
21
15
47
57
1
5
32
20
字符
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
频度
57
63
15
1
48
51
80
23
case'Q':break;
}
}while(state!='Q');
}
void menu() //显示菜单函数
{
std::cout<<"===========HuffmanCoding===========\n";
std::cout<<"input \t\t do\n";
std::cout<<"I \t\tInit_HUffTree\n"; //初始化huffmantree
void decoding(int n);
void coding(int n);
void main()
{
int n=0;
menu();
Huff HT;
char state;
do
{
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语言
一、需求分析目前,进行快速远距离通信的主要手段是电报,即将需传送的文字转化成由二级制的字符组成的字符串.例如,假设需传送的电文为“ABACCDA",它只有4种字符,只需两个字符的串,便可以分辨。
假设A 、B 、C 、D 、的编码分别为00,01,10和11,则上述7个字符的电文便为“00010010101100”,总长14位,对方接受时,可按二位一分进行译码。
当然,在传送电文时,希望总长尽可能地短.如果对每个字符设计长度不等的编码,且让电文中出现次数较多的字符采用尽可能短的编码,则传送电文的总长便可减少。
如果设计A 、B 、C 、D 的编码分别为0,00,1,01,则上述7个字符的电文可转换成总长为9的字符串“000011010"。
但是,这样的电文无法翻译,例如传送过去的字符串中前4个字符的字串“0000”就可以有很多种译法,或是“AAAA ”或者“BB ”,或者“ABA ”等.因此,若要设计长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。
然而,如何进行前缀编码就是利用哈夫曼树来做,也就有了现在的哈夫曼编码和译码.二、概要设计利用哈夫曼树编/译码 (一)、建立哈夫曼树 (二)、对哈夫曼树进行编码 (三)、输出对应字符的编码 (四)、译码过程主要代码实现: struct code //结构体的定义 { char a ; int w ; int parent; int lchild; int rchild; };void creation(code *p,int n ,int m ); //建立哈夫曼树 void coding (code *p,int n ); //编码 void display (code *p ,int n ,int m); //输出函数 void translate (char **hc,code *p,int n); //译码三、 详细设计(一)、建立哈夫曼树2 3 4 5 * * * 6 7序号:权值: 1 2 3 4 3 6 10 6 图3-1 图(二)、对哈夫曼树进行编码 主要代码实现: for(c=i,f=p [i ].parent;f!=0;c=f ,f=p [f ]。
数据结构哈夫曼编码译码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;}```上述代码中,我们使用结构体来表示哈夫曼树的节点,其中包括该节点的权值(即字符出现的次数)、父节点、左右孩子节点等信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int m,s1,s2;
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表
void Select(HuffmanTree HT,int n) {
int i,j;
for(i = 1;i <= n;i++)
if(!HT[i].parent){s1 = i;break;}
for(j = i+1;j <= n;j++)
if(!HT[j].parent){s2 = j;break;}
for(i = 1;i <= n;i++)
if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))s1=i; for(j = 1;j <= n;j++)
if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j; }
void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) {
// 算法6.13
// w存放n个字符的权值(均>0),构造哈夫曼树HT,
// 并求出n个字符的哈夫曼编码HC
int i, j;
char *cd;
int p;
int cdlen;
if (n<=1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用
for (i=1; i<=n; i++) { //初始化
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m; i++) { //初始化
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
puts("\n哈夫曼树的构造过程如下所示:");
printf("HT初态:\n 结
点weight parent lchild rchild");
for (i=1; i<=m; i++)
printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,
HT[i].parent,HT[i].lchild, HT[i].rchild);
printf(" 按任意键,继续...");
getchar();
for (i=n+1; i<=m; i++) { // 建哈夫曼树
// 在HT[1..i-1]中选择parent为0且weight最小的两个结点,
// 其序号分别为s1和s2。
Select(HT, i-1);
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("\nselect: s1=%d s2=%d\n", s1, s2);
printf(" 结点weight parent lchild rchild");
for (j=1; j<=i; j++)
printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight,
HT[j].parent,HT[j].lchild, HT[j].rchild);
printf(" 按任意键,继续...");
getchar();
}
//------无栈非递归遍历哈夫曼树,求哈夫曼编码
cd = (char *)malloc(n*sizeof(char)); // 分配求编码的工作空间p = m; cdlen = 0;
for (i=1; i<=m; ++i) // 遍历哈夫曼树时用作结点状态标志HT[i].weight = 0;
while (p) {
if (HT[p].weight==0) { // 向
左
HT[p].weight = 1;
if (HT[p].lchild != 0) { p = HT[p].lchild; cd[c dlen++] ='0'; }
else if (HT[p].rchild == 0) { // 登记叶子
结点的字符的编码
HC[p] = (char *)malloc((cdlen+1) * sizeof(char));
cd[cdlen] ='\0'; strcpy(HC[p], cd); // 复制编码(串)
}
} else if (HT[p].weight==1) { // 向右HT[p].weight = 2;
if (HT[p].rchild != 0) { p = HT[p].rchild; cd[c dlen++] ='1'; }
} else { // HT[p].weight==2,退回退到父结点,编码长度减1
HT[p].weight = 0; p = HT[p].parent; --cdlen;
}
}
} // HuffmanCoding
int main() {
HuffmanTree HT;HuffmanCode *HC;int *w,n,i;
puts("输入结点数:");
scanf("%d",&n);
getchar();
HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode));
w = (int *)malloc(n*sizeof(int));
printf("输入%d个结点的权值\n",n);
for(i = 0;i < n;i++)
scanf("%d",&w[i]);
getchar();
HuffmanCoding(HT,HC,w,n);
puts("\n各结点的哈夫曼编码:");
for(i = 1;i <= n;i++)
printf("%2d(%4d):%s\n",i,w[i-1],HC[i]);
getchar();
}。