哈弗曼编码和译码.cpp

<span style="color:#6600cc;">#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct{
     char a;//记录对应字符
     int weight;//权值
     int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char * *HuffmanCode;//动态分配数组存储哈夫曼编码表

void Select(HuffmanTree HT,int m,int *s1)//选择双亲节点为0且权值最小的节点
{int i,j,k,h,a,b;
    for(a=1;a<=m;a++)
        if(HT[a].parent==0)
             break;
    i=a;k=a;
 for(;i<=m;i++)
    if(HT[i].weight<HT[k].weight&&HT[i].parent==0)
           k=i;
    *s1=k;
}

//求哈夫曼编码
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,char *s,int n)
{
 int m,i,start,s1,s2,c,f;
 char *cd;
 HuffmanTree p;
 if(n<=1) return;
 m=2*n-1;
 *HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
 for(i=1;i<=n;i++,w++,s++)
  {(*HT)[i].weight=*w;//叶子节点的权值不变
  (*HT)[i].a=*s;
  (*HT)[i].parent=0,(*HT)[i].lchild=0,(*HT)[i].rchild=0;}
    for(i=n+1;i<=m;i++)
        (*HT)[i].parent=0;//parent初始化
 for(i=n+1;i<=m;++i){//建哈夫曼树
  Select(*HT,i-1,&s1);(*HT)[s1].parent=i;
        Select(*HT,i-1,&s2);/*选择parent为0且权值最小的两个节
        点分别作为s1和s2*/
  (*HT)[s2].parent=i;
  (*HT)[i].lchild=s1;(*HT)[i].rchild=s2;(*HT)[i].a='0';
  (*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
 }
 //从叶子到根逆向求每个字符的哈夫曼编码
 (*HC)=(HuffmanCode)malloc((n+1)*sizeof(char *));/*分配n个
 字符编码的头指针向量*/
 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));/*为第i
 个字符编码分配空间*/
 strcpy((*HC)[i],&cd[start]);//从cd复制编码到HC
 }
}

//解码
void HUffmanDising(HuffmanTree HT,int n){
  FILE *fp3,*fp4;HuffmanTree p;
  int c,m;char b;
  p=HT;m=2*n-1;*p=HT[m];
  fp3=fopen("File3.txt","r");
  fp4=fopen("File4.txt","w");
  if(fp3!=NULL)
 {fscanf(fp3,"%c",&b);/*读入一个字符,如果为‘0’遍历左子树,
    为‘1’遍历右子树,遇到叶子节点输出*/
  while(!feof(fp3)){
           if(b=='0'){
                if((*p).a=='0')
                c=(*p).lchild,(*p)=HT[c];//指向左孩子
               }
            if(b=='1'){
                if((*p).a=='0')
                 c=(*p).rchild,(*p)=HT[c];//指向右孩子
               }
            if((*p).a!='0')  fprintf(fp4,"%c",(*p).a),//叶子节点输出
            (*p)=HT[m];//指向根结点
            if(!feof(fp3)) fscanf(fp3,"%c",&b);
 }
  }
   fclose(fp4);fclose(fp3);
}

void PrintfBitree(HuffmanTree *HT,HuffmanCode *HC,int n)
{int i,j=1,m=n*2-1;
 printf("序号   字符   权值   双亲   左孩子    右孩子  哈夫曼码\n");
  for(i=1;i<=m;i++,j++)
    {printf(" %02d     %c      %2d     %2d    %2d        %2d",i,(*HT)[i].a,(*HT)[i].weight,(*HT)[i].parent,(*HT)[i].lchild,(*HT)[i].rchild);
    if(j<=n) printf("       %s ",(*HC)[j]);
    printf("\n");}
}

int main()
{   int a[258],n,c[100],i,j,k,z;char e;char m[100],b;
    HuffmanTree HT;HuffmanCode HC;
 FILE *fp1,*fp2,*fp3,*fp4;
 for(i=0;i<=256;i++)
   a[i]=0;//读入一个字符,在数组a中的位置由其ASCII吗决定
    for(i=0;i<100;i++)
         c[i]=0;//记录每一个字符的权值
 fp1=fopen("File1.txt","r");
 if(fp1!=NULL)
 {
  while(!feof(fp1)){
   fscanf(fp1,"%c",&e);
  if(!feof(fp1)) a[(int)e]++;//统计出现次数
  }
 }
 fclose(fp1);
 for(i=0,j=0;i<=256;i++)
   if(a[i]!=0)
   c[j++]=a[i],m[j-1]=(char)i;//将字符存到数组m中
 HuffmanCoding(&HT,&HC,c,m,j);
 fp1=fopen("File1.txt","r");
 fp2=fopen("File2.txt","w");
 fp3=fopen("File3.txt","w+");
 if(fp1!=NULL)//在文件二语三中输出文件一中内容所对应的哈夫曼吗
 {
  while(!feof(fp1)){
   fscanf(fp1,"%c",&e);
   if(feof(fp1)) break;
       for(i=0;i<j;i++)
          if(m[i]==e) break;
          fprintf(fp2,"%s",HC[i+1]);
           fprintf(fp3,"%s",HC[i+1]);
  }
 }
 fclose(fp1);
 fclose(fp2);
 fclose(fp3);
 PrintfBitree(&HT,&HC,j);//输出相关信息
    HUffmanDising(HT,j);//解码函数
}

