c++实现哈夫曼huffman压缩文本

哈夫曼压缩原理就是构建二叉树,出现频率高的字母用更少的位数来表示,实现压缩的效果

比如字符串abcbbc

构建哈夫曼树

这样构建出编码表b->0,a->10,  c->11

原本6个字符要48位来表示,现在只需要9位来表示即可

 

1.    首先将文本文件的每一个字符进行统计,构建编码表,这个编码表大概50几k

void readTxt(string file,Character *cList)

{

    ifstream infile;

    infile.open(file.data());  //将文件流对象与文件连接起来

    assert(infile.is_open());  //若失败,则输出错误消息,并终止程序运行



    char c;

    infile >> noskipws;

    while (!infile.eof())

    {

        addList(c,cList);

        infile>>c;

    }

    infile.close();            //关闭文件输入流

}

void addList(char c,Character *cList){

    //为空就退出

    if(!c) return;

    totalNum++;

    int i=0;

    for(;i<cnumber;i++){

        if(c==cList[i].data){

            break;

        }

    }



    cList[i].number++;



    if(i==cnumber){

        cList[cnumber].data = c;

        cnumber++;

    }



    if(i>0 && cList[i].number>cList[i-1].number){

        int num = cList[i].number;

        char ch = cList[i].data;

        cList[i].data = cList[i-1].data;

        cList[i].number = cList[i-1].number;

        cList[i-1].data = ch;

        cList[i-1].number = num;

    }

}

 

1.    根据huffman树原理,构建编码表(如下图所示),词频越高则用更小的编码表示

 

 

//换行符

string enterCode;

////////////

typedef struct node{

    char ch;                         //存储该节点表示的字符,只有叶子节点用的到

    int val;                         //记录该节点的权值

    structnode *self,*left,*right;   //三个指针,分别用于记录自己的地址,左孩子的地址和右孩子的地址

    friend booloperator <(const node &a,constnode &b) //运算符重载,定义优先队列的比较结构

    {

        return a.val>b.val;          //这里是权值小的优先出队列

    }

}node;

int codeTablePlace = 0;

node *myroot;

priority_queue<node> p;               //定义优先队列

char res[10000];                         //用于记录哈夫曼编码

void dfs(node *root,int level,CodeTableItem *codetable,Character *cList)        //哈夫曼编码表

{

    if(root->left==root->right)       //叶子节点的左孩子地址一定等于右孩子地址,且一定都为NULL;叶子节点记录有字符

    {

        if(level==0)                  //“AAAAA”这种只有一字符的情况

        {

            res[0]='0';

            level++;

        }

        res[level]='\0';              //字符数组以'\0'结束

        //printf("%c=>%s\n",root->ch,res);

        //搜索在统计表中的位置

        for(int j=0;j<cnumber;j++){

            if(root->ch==cList[j].data){

                codetable[j].data = root->ch;

                codetable[j].code =res;

            }

        }

//        codetable[codeTablePlace].data = root->ch;

//        codetable[codeTablePlace].code = res;

        if(int(root->ch)==10)

            enterCode =res;

       // codeTablePlace++;

    }

    else

    {

        res[level]='0';               //左分支为0

        dfs(root->left,level+1,codetable,cList);

        res[level]='1';               //右分支为1

        dfs(root->right,level+1,codetable,cList);

    }

}

void huffman(Character *hash,CodeTableItem *codeTable)               //构建哈夫曼树

{

    node *root,fir,sec;

    for(int i=0;i<cnumber;i++)

    {

        root=(node *)malloc(sizeof(node));         //开辟节点

        root->self=root;                           //记录自己的地址,方便父节点连接自己

        root->left=root->right=NULL;               //该节点是叶子节点,左右孩子地址均为NULL

        root->ch=hash[i].data;                            //记录该节点表示的字符

        root->val=hash[i].number;                         //记录该字符的权值

        p.push(*root);                             //将该节点压入优先队列

    }

    //下面循环模拟建树过程,每次取出两个最小的节点合并后重新压入队列

    //当队列中剩余节点数量为1时,哈夫曼树构建完成

    while(p.size()>1)

    {

        fir=p.top();p.pop();     //取出最小的节点

        sec=p.top();p.pop();     //取出次小的节点

        root=(node *)malloc(sizeof(node));         //构建新节点,将其作为fir,sec的父节点

        root->self=root;                           //记录自己的地址,方便该节点的父节点连接

        root->left=fir.self;     //记录左孩子节点地址
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值