C++ 实现Huffman编译码器

来源:互联网 发布:数据库nvl 编辑:程序博客网 时间:2024/05/29 12:32

实现功能

1.实现自动统计输入文本的字符个数以及各字符的权值;
2.实现输入字符及各权值进行Huffman编码;
3.实现从文档保存数据及读取数据;
4.各字符及其权值是由单链表的形式存储的;
5.译码是每50个01字符输出换行;
**注**Huffman树的建立是通过课本方法建立,其方式就不多说了。

代码实现

huffman.cpp

#include "huffman3.h"void Huffman :: readtext(char *file){           //读取文件中的数据,包括空格    indata.open(file);    if (! indata)    {        cout << "ERROR!" << endl;    }    char temp[100];    indata.getline(temp, 100);    text += temp;}void Huffman :: savetext(char *file){                      //保存数据到文件    outdata.open(file);    if (! outdata)    {        cout << "ERROR" << endl;    }    outdata << text;}void Huffman :: readcode(char *file){                          //读取代码    indata.open(file);    indata >> huffmancode; }/*void Huffman::ReadCodeFromFile(char *filename){                          //读取代码(这个也可以用)    ifstream infile(filename);    if (!infile)    {        cerr << "无法打开文件!" << endl;        return;    }    infile >> huffmancode;    cout << huffmancode << endl;}*/void Huffman :: savecode(char *file){    outdata.open(file);    if (!outdata)    {        cout << "ERROR" << endl;    }    outdata << huffmancode;}void Huffman::HuffmanCoding(){   //huffman树的建立    if (number <= 1)        return;    int m = 2 * number - 1;     //哈弗曼树所需节点数    huffmantree = new HTNode[m + 1];        //0号单元未使用    huffmancharslist p;    p = l -> next;    int i;    for (i = 1; i <= number; ++i)//初始化    {        huffmantree[i].weight = p -> weight;        huffmantree[i].parent = 0;        huffmantree[i].lchild = 0;        huffmantree[i].rchild = 0;        p = p -> next;    }    for (i = number + 1; i <= m; ++i)    {        huffmantree[i].weight = 0;        huffmantree[i].parent = 0;        huffmantree[i].lchild = 0;        huffmantree[i].rchild = 0;    }    for (i = number + 1; i <= m; ++i)//建哈弗曼树    {        int s1, s2;        select(i - 1, s1, s2);        huffmantree[s1].parent = huffmantree[s2].parent = i;        huffmantree[i].lchild = s1;        huffmantree[i].rchild = s2;        huffmantree[i].weight = huffmantree[s1].weight + huffmantree[s2].weight;    }    p = l -> next;                  //从叶子到根节点逆向求每个字符的哈弗曼编码    char *cd = new char[number];    //分配求编码的工作空间(每个字符编码结果最长n-1再加上'/0')    cd[number - 1] = '/0';          //编码结束符    for (i = 1; i <= number; ++i)       //逐个字符求哈弗曼编码    {        int start = number - 1;        int c, f;        for (c = i, f = huffmantree[i].parent; f != 0; c = f, f = huffmantree[f].parent)//从叶子到根逆向求编码        {            if (huffmantree[f].lchild == c) //左孩子编码为0                cd[--start] = '0';            else                            //右孩子编码为1                cd[--start] = '1';        }        char *a[i];        a[i] = (char *) malloc ((number - start) * sizeof(char));        strcpy(a[i], &cd[start]);        p -> code = a[i];        cout << p -> code << endl;        p = p -> next;    }    delete[] cd;   //清除缓存}void Huffman::select(int n, int &s1, int &s2){          //选取n个元素中权值最小的两个元素    s1 = s2 = 0;    for (int i = 1; i <= n; ++i)    {        if (huffmantree[i].parent != 0)            continue;        if (s1 == 0)            s1 = i;        else if (s2 == 0)        {            if (huffmantree[i].weight < huffmantree[s1].weight)            {                s2 = s1;                s1 = i;            }            else                s2 = i;        }        else        {            if (huffmantree[i].weight < huffmantree[s1].weight)            {                s2 = s1;                s1 = i;            }            else if (huffmantree[i].weight < huffmantree[s2].weight)                s2 = i;        }    }}void Huffman::PrintCharWeight(){   //输出各字符及其权值(检验时用)    huffmancharslist p;    p = l -> next;    while (p)    {        switch (p -> ch)        {        case '/t':            cout << "//t";            break;        case '/n':            cout << "//n";            break;        default:            cout << p -> ch;            break;        }        cout << "——" << p -> weight << endl;        p = p -> next;    }}void Huffman :: printtext(){      //输出文本    cout << text << endl;}void Huffman :: printcode(){       //输出代码    for (int i = 0; i <= huffmancode.size(); i ++)    {        cout << huffmancode[i];        if ((i + 1) % 50 == 0)        {   //每输出50个编码换行            cout << endl;        }    }}void Huffman :: Encode(){        //编码    huffmancharslist p;    for (int i = 0; i < text.size(); i ++)    {        p = l -> next;        for (int j = 1; j <= number; j ++)        {            if (text[i] == p -> ch)            {                huffmancode += p -> code;            }            p = p -> next;        }    }}void Huffman :: Decode(){       //解码    text = "";    string temp;    huffmancharslist p;    for (int i = 0; i < huffmancode.size(); i ++)    {        temp += huffmancode[i];        p = l -> next;        for (int j = 1; j <= number; j ++)        {            if (temp == p -> code)            {                text += p -> ch;                temp = "";            }            p = p -> next;        }    }    cout << text << endl;//输出编码}void Huffman :: get_number(){       //输入字符数    cout << "输入字符个数:" << endl;    cin >> number;}void Huffman :: get_weight(){     //输入字符及权值    huffmancharslist p, q;    p = (huffmancharslist) malloc (sizeof(LNode));    l -> next = p;    cout << "请输入字符和权值:" << endl;    int i;    for (i = 1; i < number; ++i)    {        cin.ignore();       //清除输入缓冲区        cin.get(p -> ch);   //输入单个字符,可以是空白符        cin >> p -> weight;        q = (huffmancharslist) malloc (sizeof(LNode));        p -> next = q;        p = q;    }    if (i == number)    {        cin.ignore();        cin.get(p -> ch);        cin >> p -> weight;        p -> next = NULL;    }}void Huffman :: countchars(){     //统计输入的字符及个字符权值    huffmancharslist p, q, temp;    p = (huffmancharslist) malloc (sizeof(LNode));    l -> next = p;    p -> next = NULL;    p -> ch = text[0];    p -> weight = 1;    number = 1;    for (int i = 1; i != text.size(); ++i)    {        int j;        p = l -> next;        for (j = 1; j <= number; ++j)           {            if (text[i] == p -> ch)            {                p -> weight ++;                break;            }            temp = p;            p = p -> next;        }        if (j > number)             {            p = temp;            ++number;            q = (huffmancharslist) malloc (sizeof(LNode));            q -> ch = text[i];            q -> weight = 1;            p -> next = q;            q -> next = NULL;        }    }}

