数据结构之哈夫曼编译码器的实现(C语言)

一枚学习编程的小白,前段时间在看数据结构,就把学到的整理一下下,有错误的地方希望大神可以指点嘻嘻嘻~

需求分析:一个完整的系统应具有以下功能

  1. 初始化: 从终端输入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存入文件hfmtree文件中。
  2. 编码: 利用已建立的哈夫曼树,对文件tobetran中的正文进行编码,然后将结果存入codefile中。
  3. 译码: 利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入文件textfile中 。
  4. 印代码文件: 将文件codefile以紧凑格式显示在终端上,每行50个代码,同时将此字符形式的编码文件写入文件codeprint中。
  5. 印哈夫曼树: 将内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。
    测试数据:利用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“this program is my favorite”

哈夫曼树:
设有n个权值{w1,w2,……wn},构造一棵有n个叶子结点的二叉树,每个叶子的权值为wi,则wpl最小的二叉树叫哈夫曼树。

路径: 从树中一个结点到另一个结点之间的分支构成这两个结点间的~
路径长度:路径上的分支数
树的路径长度: 从树根到每一个结点的路径长度之和
树的带权路径长度: 树中所有带权结点的路径长度之和

构造Huffman树的方法——Huffman算法
1、根据给定的n个权值{w1,w2,……wn},构造n棵只有根结点的二叉树,令其权值为wj
2、在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和
3、在森林中删除这两棵树,同时将新得到的二叉树加入森林中
重复上述两步,直到只含一棵树为止,这棵树即哈夫曼树
Huffman编码:

思想: 根据字符出现频率编码,使电文总长最短
编码: 根据字符出现频率构造Huffman树,然后将树中结点引向其左孩子的分支标“0”,引向其右孩子的分支标“1”;每个字符的编码即为从根到每个叶子的路径上得到的0、1序列

Huffman译码:

从Huffman树根开始,从待译码电文中逐位取码。若编码是“0”,则向左走;若编码是“1”,则向右走,一旦到达叶子结点,则译出一个字符;再重新从根出发,直到电文结束

