设计一个哈夫曼编码、译码系统。对一个ASCII编码的文本文件中的字符进行哈夫曼编码,生成编码文件;反过来,可将编码文件译码还原为一个文本文件。
(1) 从文件中读入任意一篇英文短文(文件为ASCII编码,扩展名为txt);
(2) 统计并输出不同字符在文章中出现的频率(空格、换行、标点等也按字符处理);
(3) 根据字符频率构造哈夫曼树,并给出每个字符的哈夫曼编码;
(4) 图形化输出哈夫曼树、哈夫曼编码;
(5) 将文本文件利用哈夫曼树进行编码,存储成压缩文件(编码文件后缀名.huf)
(6) 用哈夫曼编码来存储文件,并和输入文本文件大小进行比较,计算文件压缩率;
(7) 进行译码,将huf文件译码为ASCII编码的txt文件,与原txt文件进行比较。
[测试数据]文本文件自行选择,至少含3000个字符。
[实现代码]

#include<iostream>
#include<fstream>
#include<queue>
#include<math.h>
using namespace std;
struct Node{
public:
Node *right;
Node *left;
char data;
int weight;
int x[];
};
void InsertionSort(Node*A[],int n){
for(int i=;i<n;i++){
Node *get=A[i];
int j=i-;
while(j>=&&A[j]->weight>get->weight){
A[j+]=A[j];
j--;
}
A[j+]=get;
}
}
Node* father(Node*root,Node*son){
Node*temp;
if(root==NULL||son==NULL)
return NULL;
if(root->left==son||root->right==son)
return root;
temp=father(root->left,son);
if(temp!=NULL)
return temp;
else
return father(root->right,son);
}
void preorder(Node*root){
if(root!=NULL) {
cout<<root->weight<<" ";
preorder(root->left);
preorder(root->right);
}
}
void sumlevel(Node*root,int *count,int l){
if(root!=NULL) {
count[l]=count[l]+;
sumlevel(root->left,count,l+);
sumlevel(root->right,count,l+);
}
}
void levelorder(Node*t,int*count){
queue<Node*>q;
int x=,i=;
if(t!=NULL){
Node*p;
for(int z=;z<;z++){
cout<<" ";
}
cout<<t->data<<"("<<t->weight<<")"<<endl;
x=x+;
i=i+;
q.push(t);
while(!q.empty()){
p=q.front();
q.pop();
if(p->left){
for(int z=;z</(i+);z++) cout<<" ";
cout<<p->left->data<<"("<<p->left->weight<<")";
if(x==count[i]){
cout<<endl;
i++;
x=;
}
x=x+;
q.push(p->left);
}
if(p->left){
for(int z=;z</(i);z++) cout<<" ";
cout<<p->right->data<<"("<<p->right->weight<<")";
if(x==count[i]){
cout<<endl;
i++;
x=;
}
x=x+;
q.push(p->right);
}
}
}
}
void TreePrint(Node *T,int level)
{
if (T!=NULL) return;
TreePrint(T->right,level+); //打印右子树,并将层次加1
for (int i=;i<level;i++) //按照递归的层次打印空格
{
printf(" ");
}
cout<<T->weight<<endl;
TreePrint(T->left,level+); //打印左子树,并将层次加1
}
int main(){
//打开待压缩文件
ifstream file("C:\\Users\\wenjian\\start.txt");
char a;
Node *root1;
int n[]={};
int x,i,j,num=;
while(!file.eof()){
file.get(a);
if(file.fail()) break;
x=a;
n[x]++;
}
for(i=;i<;i++){
if(n[i]!=) num++;
}
Node *m[num],*mm[num];
for(i=;i<num;i++){
m[i]=new Node;
m[i]->left=NULL;
m[i]->right=NULL;
}
j=;
for(i=;i<;i++){
if(n[i]!=){
m[j]->data=i;
m[j]->weight=n[i];
j++;
}
}
InsertionSort(m,num);
Node *p1,*p2,*p,*t;
j=;
for(i=;i<num;i++){
mm[i]=m[i];
}
for(i=;i<num-;i++){
t=new Node;
p1=m[i];
p2=m[i+];
t->weight=m[i]->weight+m[i+]->weight;
t->left=p1;
t->right=p2;
p=t;
j=i+;
while(j<num&&p->weight > m[j]->weight){
m[j-]=m[j];
j=j+;
}
m[j-]=p;
}
root1=m[num-];
int zz[];
Node *s,*z;
for(i=;i<num;i++){
for(int xx=;xx<;xx++){
zz[xx]=-;
}
s=father(root1,mm[i]);
z=mm[i];
j=;
while(s!=root1){
if(s->left==z){
zz[-j]=;
}
if(s->right==z){
zz[-j]=;
}
z=s;
s=father(root1,z);
j++;
}
if(s->left==z) zz[-j]=;
if(s->right==z) zz[-j]=;
x=;
for(int xx=g0;xx<;xx++){
if(zz[xx]>-) x++;
}
for(int xx=;xx<;xx++){
zz[xx]=zz[xx+-x];
}
for(int xx=x;xx<;xx++){
zz[xx]=-;
}
for(int xx=;xx<;xx++){
mm[i]->x[xx]=zz[xx];
}
}
for(i=;i<num;i++){
cout<<mm[i]->data<<":"<<mm[i]->weight<<" ";
for(j=;j<;j++){
if(mm[i]->x[j]>=) cout<<mm[i]->x[j];
}
cout<<endl;
}
file.close();
//再次打开文件
ifstream file1("C:\\Users\\wenjian\\start.txt");
//生成的中间文件
ofstream putfile("C:\\Users\\daima\\progress.txt");
//生成压缩.huf文件
ofstream assicfile("C:\\Users\\wenjian\\assic.huf");
int f=,o=,w=;
while(!file1.eof()){
file1.get(a);
if(file1.fail()) break;
for(i=;i<num;i++){
if(mm[i]->data==a){
for(j=;j<;j++){
o=;
if(mm[i]->x[j]==-) break;
putfile<<mm[i]->x[j];
if(f<){
for(int d=;d<-f;d++){
o=*o;
}
w=mm[i]->x[j]*o+w;
f=f+;
}
if(f==){
w=mm[i]->x[j]+w;
f=;
char ww=w;
assicfile<<ww;
w=;
}
}
}
}
}
file1.close();
putfile.close();
// ifstream outfile("progress.txt");
// ofstream infile("end.txt"); /////
//重新打开中间文件,生成最终解压文件
ifstream outfile("C:\\Users\\daima\\progress.txt");
ofstream infile("C:\\Users\\wenjian\\end.txt");
char y;
while(!outfile.eof()){
if(outfile.fail()) break;
s=root1;
z=s;
while(z->left){
outfile.get(y);
if(y==''){
s=z;
z=s->left;
}
if(y==''){
s=z;
z=s->right;
}
}
if(outfile.fail()) break;
infile<<z->data;
}
outfile.close();
infile.close();
int sum[]={};
sumlevel(root1,sum,);
levelorder(root1,sum);
int q=;
for(i=;i<;i++){
q=q*;
if(q>=num) break;
}
int zzz=i+;
ifstream file2("end.txt");
while(!file2.eof()){
if(file2.fail()) break;
file2.get(a);
for(i=;i<zzz;i++){
}
if(file2.fail()) break;
}
file2.close();
float g,h;
cout<<"请分别输入原文件与压缩文件大小:"<<endl;
cin>>g;
cin>>h;
float hh=h/g;
cout<<"压缩率:"<<-hh<<endl;
}