</span>

哈弗曼编码和译码.cpp,布布扣,bubuko.com

时间: 2024-12-10 10:27:37

哈弗曼编码和译码.cpp的相关文章

数据结构实验2(设计哈弗曼编码和译码系统)

设计一个哈弗曼编码和译码系统, 要求如下: B--建树:读入字符集和各字符频度,建立哈夫曼树. T--遍历:先序和中序遍历二叉树. E--生成编码:根据已建成的哈夫曼树,产生各个字符的哈夫曼编码. C--编码:输入由字符集中字符组成的任意字符串,利用已生成的哈夫曼编码进行编码,显示编码结果,并将输入的字符串及其编码结果分别保存在磁盘文件textfile.txt和codefile.txt中. D--译码:读入codefile.txt,利用已建成的哈夫曼树进行译码,并将译码结果存入磁盘文件resul

哈弗曼编码及译码

路径长度:从树的一个结点到另一个结点之间边的条数. 树的路径长度:从树根到每个叶子结点之间路径长度之和. 带权树的路径长度:每个叶子结点带有权值,树根到叶子结点的路径长度乘以该叶子结点的权值之和. 哈弗曼树:带权树的路径长度最小的树,又称作最小二叉树和最优二叉树. 哈夫曼树的构造过程: 1.      根据给定的n个带权的结点,构成含有n棵二叉树(每个结点是一棵树)的集合,该树的左右子树均为空. 2.      从含有n棵子树集合中找出两棵权值最小的树最为左右子树构成一个新的二叉树. 3.   

【算法设计与分析】8、哈弗曼编码,贪心算法实现

写这个玩意,我也是深深地感觉到自己数据结构的薄弱,可笑的是我一直以为学的还可以,结果一个堆结构就干了我半个月,才懂个大概= =,我也是醉了 BinaryTree.h二叉树的实现 /** * 书本:<算法分析与设计> * 功能:这个头文件是为了实现二叉树 * 文件:BinaryTree.h * 时间:2014年12月15日18:35:51 * 作者:cutter_point */ // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |

哈弗曼编码译码系统

/**********************************************************************                                        * 学校:黄淮学院                                                         * 院系:信息工程学院                                                     * 年级专业:网络

利用哈弗曼编码进行压缩

// sZipDemo.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "HuffmanTree.cpp" #include "sZip.h" #include <fstream> #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { char str1[100

用哈弗曼编码实现文件压缩和解压

放假了把这个改一下,发现确实用单字节压缩的压缩率要高一些,暂时没去管为什么,不过放假静下心来写的话确实效率高很多. 新版详见:http://blog.csdn.net/tookkke/article/details/50575103 今天脑洞大开突然想写一下,明明都要考试了,唉,怎么就管不住这手啊  总之呢,就是根据每种编码的出现频率把等长的编码换成变长的,据说理论上压缩比率是比较高的,可是为什么经检验我这个大部分时候压缩出来的比源文件还大呢? 哈弗曼编码的时候要先做一颗字典树,查找的时候就按照

uva 10954 Add All(哈弗曼编码)

这道题我一开始想错了,这么简单的题都wa了两发...我往贪心上面想了,每次都找一个最小的数相加,结果就是 排序后直接往后加,还在那纳闷为何出错...其实这道题是哈弗曼编码问题,简直是模板题目,就是每次找两个最 小的结点求和后把他们的和放到节点中去,把这两个点删除...用的multiset,其实和set容器差不多,就是可 以存放重复的元素... 代码: #include<iostream> #include<cstdio> #include<cstdlib> #inclu

java实现哈弗曼编码

根据输入的各个叶节点的权值,构建一棵最优树,根据最小带全路径,确定由0,1组成的哈弗曼编码. 首先在一个封装类TNode中构建一棵树的元素,比如权值,左节点,右节点,同时在TNode类中构建了哈弗曼编码值,以及判断节点是否为叶子节点 package 霍夫曼编码; /** * * @author luckid * @version 2014_10_11 * */ /** * 定义Huffman编码的节点 */ public class TNode { /** * * @param weight *

哈弗曼编码解码

#lang scheme ( define nil '() ) ( define ( make-leaf symbol weight ) ( list 'leaf symbol weight ) ) ( define ( leaf? obj ) ( eq? ( car obj ) 'leaf ) ) ( define ( symbol-leaf x ) ( cadr x ) ) ( define ( weight-leaf x ) ( caddr x ) ) ( define ( make-co