基本知识说完之后,上代码!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define leafnum 27
#define hufnum 2*leafnum
#define maxdouble 9999.9//哈夫曼树节点存储结构
typedef struct tnode
{char name;double weight;int lchild,rchild,parent;
}huftree;//哈夫曼编码表结构
typedef struct cnode
{char bits[leafnum+1];int start;char ch;
}hufcode;hufcode code[leafnum+1];
huftree tree[hufnum+1];
char huffmancode[1000];
//定义全局数组来存放这些字符名称和对应频度
char ch[] = {'\0',' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
float w[] = {0,186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1};//建立哈夫曼树
void creattreehuffman(huftree tree[])
{int i, j, p1, p2;double least1, least2;for (i=1; i<=hufnum; i++){tree[i].name = '\0';tree[i].parent = 0;tree[i].lchild = 0;tree[i].rchild = 0;tree[i].weight = 0.0;}for (i=1; i<=leafnum; i++){tree[i].name = ch[i];tree[i].weight = w[i];}for (i=leafnum+1; i<=hufnum; i++){p1=0; p2=0; least1=least2=maxdouble;for (j=1; j<i; j++)if (tree[j].parent==0)if (tree[j].weight<least1){least2=least1;least1=tree[j].weight;p2=p1;p1=j;}else{if(tree[j].weight<least2){least2=tree[j].weight;p2=j;}}tree[p1].parent=i;tree[p2].parent=i;tree[i].lchild=p1;tree[i].rchild=p2;tree[i].weight=tree[p1].weight+tree[p2].weight;}tree[hufnum-1].parent=0;
}
// 建立哈夫曼编码
void creatcodehuffman(hufcode code[], huftree tree[])
{int i, c, p;hufcode buf;for (i=1; i<=leafnum; i++){buf.ch=ch[i];buf.start=leafnum;c=i;p=tree[i].parent;while (p != 0){buf.start--;if (tree[p].lchild==c)buf.bits[buf.start]='0';else buf.bits[buf.start]='1';c=p;p=tree[p].parent;}code[i]=buf;}
}
//哈夫曼编码
void writecodehuffman(hufcode code[], huftree tree[])
{int i, j, k, n=0;char c[100];printf("请输入字符串:\n");gets(c);printf("\n");printf("则字符串的哈夫曼编码为:\n");for(i=0;i<strlen(c);i++){for (j=1; j<=leafnum; j++)if (c[i]==tree[j].name)for(k=code[j].start; k<leafnum; k++){printf("%c", code[j].bits[k]);huffmancode[n] = code[j].bits[k];n++;}}
}
//哈夫曼译码
void transcodehuffman(hufcode code[], huftree tree[], char s[])
{int i;char *q=NULL;i=hufnum-1; q=s;while (*q!='\0'){if (*q=='0') i=tree[i].lchild;if (*q=='1') i=tree[i].rchild;if ((tree[i].lchild==0)&&(tree[i].rchild==0)){printf("%c",code[i].ch);i = hufnum - 1;}q++;}printf("\n");
}
//输出哈夫曼树
void printtreehuffman(huftree tree[])
{int i;printf("根据字符的使用概率所建立的哈夫曼数为:\n");printf( "字符序号   字符名称      字符频率    双亲位置    左孩子  右孩子\n");for (i = 1; i < hufnum; i++){printf("\t %d \t %c \t ",i,tree[i].name);printf(" %f \t %d \t %d \t %d \n", tree[i].weight,tree[i].parent,tree[i].lchild,tree[i].rchild) ; }
}
//输出每个字符的哈夫曼编码
void printcodehuffman(hufcode code[])
{int i, j;printf( "根据哈夫曼树对字符所建立的哈夫曼编码为:\n");printf( "字符序号   字符名称   字符编码 \n");for (i =1; i <= leafnum; i++){printf("\t %d \t %c ",i,code[i].ch);for(j=code[i].start;j <leafnum;j++)printf("%c",code[i].bits[j]);printf("\t \t \n");}
}
//主函数
void main()
{FILE *fp;int i;char buffer[1000];creattreehuffman(tree);printtreehuffman(tree);creatcodehuffman(code, tree);printcodehuffman(code);writecodehuffman(code, tree);if((fp=fopen("e:\\codefile.txt","w"))==NULL){printf("文件打开失败!\n");exit(0);}fprintf(fp,"哈夫曼编码为: %s",huffmancode);for(i=0;i<strlen(huffmancode);i++){buffer[i] = huffmancode[i];}printf("\n");printf( "codefile文件中的代码如下:\n" );printf( "哈夫曼编码为: %s \n\n",huffmancode );printf( "codefile文件中代码译码为:" );transcodehuffman(code, tree, buffer);
}
最后:编写实现方式有多种,小白欢迎大家批评指正

数据结构之哈夫曼编译码器(C语言版)相关推荐

  1. 霍夫曼编码PHP,数据结构:哈夫曼编码(php版)

    概述下: 哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩. 在计算机信息处理中,"哈夫曼编码"是一种一致性编码法(又称"熵编码法"),用于 ...

  2. 数据结构与算法(C语言版)---哈夫曼编译码器

    1.需求分析 1.1.问题阐述 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本.但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原 ...

  3. 数据结构“基于哈夫曼树的数据压缩算法”的实验报告

    一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055@qq.com Last edited: 2022.11.20 目录 数据结构& ...

  4. 数据结构(哈夫曼树+KMP)之 数据加密+解密

    数据结构(哈夫曼树+KMP)之 数据加密+解密 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> #define N 1 ...

  5. 2020-10-1 //严蔚敏《数据结构》 //赫夫曼树及其应用:创建顺序赫夫曼树创建及得到赫夫曼编码

    //严蔚敏<数据结构> //赫夫曼树及其应用:创建顺序赫夫曼树创建及得到赫夫曼编码 //(从叶子结点到根逆向求每个字符的赫夫曼编码)以及(无栈非递归遍历赫夫曼树,求赫夫曼编码) //自学中 ...

  6. 哈夫曼编码c语言实现

    哈夫曼编码的原理看 百度百科 先生成一个哈夫曼树,参考 哈夫曼树c语言实现 生成接近等长码 须要注意的是,为了缩短码长方差,且编出的码更接近于等长码,排序的时候,第一优先级为概率大小,第二优先级为左节 ...

  7. 数据结构之赫夫曼文件压缩解压

    一.文件压缩 具体要求:给你一个图片文件,要求对其进行无损压缩, 看看压缩效果如何. 思路:读取文件-> 得到赫夫曼编码表 -> 完成压缩 package com.ws.数据结构.树.赫夫 ...

  8. 信息论 输入概率的哈夫曼编码 C语言

    信息论 哈夫曼编码 C语言 哈夫曼编码是一种效率比较高的变长无失真信源编码方法.哈夫曼编码的编码方法,步骤如下: 将信源符号按概率从大到小的顺序排列,为方便起见,令p(a1)>=p(a2)> ...

  9. 数据结构 基于哈夫曼树的数据压缩算法

    数据结构 基于哈夫曼树的数据压缩算法 实验目的 实验内容 实验提示 实验代码 实验小结 实验目的 1.掌握哈夫曼树的构造算法. 2.掌握哈夫曼编码的构造算法. 实验内容 问题描述 输入一串字符串,根据 ...

最新文章

  1. (C++)用upper_bound函数取代自己写的二分查找
  2. 两个运放制作加法器_集成运放电路设计原理图
  3. Oracle安装完成后如何创建表空间及用户
  4. 折半查找的思想及源码_结构与算法(04):排序规则与查找算法
  5. rest和rest ful_为什么REST如此重要
  6. 【算法分析与设计】排序算法的时间复杂度与O(NlogN)
  7. WordPress电影资源下载主题:zmovie
  8. 精通HTML5+CSS3需要学什么?
  9. 链接在HTML的英文,html超链接学习(适于初学者)(国外英文资料).doc
  10. 将一个输入流(InputStream)写入到一个文件中
  11. python数据分析-《Python数据分析与数据化运营》电子版
  12. python常用函数使用
  13. 各种常用的JSON接口
  14. 旧电脑 软路由 openwrt 自定义安装ipk 操作记录
  15. 也谈谈如何胜任中小型公司的技术总监
  16. 微博立场检测 60分Baseline
  17. (一)互联智能车载终端系统,介绍,构思,搭建
  18. 当3dsmax软件崩溃闪退时,该如何做?
  19. ncut算法分割图像的matlab,Ncut_9 归一化切割和图像分割算法及其论文, 不仅度量了不同分组之间总体不相似性, matlab 269万源代码下载- www.pudn.com...
  20. RF+APPIUM详细使用教程

热门文章

  1. 【vue axios 跨域】cookie、origin等一步步递进的跨域踩坑 已解决
  2. oracle事务操作例子,oracle 事务 与 提交
  3. pyecharts绘制双y轴图并将html文件转为png图片格式
  4. r7 3750h和r5 3550h的差距 r7 3750h和r5 3550h哪个好
  5. 数据提取之JSON与JsonPATH
  6. 使用excel生成商品条形码
  7. ASP.NET Core 部署到docker
  8. Linux shell 日期,时间相关的命令
  9. Linux中常用软件安装
  10. Qt学习)—— 代码实现文件的打开与保存