C++实现哈夫曼编码/译码器(数据结构)的更多相关文章

  1. c++实验8 哈夫曼编码-译码器

    哈夫曼编码-译码器 此次实验的注释解析多加不少---若对小伙伴们有帮助 希望各位麻烦点个关注 多谢 1.哈夫曼树构造算法为: (1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根结点的二叉树, ...

  2. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  3. SDUT 3345 数据结构实验之二叉树六:哈夫曼编码

    数据结构实验之二叉树六:哈夫曼编码 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 字符的编 ...

  4. 20172332 2017-2018-2 《程序设计与数据结构》Java哈夫曼编码实验--哈夫曼树的建立,编码与解码

    20172332 2017-2018-2 <程序设计与数据结构>Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 哈夫曼树 1.路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子 ...

  5. SDUT OJ 数据结构实验之二叉树六:哈夫曼编码

    数据结构实验之二叉树六:哈夫曼编码 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

  6. [数据结构与算法]哈夫曼(Huffman)树与哈夫曼编码

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  7. C语言数据结构之哈夫曼树及哈夫曼编码的实现

    代码清单如下: #pragma once #include<stdio.h> #include"stdlib.h" #include <string.h> ...

  8. Java数据结构(十二)—— 霍夫曼树及霍夫曼编码

    霍夫曼树 基本介绍和创建 基本介绍 又称哈夫曼树,赫夫曼树 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树 霍夫曼树是带权路径长度最短的树,权值较 ...

  9. 10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压

    最终结果哈夫曼树,如图所示: 直接上代码: public class HuffmanCode { public static void main(String[] args) { //获取哈夫曼树并显 ...

随机推荐

  1. Quartz.Net系列(十六):Misfire策略在SimpleScheduler和CronScheduler中的使用

    1.场景 ①因为工作线程都在忙碌,所以导致某些Trigger得不到触发 也就是默认10个工作线程而我有15个Trigger同时触发 这就导致有5个不能被触发,而不幸的是Trigger所关联的Job执行 ...

  2. Dresdon简介

    很久没有写文章了.这几年经历了很多事情:离开VMware的不舍,拿到融资的开心,重回VMware的亲切,以及不再争强好胜,只做自己喜欢事情的平和. 可以说,我是幸运的:我这一辈子都在选择,而不是被迫接 ...

  3. noi linux gedit 配置(c++环境)

    基本配置 方法一 查看所有命令: gsettings list-recursively | grep -i gedit 命令解释 gsettings set org.gnome.gedit.prefe ...

  4. PowerJob 技术综述,能领悟多少就看你下多少功夫了~

    本文适合有 Java 基础知识的人群 作者:HelloGitHub-Salieri HelloGitHub 推出的<讲解开源项目>系列.从本章开始,就正式进入 PowerJob 框架的技术 ...

  5. 三面拿杭州研究院50offer:面对这些问题,你都能做到嘛??

    5G的到来证明了互联网行业发展一如既往的快,作为一名开发人员(Java岗)梦想自然是互联网行业的大厂,这次我的一个学员拿到了杭州的一个研究院offer,透露一下,年薪50多万,保底16,在这里分享一拨 ...

  6. web自动化 -- 切换 iframe

    先看源码 switch_to_frame() frame() 具体用法

  7. 高度塌陷与BFC

    高度塌陷的产生条件 子元素浮动,脱离文档流 子元素绝对定位或固定定位,脱离文档流 定位产生的高度塌陷只能通过加固定高度或更换其他方案解决塌陷,本文主要讨论浮动产生塌陷的解决方法. 高度塌陷的解决方法 ...

  8. jboss在eclipse里一直是starting解决方法之一

    jboss\server\default\deploy\jboss-web.deployer\server.xml中的端口设置必须与eclipse中jboss的端口设置的一直.否则就算可以访问 一会在 ...

  9. 时间序列ARIMA模型

    时间序列ARIMA模型 1.数据的平稳性与差分法 让均值和方差不发生明显的变化(让数据变平稳),用差分法 2.ARIMA模型-----差分自回归平均移动模型 求解回归的经典算法:最大似然估计.最小二乘 ...

  10. Python List len()方法

    描述 len() 方法返回列表元素个数.高佣联盟 www.cgewang.com 语法 len()方法语法: len(list) 参数 list -- 要计算元素个数的列表. 返回值 返回列表元素个数 ...