哈夫曼编码(解压,压缩)

本文详细介绍了如何使用哈夫曼编码进行文件的加压缩与解压操作,包括Huffman Tree的构建、编码算法、解码过程以及实际应用案例。从创建Huffman Tree到实现文件的位级压缩,展示了整个编码解码流程。
摘要由CSDN通过智能技术生成

哈夫曼编码加压缩,解压

// HuffmanTree.h

//   HuffmanTree.h 

#ifndef HUFFMANTREE_H
#define HUFFMANTREE_H
#include<bits/stdc++.h>
using namespace std;

typedef struct Hufnode
{
    int rt,lchild,rchild,w;
}Hufnode,*Huftree;

class HuffmanTree
{
    public:
        void CreatHuf(int n,int *word);
    public:
        Hufnode *Hfm;
        int num,tot; //
};

#endif // HUFFMANTREE_H

// HuffmanTree.cpp

// HuffmanTree.cpp

#include "HuffmanTree.h"
#include<bits/stdc++.h>
using namespace std;
//typedef pair<int,int>pair<int,int>;
void HuffmanTree::CreatHuf(int n,int *word)
{
    num=n;
    tot=2*num-1;
    Hfm=new Hufnode[tot+1];
    for(int i=1;i<=tot;i++) // 完全初始化
    {
        Hfm[i].w=0;
        Hfm[i].rt=0;
        Hfm[i].lchild=0;
        Hfm[i].rchild=0;
    }
    priority_queue< pair<int,int>,vector< pair<int,int> >,greater< pair<int,int> > > que; //优先队列返回最小值
    for(int i=1;i<=n;i++)
    {
        Hfm[i].w=word[i];
        que.push(make_pair(Hfm[i].w,i));
    }
    for(int i=n+1;i<=tot;i++)
    {
        int min_1,min_2;
        min_1=que.top().second;
        que.pop();
        min_2=que.top().second;
        que.pop();
        Hfm[i].lchild=min_1;
        Hfm[i].rchild=min_2;
        Hfm[min_1].rt=i;
        Hfm[min_2].rt=i;
        Hfm[i].w=Hfm[min_1].w+Hfm[min_2].w;
        que.push(make_pair(Hfm[i].w,i));
    }
}

// main.cpp

