数据结构复习之利用Huffman树进行编码和译码

//编码#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<fstream>
#include<map>
using namespace std;

typedef struct HuffmanNode{
    int w;//节点的权值
    int ld, rd;//左右孩子节点
    int p;//父节点
    char ch;//当前节点的字符
    HuffmanNode(){
        ld = rd = p = -1;
    }
}huffmanNode, *pHuffmanNode;

typedef pair<int, int> pii;//haffuman节点和它的编号 

bool operator > (pii x, pii y){
    return x.first > y.first;
}

struct Huffman{
    int cntNode;//总结点的个数
    string orgCode;
    string huffmanCode;
    pHuffmanNode huffman =    NULL;
    priority_queue<pii, vector<pii>, greater<pii> >qNode;
    map<string, char> huffmanMapx;//哈夫曼编码对应字符
    map<char, string> huffmanMapy;//字符对应哈夫曼编码
    void initHuffman(char *str){
        orgCode = str;
        cntNode = 0;
        int cnt[150];//统计每一个节点的个数
        memset(cnt, 0, sizeof(cnt));
        for(int i=0; str[i]; ++i){
            if(cnt[str[i]]==0) ++cntNode;
            ++cnt[str[i]];
        }
        huffman = new HuffmanNode[2*(cntNode)];
        int index = 0;
        for(int i=0; i<150; ++i){
            if(cnt[i]!=0){
                huffman[index].w = cnt[i];
                huffman[index].ch = i;
                qNode.push(make_pair(huffman[index].w, index));
                ++index;
            }
        }
        while(qNode.size()>=2) {
            pii ldPii = qNode.top();
            qNode.pop();
            pii rdPii = qNode.top();
            qNode.pop();
            huffman[index].w = ldPii.first + rdPii.first;
            huffman[index].ld = ldPii.second;
            huffman[index].rd = rdPii.second;
            huffman[ldPii.second].p = index;
            huffman[rdPii.second].p = index;
            qNode.push(make_pair(huffman[index].w, index));
            ++index;
        }
    }

    void huffmanCoding() {
        for(int i=0; i<cntNode; ++i){//从每一个孩子节点向上寻找
            string code = "";
            for(int child=i, p=huffman[child].p; ~p; child = p, p = huffman[child].p) {
                if(huffman[p].ld == child){//左子树
                    code += ‘0‘;
                } else if(huffman[p].rd == child){//右子树
                     code += ‘1‘;
                }
            }
            reverse(code.begin(), code.end());
            huffmanMapx.insert(make_pair(code, huffman[i].ch));
            huffmanMapy.insert(make_pair(huffman[i].ch, code));
        }
    }

    void outHuffmanTree(fstream &fout, int f){
        if(huffman[f].ld==-1 && huffman[f].rd==-1){
            fout<<0<<" ";
            return ;
        } else {
            fout<<1<<" ";
            outHuffmanTree(fout, huffman[f].ld);
            outHuffmanTree(fout, huffman[f].rd);
        }
    }

    void outHuffmanCode(){
        huffmanCode = "";//存储字符串的哈夫曼编码之后的内容
        fstream fout("out.txt", ios_base::out);
        for(int i=0; i<orgCode.length(); ++i){
            huffmanCode += huffmanMapy[orgCode[i]];
        }
        cout<<huffmanCode<<endl;
        fout<<huffmanCode<<endl;//想文件中输入huffman编码
        int f = 2*cntNode-2;//huffman树的父节点
        outHuffmanTree(fout, f);
        fout<<endl;
        for(map<string, char>::iterator it = huffmanMapx.begin(); it!=huffmanMapx.end(); ++it){
            cout<<it->first << " -> " << it->second<<endl;
            fout<<it->first<<" "<<it->second<<endl; //向文件中输入HuffmanMap
        }
    }
};

int main(){
    char str[100];
    Huffman huffman;
    gets(str);
    huffman.initHuffman(str);
    huffman.huffmanCoding();
    huffman.outHuffmanCode();
    return 0;
}
//译码#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<fstream>
#include<map>
using namespace std;

typedef struct HuffmanTreeNode{
    HuffmanTreeNode *ld, *rd;
    HuffmanTreeNode(){
        ld = NULL;
        rd = NULL;
    }
} *pHuffmanTreeNode;

struct Huffman{
    pHuffmanTreeNode T;
    string code;
    map<string, char>huffmanMapx;

    void buildT(fstream &fin, pHuffmanTreeNode &T){
        int w;
        fin>>w;
        T = new HuffmanTreeNode();
        if(w==0)
            return ;
         buildT(fin, T->ld);
         buildT(fin, T->rd);
    }

    void outT(pHuffmanTreeNode T){
        if(T->ld != NULL){
            cout<<0<<endl;
            outT(T->ld);
        }
        else return;
        if(T->rd != NULL){
            cout<<1<<endl;
            outT(T->rd);
        }
    }

    void initHuffmanTree(){
        fstream fin("in.txt", ios_base::in);
        T = NULL;
        fin>>code;
        buildT(fin, T);
        //outT(T);
        string mapContent;
        while(getline(fin, mapContent)){
            int index = mapContent.find_first_of(‘ ‘);
            huffmanMapx.insert(make_pair(mapContent.substr(0, index), mapContent[index+1]));
        }
    }

    void outHuffmanEncode(){
        string encode = "", cd="";
        initHuffmanTree();
        pHuffmanTreeNode p = T;
        for(int i=0; i<code.length(); ++i){
            if(p->ld==NULL && p->rd==NULL){
                encode+=huffmanMapx[cd];
                cd="";
                --i;
                p=T;
            } else {
                cd+=code[i];
                if(code[i]==‘0‘)
                    p=p->ld;
                else if(code[i]==‘1‘)
                    p=p->rd;
            }
            if(i==code.length()-1) encode+=huffmanMapx[cd];
        }
        cout<<encode<<endl;
    }
};