huffman.h

#include <iostream>#include <string>#include <string.h>#include <stdlib.h>#include <fstream>using namespace std;typedef struct //huffmantree{    unsigned int weight;    unsigned int parent, lchild, rchild;}HTNode, *HuffmanTree;typedef struct LNode //字符链表结点{    char ch;    unsigned int weight;    char *code;    struct LNode *next;}LNode, *huffmancharslist;class Huffman{    private:        ifstream indata;   //输入文件流        ofstream outdata;   //输出文件流        string huffmancode, text;        int number;    //字符链表结点个数        HuffmanTree huffmantree;        huffmancharslist l;  //头节点    public:        Huffman() {    //初始化            l = (huffmancharslist) malloc (sizeof(LNode));            l -> next = NULL;        }        void savetext(char *file);        void readtext(char *file);        void readcode(char *file);        void savecode(char *file);        void countchars();        void HuffmanCoding();        void select(int n, int &s1, int &s2);        void Encode();        void Decode();        void get_number();        void get_weight();        void printcode();        void treeprint();        void PrintCharWeight();        void CountCharsWeight();        void printtext();        //void ReadCodeFromFile(char *filename);};

main.cpp

#include "huffman3.h"int main(){    Huffman huffman;    huffman.readtext("text.txt");    huffman.printtext();    cout << "请选择是否系统自己统计权值? 1.yes  2.no  3.exit" << endl;    int chose2;    cin >> chose2;    while (chose2 == 1 || chose2 == 2)    {        switch (chose2)        {        case 1:            huffman.countchars();            break;        case 2:            huffman.get_number();            huffman.get_weight();            break;          }        cout << "建哈夫曼树……" << endl;        huffman.HuffmanCoding();        cout << "编码中……" << endl;        huffman.Encode();        cout << "保存编码……" << endl;        huffman.savecode("code.txt");        cout << "输出编码结果:";        huffman.printcode();        cout << endl;        cout << "从文件中读取编码……" << endl;        huffman.readcode("code.txt");        //huffman.ReadCodeFromFile("code.txt");        cout << "解码……" << endl;        huffman.Decode();        chose2 = 3;    }    while (chose2 != 1 && chose2 != 2 && chose2 != 3)    {        cout << "don't so stupid! just fallow my rules!" << endl;    }    return 0;}
0 0