//  main.cpp
#include<bits/stdc++.h>
#include<windows.h>
#include "HuffmanTree.h"
using namespace std;
typedef char **HuffmanCode; //哈夫曼编码表
int word[300];
HuffmanCode HC;
map<char,int> mp;// 字母对应编号
map<int,char> decmp; // 编号对应字母
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n) // 哈夫曼编码
{
	HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
	char *cd=new char [n];
	cd[n-1]='\0';
	for(int i=1;i<=n;i++)
	{
		int start=n-1;
		for(int j=i,fa=HT.Hfm[i].rt;fa!=0;j=fa,fa=HT.Hfm[fa].rt)
        {
            if(HT.Hfm[fa].lchild==j) cd[--start]='0';
			else cd[--start]='1';
        }
		HC[i]=(char*)malloc((n-start)*sizeof(char));
		strcpy(HC[i],&cd[start]);
	}
	delete cd;
}
void Menu_Show()
{
    cout<<"**********************************************************************"<<endl;
    cout<<"*                        哈夫曼编码译码器                            *"<<endl;
    cout<<"*            1、选择需要进行编码的文件                               *"<<endl;
    cout<<"*            2、建立哈夫曼树                                         *"<<endl;
    cout<<"*            3、建立密码本并对文件编码                               *"<<endl;
    cout<<"*            4、选择需要进行解码的文件并解码                         *"<<endl;
    cout<<"*            5、按位压缩方式对文件进行压缩                           *"<<endl;
    cout<<"*            6、对压缩的文件进行解压                                 *"<<endl;
    cout<<"*            7、对解压缩的文件进行解码                               *"<<endl;
    cout<<"*            输入其他任意数字退出                                    *"<<endl;
    cout<<"**********************************************************************"<<endl;
}
void Option_1(int &n)
{
    DWORD startTime=GetTickCount();
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt");
    char c;
    ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\原文.txt");
    mp.clear();
    int tot=0;
    while(in.get(c))
    {
        if(mp[c]==0)
        mp[c]=(++tot),decmp[tot]=c;
        word[mp[c]]++;
    }
    cout<<"              编码的文件读入成功"<<endl;
    n=tot;
    in.close();
    DWORD endTime=GetTickCount();
    out<<"读入要编码的文件运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_2(HuffmanTree&hf,int n)
{
    DWORD startTime=GetTickCount();
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
    hf.CreatHuf(n,word);
    cout<<"              哈夫曼树已成功建立"<<endl;
    cout<<"              ***哈夫曼树如下***\n"<<endl;
    cout<<"编号    权 值    父节点    左子节点    右子节点\n";
    for(int i=1;i<=hf.tot;i++)
    {
        printf("%4d    %4d     %4d       %4d       %4d\n",i,hf.Hfm[i].w,hf.Hfm[i].rt,hf.Hfm[i].lchild,hf.Hfm[i].rchild);
    }
    DWORD endTime=GetTickCount();
    out<<"建立哈夫曼树并输出哈夫曼树运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_3(HuffmanTree hf,int n)
{
    DWORD startTime=GetTickCount();
    ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
    HuffmanCoding(hf,HC,n);
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼编码文.txt");
    cout<<"              密码本已成功建立  "<<endl;
    cout<<"              ***如下***        "<<endl;
    for(int i=1;i<=n;i++)
    {
        if(decmp[i]=='\n') cout<<"Enter";
        else cout<<decmp[i];
        cout<<"  :";
        cout<<HC[i]<<endl;
    }
    char c;
    ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\原文.txt");
    while(in.get(c))
    {
        out<<HC[mp[c]];
    }
    out.close();
    in.close();
    DWORD endTime=GetTickCount();
    outf<<"建立密码本并编码运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_4(HuffmanTree hf,int n)
{
    DWORD startTime=GetTickCount();
    ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
    ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼编码文.txt");
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼解码文.txt");
    int now=2*n-1;
    char c;
    while(in.get(c))
    {
        if(c=='1') now=hf.Hfm[now].rchild;
        else now=hf.Hfm[now].lchild;
        if(hf.Hfm[now].rchild==0 && hf.Hfm[now].lchild==0)
        {
            out<<decmp[now];
            now=2*n-1;
        }
    }
    in.close();
    out.close();
    DWORD endTime=GetTickCount();
    outf<<"解码哈夫曼编码文运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_5()
{
    DWORD startTime=GetTickCount();
    ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
    ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼编码文.txt");
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\压缩文.cod",ios::binary);
    char c;
    int flag=0,tmp=0,n1=0,n2=0;
    while(in.get(c))
    {
        flag++;
        n1++;
        tmp=tmp*2+c-'0';
        if(flag==8)
        {
            n2++;
            flag=0;
            out<<(unsigned char)(tmp);
            tmp=0;
        }
    }
    if(flag%8!=0) out<<(unsigned char)(tmp),n2++;
    out<<(unsigned char)(flag%8);
    n2++;
    cout<<"                              ***压缩成功***    "<<endl;
    in.close();
    out.close();
    cout<<"压缩比为  :";
    cout<<(100.0*n2)/n1<<"%"<<endl;
    DWORD endTime=GetTickCount();
    outf<<"压缩哈夫曼编码文运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Unzip()
{
    DWORD startTime=GetTickCount();
    ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
    ifstream inf("D:\\C,C++\\数据结构\\HuffmanCode\\压缩文.cod",ios::binary);
    inf.seekg(0,ios::end);
    int n=inf.tellg();
    inf.close();
    ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\压缩文.cod",ios::binary);
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\解压编码文.txt");
    char c;
    while(in.get(c))
    {
        unsigned char ch=c;
        int ans=(int)ch;
        if(n==2)
        {
            in.get(c);
            ch=c;
            int t=(int)ch;
            int res=pow(2,t-1);
            for(int i=t-1;i>=0;i--)
            {
                int tmp=ans/res;
                ans%=res;
                res/=2;
                out<<tmp;
            }
            break;
        }
        int res=pow(2,7);
        for(int i=7;i>=0;i--)
        {
            int tmp=ans/res;
            ans%=res;
            res/=2;
            out<<tmp;
        }
        n--;
    }
    cout<<"                              ***解压成功***    "<<endl;
    in.close();
    out.close();
    DWORD endTime=GetTickCount();
    outf<<"解压压缩文运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Transfer(HuffmanTree hf,int n)
{
    DWORD startTime=GetTickCount();
    ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
    ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\解压编码文.txt");
    ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\解压哈夫曼解码文.txt");
    cout<<"                              ***解压码文如下***    "<<endl;
    int now=2*n-1;
    char c;
    while(in.get(c))
    {
        if(c=='1') now=hf.Hfm[now].rchild;
        else now=hf.Hfm[now].lchild;
        if(hf.Hfm[now].rchild==0 && hf.Hfm[now].lchild==0)
        {
            out<<decmp[now];
            now=2*n-1;
        }
    }
    in.close();
    out.close();
    DWORD endTime=GetTickCount();
    outf<<"将解压缩后的哈夫曼编码解码运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
int main()
{
    HuffmanTree hf;
    int n;
    while(true)
    {
        system("pause");
        system("cls");
        Menu_Show();
        int m1;
        cout<<"请输入你要进行的操作  :";
        cin>>m1;
        switch(m1)
        {
            case 1:Option_1(n);   break;
            case 2:Option_2(hf,n);break;
            case 3:Option_3(hf,n);break;
            case 4:Option_4(hf,n);break;
            case 5:Option_5();    break;
            case 6:Unzip();       break;
            case 7:Transfer(hf,n);break;
            default:return 0;     break;
         }
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值