int main(){
    Huffman huffman;
    huffman.outHuffmanEncode();
    return 0;
}

操作流程:

文本内容:aaaaaaabbbbbccdddd, and I am a student, my name is hjzgg!

1.首先利用‘‘编码"工具将文本编码,会输出一个out.txt的文本,将out.txt文本中的内容发送给你的好友。

2.接受到out.txt文本的内容后,将内容复制到文本名为in.txt的文件中,利用"译码"工具(保证in.txt和译码工具在同一目录下)可以查看文本内容。

3.其中out.txt文本的格式如下:

时间: 2024-10-05 23:58:08

数据结构复习之利用Huffman树进行编码和译码的相关文章

Huffman树的编码译码

上个学期做的课程设计,关于Huffman树的编码译码. 要求: 输入Huffman树各个叶结点的字符和权值,建立Huffman树并执行编码操作 输入一行仅由01组成的电文字符串,根据建立的Huffman树进行译码操作,程序最后输出译码后的结果 Huffman.h定义了树的结点信息,各种操作.GCC编译通过. 1 #ifndef HUFFMAN_H_INCLUDED 2 #define HUFFMAN_H_INCLUDED 3 #include <iostream> 4 #include <

Huffman树与编码

带权路径最小的二叉树称为最优二叉树或Huffman(哈夫曼树). Huffman树的构造 将节点的权值存入数组中,由数组开始构造Huffman树.初始化指针数组,指针指向含有权值的孤立节点. b = malloc(n*sizeof(BTreeNode)); for (i = 0; i < n; i++) { b[i] = malloc(sizeof(BTreeNode)); b[i]->data = a[i]; b[i]->left = NULL; b[i]->right = NU

【数据结构】哈夫曼树实现编码译码

根据一段字符串中字符的个数 作为该字符的权值生成哈夫曼树. 然后根据生成的哈夫曼编码,对任意字符串实现编码,对任意二进制串实现译码. 程序运行结果: 1.程序主界面: 2.根据字符串 创建哈夫曼树及编码: 3.生成的编码表如下: 4.根据生成的哈夫曼编码对字符串编码: 5.生成的编码保存在文件中: 6.对二进制串译码: 结果: 代码: 哈夫曼树的生成和编码的常见,以及编码和译码函数 //_HuffmanTree_H #ifndef _HuffmanTree_H #define _HuffmanT

Huffman树及其编码(STL array实现)

这篇随笔主要是Huffman编码,构建哈夫曼树有各种各样的实现方法,如优先队列,数组构成的树等,但本质都是堆. 这里我用数组来存储数据,以堆的思想来构建一个哈弗曼树,并存入vector中,进而实现哈夫曼编码 步骤: 1生成哈夫曼树  (取最小权值树和次小权值树生成新树,排列后重新取树,不断重复)    2编码   (遵循左零右一的原则)           3解码(是编码的逆向,本文还未实现,日后有机会补充) data.txt  测试数据: 51 2 3 4 5abcde 结果: 下面贴代码:

数据结构复习之次优查找树的建立

查找效率最高即平均查找长度最小,根据前面所学知识,我们可以给出有序表在非等概率情况下应遵循的两个原则: 1.最先访问的结点应是访问概率最大的结点:  2.每次访问应使结点两边尚未访问的结点的被访概率之和尽可能相等. 这两个原则可用一句话来表示,即判定树为带权内路径长度之和最小的二叉树,亦即:PH = ∑wihi  最小,其中 n 为有序表长度,hi 为第 i 个结点在判定树上的层次数,wi = cpi,c 为某个常数,pi 为第 i 个结点的查找概率. 这样的树称为静态最优查找树(static

C语言:哈夫曼树的编码与译码

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #define N 100 typedef struct { int weight; int parent, lchild, rchild; }hafuman; typedef struct { char data[N]; //字符数据 char copy[N][10*N];//编码 }bianma; void

【数据结构】第6章 树(下)

数据结构第6章 树(下) §6.4 树和森林 6.4.1 树的储存结构 ①父亲表示法(利用每个(除根)结点只有唯一的父亲的性质) ②孩子表示法(用广义表实现) ③孩子兄弟表示法(二叉链表指向第一个孩子结点和下一个兄弟结点) 6.4.2森林与二叉树的转换 二叉树和树都可以用二叉链作为储存结构(分别是孩子表示法和孩子兄弟表示法),给定一棵树,可以找到唯一的一棵二叉树与之对应.两者的物理结构是相同的,只是解释不同而已(旋转). 任何一棵和树对应的二叉树,其右子树必空(因为根是没有兄弟的),在森林中可以

Huffman树及其编解码

Huffman树--编解码 介绍: ??Huffman树可以根据输入的字符串中某个字符出现的次数来给某个字符设定一个权值,然后可以根据权值的大小给一个给定的字符串编码,或者对一串编码进行解码,可以用于数据压缩或者解压缩,和对字符的编解码. ??可是Huffman树的优点在哪? ??1.就在于它对出现次数大的字符(即权值大的字符)的编码比出现少的字符编码短,也就是说出现次数越多,编码越短,保证了对数据的压缩. ??2.保证编的码不会出现互相涵括,也就是不会出现二义性,比如a的编码是00100,b的

Huffman树费用

问题描述 Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, -, pn-1},用这列数构造Huffman树的过程如下: 1. 找到{pi}中最小的两个数,设为pa和pb,将pa和pb从{pi}中删除掉,然后将它们的和加入到{pi}中.这个过程的费用记为pa + pb. 2. 重复步骤1,直到{pi}中只剩下一个数. 在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用. 本题任务:对于给定的一个数列