赫夫曼编译码器实验报告

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAX 100
#define MAXVALUE 10000

typedef struct{
    char ch;
    int weight,flag;
    int parent,lchild,rchild;
}HTNode;

typedef struct{
    char ch;
    int bit[MAX];
    int start,weight;
}Code;

typedef struct{
    char ch;
    char bit[MAX];
    int weight;
}Coding;

void HaffmanCoding1(int weight[],char ch[],int n,HTNode haffTree[]){
    /**
    生成哈夫曼树的函数1
    */
    int i,j,m1,m2,x1,x2;
    for (i=0;i<2*n-1;i++){
       if(i<n){
           haffTree[i].weight=weight[i];
           haffTree[i].ch=ch[i];
       }
       else haffTree[i].weight=0;
       haffTree[i].parent=-1;
       haffTree[i].flag=0;
       haffTree[i].lchild=-1;
       haffTree[i].rchild=-1;
    }
    for (i=0;i<n-1;i++){
       m1=m2=MAXVALUE;
       x1=x2=0;
       for (j=0;j<n+i;j++){
           if (haffTree[j].weight<m1&&haffTree[j].flag==0){
              m2=m1;
              x2=x1;
              m1=haffTree[j].weight;
              x1=j;
           }
           else if(haffTree[j].weight<m2 && haffTree[j].flag==0){
              m2=haffTree[j].weight;
              x2=j;
           }
       }
       haffTree[x1].parent= n + i;
       haffTree[x2].parent = n + i;
       haffTree[x1].flag = 1;
       haffTree[x2].flag = 1;
       haffTree[n+i].weight = haffTree[x1].weight + haffTree[x2].weight;
       haffTree[n+i].lchild = x1;
       haffTree[n+i].rchild = x2;
    }
    /**
    把哈弗曼树存储到huffman.txt中。
    */
    FILE *fp;
    fp=fopen("huffman.txt","w+");
    printf("%d\n",n);
    fprintf(fp,"%d\n",n);
    for (i=0;i<n;i++)
       fprintf(fp,"%c %d %d %d\n",haffTree[i].ch,haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);
    for (i=n;i<2*n-1;i++)
       fprintf(fp,"%d %d %d\n",haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);
    fclose(fp);
}

void HaffmanCoding2(HTNode haffTree[],int n,Code haffCode[]){
    /**
    生成哈夫曼树的函数2
    */
    Code *cd=( Code *) malloc (sizeof (Code));
    int i,j,child,parent;
    for (i=0; i<n; i++){
       cd->start=n-1;
       cd->weight=haffTree[i].weight;
       cd->ch=haffTree[i].ch;
       child=i;
       parent=haffTree[child].parent;
       while (parent !=-1){
           if (haffTree[parent].lchild==child)
              cd->bit[cd->start]=0;
           else
              cd->bit[cd->start]=1;
           cd->start--;
           child =parent;
           parent=haffTree[child].parent;
       }
       for (j=cd->start+1; j<n; j++)
           haffCode[i].bit[j]=cd->bit[j];
       haffCode [i].start = cd->start+1;
       haffCode [i].weight=cd->weight;
       haffCode [i].ch=cd->ch;
    }
}

void Initialization(int weight[],char ch[]){
    /**
    构造n个字符的赫夫曼编码HC
    */
    FILE *fp;
    int i,j,n;
    char ch1,wj[15];
    printf("系统正在初始化。。。\n请输入字符集大小n:\n");
    scanf("%d",&n);
    HTNode *myHaffTree=(HTNode *)malloc(sizeof (HTNode)*(2*n+1));
    Code *myHaffCode =(Code *)malloc (sizeof (Code)*n);
    for (i=0;i<n;i++){
        printf("请输入字符和权值:\n");
        getchar();
        ch[i] = getchar();
        scanf("%d",&weight[i]);
    }
    HaffmanCoding1(weight,ch,n,myHaffTree);
    HaffmanCoding2(myHaffTree,n,myHaffCode);
    fp=fopen("hfmTree.txt","w+");
    for (i=0;i<n;i++){
       printf("%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);
       fprintf(fp,"%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);
        for ( j=myHaffCode[i].start; j<n; j++){
           printf("%d",myHaffCode[i].bit[j]);
           fprintf(fp,"%d",myHaffCode[i].bit[j]);
       }
            fprintf(fp,"\n");
       printf("\n");
    }
    fclose(fp);
    printf("初始化成功!\n");
}

void Encoding(){
    /**
    利用以建好的哈弗曼树(如不存在,从文件hfmTree中读)
    输入正文进行编码,然后将结果存入文件CodeFile中
    */
    FILE *fp,*fp1,*fp2;
    char zf[500];
    fp=fopen("hfmTree.txt","r");
    Coding ch[100];
    char c;
    int i=0;
    while (feof(fp)==0){
           fscanf(fp,"%s %d %s",&ch[i].ch,&ch[i].weight,&ch[i].bit);
            i++;
    }
    fclose(fp);
    printf("现在进行编码操作。。。\n请输入字符串:\n");
    scanf("%s",zf);
    char ch1[20],ch2[20];
    int j;
    fp2=fopen("CodeFile.txt","w+");
    int len,k;
    len=strlen(zf);
    for (k=0; k<len; k++)
        for (j=0; j<i; j++)
            if (ch[j].ch==zf[k]){
                fprintf(fp2,"%s",ch[j].bit);
                printf("%s",ch[j].bit);
            }
    printf("\n");
    fclose(fp2);
    printf("编码完成!已将结果存入CodeFile.txt中.\n\n");
}

void Decoding(){
    /**
    利用已建好的哈弗曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
    */
    FILE *fp,*fp1;
    fp=fopen("huffman.txt","r");
    int i,n;
    fscanf(fp,"%d",&n);
    HTNode *myHaffTree=(HTNode *)malloc(sizeof (HTNode)*(2*n+1));
    for (i=0;i<n;i++)
        fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    for (i=n;i<2*n-1;i++)
       fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    fclose(fp);
    fp=fopen("CodeFile.txt","r");
    fp1=fopen("TextFile.txt","w+");
    char ch;
    i=2*n-2;
    while (!feof(fp)){
        fscanf(fp,"%c",&ch);
       if (ch=='0') i=myHaffTree[i].lchild;
       if (ch=='1') i=myHaffTree[i].rchild;
       if (i<n){
           printf("%c",myHaffTree[i].ch);
            fprintf(fp1,"%c",myHaffTree[i].ch);
           i=2*n-2;
       }
    }
    printf("\n");
    fprintf(fp1,"\n");
    fclose(fp);
    fclose(fp1);
    printf("译码过程完成!已将结果存入TextFile.txt中.\n\n");
}

void Print(){
    /**
    将文件CodeFile以紧凑格式显示在终端上,每行50个代码
    同时将此字符形式的编码文件写入文件CodePrin中。
    */
    FILE *fp1,*fp2;
    fp1=fopen("CodeFile.txt","r");
    fp2=fopen("CodePrin.txt","w+");
    int count=0;
    char ch;
    while (!feof(fp1)){
        fscanf(fp1,"%c",&ch);
       printf("%c",ch);
       fprintf(fp2,"%c",ch);
       count++;
       if (count==50){
           printf("\n");
           fprintf(fp2,"\n");
            count=0;
       }
    }
    printf("\n");
    fprintf(fp2,"\n");
    fclose(fp1);
    fclose(fp2);
    printf("打印代码过程完成!已将结果存入CodePrin.txt中.\n\n");

}

void PrintTree(HTNode *huf,int n,int p,FILE *fp)
{
    /**
    打印哈弗曼树函数
    树是横向显示的,叶子节点显示字符,非叶子节点显示'@'
    */
    int i;
    if (n==-1)  return;
    PrintTree(huf,huf[n].rchild,p+1,fp);
    for (i=0;i<p;i++){
        printf("   ");
        fprintf(fp,"   ");
    }
    if (p>=0&&huf[n].rchild==-1){
       printf("---");
       printf("%c\n",huf[n].ch);
       fprintf(fp,"---%c\n",huf[n].ch);
    }
    else{
       printf("@\n");
       fprintf(fp,"@\n");
    }
    PrintTree(huf,huf[n].lchild,p+1,fp);
}

void Treeprinting(){
     /**
    将已在内存中的哈弗曼树以直观的方式(树或凹入表形式)显示在终端上
    同时将次字符形式的哈弗曼树写入文件TreePrint中。
    */
    FILE *fp;
    fp=fopen("huffman.txt","r");
    int i,n;
    fscanf(fp,"%d",&n);
    HTNode *myHaffTree=(HTNode *)malloc(sizeof (HTNode)*(2*n+1));
    for (i=0;i<n;i++)
       fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    for (i=n;i<2*n-1;i++)
       fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    fclose(fp);
    fp=fopen("TreePrint.txt","w+");
    PrintTree(myHaffTree,2*n-2,0,fp);
    fclose(fp);
    printf("打印哈夫曼树过程完成!同时已将结果存入TreePrint中.\n\n");
}

void Menuprint(){
    printf("*******************************************************************************\n");
    printf("*****                                                                     *****\n");
    printf("*****                                                                     *****\n");
    printf("*****                       欢迎使用哈夫曼编/译码器                      *****\n");
    printf("*****                                                                     *****\n");
    printf("*****                                                                     *****\n");
    printf("***** E.编码   D.译码   P.印代码文件   T.印哈夫曼树   Q.退出  *****\n");
    printf("*****                                                                     *****\n");
    printf("*******************************************************************************\n");
}

int main()
{
    int i,j,n=4;
    int weight[100];
    char ch[100],cha;
    Menuprint();
    Initialization(weight,ch);
    while (1){
      printf("请输入要执行的操作:\nE.编码   D.译码   P.印代码文件   T.印哈夫曼树   Q.退出\n");
       printf("请输入要执行的操作:\n");
       scanf("%s",&cha);

       if (cha=='Q')    break;

       switch (cha){
       case 'E':    Encoding();     break;
       case 'D':    Decoding();     break;
       case 'P':    Print();        break;
       case 'T':    Treeprinting(); break;
       }
    }
    return 0;
}

时间: 2024-10-18 04:13:42

赫夫曼编译码器实验报告的相关文章

20172301 哈夫曼树实验报告

20172301 哈夫曼树实验报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 郭恺 学号:20172301 实验教师:王志强老师 实验日期:2018年12月9日 必修/选修: 必修 一.实验内容 二.实验过程 哈夫曼树 哈夫曼(Haffman)树,也称最优二叉树,是指对于一组带有确定权值的叶结点.构造的具有最小带权路径长度的二叉树. 二叉树的路径长度是指由根结点到所有的叶结点的路径长度之和. 一棵二叉树要想它的带权路径长度最小,必须使权值越大的叶结点越靠近根结点,而权值越

由二叉树构造赫夫曼树

赫夫曼树: 假设有n个权值{w1,w2,w3....},试构造一棵具有n个叶子节点的二叉树,每个叶子节点带权为wi,则其中带权路径长度最小的二叉树称为最优二叉树或者叫赫夫曼树. 构造赫夫曼树: 假设有n个权值,则构造出的赫夫曼树有n个叶子节点,n个权值分别设置为w1,w2,....wn,则赫夫曼树的构造规则为: 1.将w1,w2...看成是有n棵树的森林: 2.在森林中选择两个根节点的权值最小的树合并,作为一棵新树的左右子树,且新树的根节点权值为其左右子树根节点权值之和: 3.从森林中删除选取的

php 二叉树 与赫夫曼树

在学习图之前,中间休息了两天,感觉二叉树需要消化一下.所以中间去温习了下sql,推荐一本工具书<程序员的SQL金典>看名字不像一本好书,但是作为一个不错的SQL工具书还是可以小小备忘一下.涵盖内容不详细但是挺广,覆盖多种主流数据库 言归正传,以前知道折半查找,二叉树的概念也是感觉挺有意思,二叉树的实现有一个案例很不错,代码如下 class BiNode{ public $data; public $lchild; public $rchild; public function __constr

Huffman tree(赫夫曼树、霍夫曼树、哈夫曼树、最优二叉树)

flyfish 2015-8-1 Huffman tree因为翻译不同所以有其他的名字 赫夫曼树.霍夫曼树.哈夫曼树 定义引用自严蔚敏<数据结构> 路径 从树中一个结点到另一个结点之间的分支构成两个结点之间的路径. 路径长度 路径上的分支数目称作路径长度. 树的路径长度 树的路径长度就是从根节点到每一结点的路径长度之和. 结点的带权路径长度 结点的带权路径长度就是从该结点到根节点之间的路径长度与结点上权的乘积. 树的带权路径长度 树的带权路径长度就是树中所有叶子结点的带权路径长度之和,通常记做

赫夫曼树JAVA实现及分析

一,介绍 1)构造赫夫曼树的算法是一个贪心算法,贪心的地方在于:总是选取当前频率(权值)最低的两个结点来进行合并,构造新结点. 2)使用最小堆来选取频率最小的节点,有助于提高算法效率,因为要选频率最低的,要么用排序,要么用堆.用堆的话,出堆的复杂度为O(logN),而向堆中插入一个元素的平均时间复杂度为O(1),在构建赫夫曼树的过程中,新生成的结点需要插入到原来的队列中,故用堆来维持这种顺序比排序算法要高效地多. 二,赫夫曼算法分析 ①用到的数据结构分析 首先需要构造一棵赫夫曼树,因此需要二叉链

13.赫夫曼树及其应用

一.赫夫曼树定义与原理 1.路径长度:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径的长度; 2.树的路径长度:即从树根到每一结点的路径长度之和; 3.结点的带权的路径长度:即从该结点从到树根之间的路径长度与结点上权的乘积; 4.树的带权路径长度:为树中所有叶子结点的带权路径长度之和; 5.赫夫曼树定义:假设有n个权值{w1,w2,....,wn},构造一颗有n个叶子结点的二叉树,每个叶子结点带权wk,每个叶子的路径长度为lk,则其中带权路径长度WPL最小的

赫夫曼树(最优二叉树)

.在选择最小s1s2的时候少了一个空语句分号..调试了好久..坑爹. 这个是最优的编码策略能达到最少的编码 1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<math.h> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 typedef struct 9 {

构造最优二叉树-赫夫曼(Huffman)树算法

一.基本概念 1.赫夫曼(Huffman)树又称最优二叉树或最优搜索树,是一种带权路径长度最短的二叉树.在许多应用中,常常赋给树中结点一个有某种意义的实数,称此实数为该结点的权.从树根结点到该结点之间的路径长度与该结点上权的乘积称为结点的带权路径长度(WPL),树中所有叶子结点的带权路径长度之和称为该树的带权路径长度,通常记为: 2.两结点间的路径:从一结点到另一结点所经过的结点序列;路径长度:从根结点到相应结点路径上的分支数目;树的路径长度:从根到每一结点的路径长度之和. 3.深度为k,结点数

【数据结构】赫夫曼树的实现和模拟压缩(C++)

赫夫曼(Huffman)树,由发明它的人物命名,又称最优树,是一类带权路径最短的二叉树,主要用于数据压缩传输. 赫夫曼树的构造过程相对比较简单,要理解赫夫曼数,要先了解赫夫曼编码. 对一组出现频率不同的字符进行01编码,如果设计等长的编码方法,不会出现混淆的方法,根据规定长度的编码进行翻译,有且只有一个字符与之对应.比如设计两位编码的方法,A,B,C,D字符可以用00-11来表示,接收方只要依次取两位编码进行翻译就可以得出原数据,但如果原数据只由n个A组成的,那发出的编码就是2n个0组成,这样的