Huffman編碼與解碼C++程式__html5

來源:互聯網
上載者:User
//*******************************huffman.h**********************//*****************葉子結點為n的哈夫曼樹共有2n-1個結點**********#ifndef HUFFMAN_H#define HUFFMAN_Hclass HuffmanNode {public:    char info; //結點資訊    double weight; //結點權值    int parent, lchild, rchild; //父親結點,左右孩子結點    HuffmanNode() {        parent=lchild=rchild=-1;    }    HuffmanNode(const char &data, const double &wt, const int &pa=-1, const int &lch=-1, const int &rch=-1) {        info=data;        weight=wt;        parent=pa;        lchild=lch;        rchild=rch;    }}; //class HuffmanNode end        class HuffmanTree {public:    HuffmanTree(const int &s=100) {        maxSize=(s>100?s:100);         arrayTree=new HuffmanNode[maxSize];        currentSize=0;        codeArray=0;    }    ~HuffmanTree() {        delete[] arrayTree;        if (codeArray!=0)            delete[] codeArray;    }    void run(const char*, const char*, const char*);private:    HuffmanNode *arrayTree; //哈夫曼結點數組    int maxSize; //數組最大值    int currentSize; //當前數組大小    void insert(const char&, const double&); //插入結點    void createHuffmanTree(); //建立哈夫曼樹    void createHuffmanCode(); //建立哈夫曼編碼    int findPosition(const char &) const; //返回字元在arrayTree[]中的位置    int getLongestCodeLength() const; //返回編碼系統中長度最大的編碼的位置    int isEqual(const char *s) const; //判斷s是否存在於編碼系統中,若存在則返回s在編碼系統中的位置,否則返回-1    void print(); //列印huffman編碼private:    class Code { //HuffmanTree的私人類,編碼類別    public:        Code():length(10) { ptr=new char[length]; }        ~Code() { delete[] ptr; }        char *ptr;        const int length;    };    Code *codeArray; //數組大小為currentSize    void reverse(char arr[]);}; //class HuffmanTree end#endif //huffman.h end//**************************huffman.cpp**********************#include #include //for ofstream ifstream#include   //for numeric_limits::max()#include //for exit()#include //for strlen(), strcpy(), strcmp()#include "huffman.h"using namespace std;void HuffmanTree::insert(const char &data, const double &wt) { //插入結點    if (2*currentSize-1 >= maxSize) //葉子結點為n的哈夫曼樹共有2n-1個結點        return;    arrayTree[currentSize].info=data;    arrayTree[currentSize].weight=wt;    currentSize++;}void HuffmanTree::reverse(char arr[]) { //反轉字串    const int len=strlen(arr);    char *p;    p=new char[len+1];    strcpy(p, arr);    p[len]='\0';    int k=0;    for (int i=len-1; i>=0; i--)         arr[i]=p[k++];    arr[len]='\0';    delete[] p;}int HuffmanTree::findPosition(const char &ch) const { //返回字元ch在arrayTree[]中的位置    for (int i=0; i<currentsize; i++)        if (arrayTree[i].info == ch)            return i;    return -1;}int HuffmanTree::getLongestCodeLength() const { //返回編碼數組codeArray[]長度最長的編碼的位置    if (currentSize == 0)        return -1;    int len=strlen(codeArray[0].ptr);    int i=1;    while (i < currentSize) {        int tmp=strlen(codeArray[i].ptr);        if (tmp > len)            len=tmp;        i++;    }    return len;}int HuffmanTree::isEqual(const char *s) const { //判斷s的編碼是否存在,若存在返回編碼在數組codeArray[]中的位置,否則返回-1    for (int i=0; i<currentsize; i++)=""         if (strlen(s) == strlen(codeArray[i].ptr)) //可以去掉此行            if (strcmp(s, codeArray[i].ptr) == 0)                return i;    return -1;}    void HuffmanTree::print() { //列印編碼    int k=0;    while (k < currentSize) {        cout<<arraytree[k].info<<'('<<arraytree[k].weight<<"): "<<codearray[k].ptr<<endl;        k++;    }}void HuffmanTree::createHuffmanTree() { //構造huffmanTree    int i=currentSize;    int k;    double wt1, wt2;    int lnode, rnode;    while (i < 2*currentSize-1) {        wt1=wt2=numeric_limits::max();        k=0;        while (k < i) {            if (arrayTree[k].parent==-1) {                if (arrayTree[k].weight<wt1) {                    wt2=wt1;                    rnode=lnode;                    wt1=arrayTree[k].weight;                    lnode=k;                }                else if (arrayTree[k].weight<wt2) {                    wt2=arrayTree[k].weight;                    rnode=k;                }             }            k++;        }        arrayTree[i].weight = arrayTree[lnode].weight+arrayTree[rnode].weight;        arrayTree[i].lchild=lnode;        arrayTree[i].rchild=rnode;        arrayTree[lnode].parent=arrayTree[rnode].parent=i;        i++;    }}            void HuffmanTree::createHuffmanCode() { //構造huffmanCode,即哈夫曼編碼    codeArray=new Code[currentSize];    int i=0;    int k, n, m;    while (i < currentSize) {        k = arrayTree[i].parent;        n=0;        m=i;        while (k!=-1 && k<currentsize*2-1) {            if (arrayTree[k].lchild==m)                 codeArray[i].ptr[n++]='0';            else if (arrayTree[k].rchild==m)                 codeArray[i].ptr[n++]='1';            m=k;            k=arrayTree[m].parent;        }        codeArray[i].ptr[n]='\0';        reverse(codeArray[i].ptr); //反轉字串,使之變成正確的編碼        i++;    }}void HuffmanTree::run(const char *inFilename, const char *outFilename, const char *secondOutName) { //run函數的實現    //開啟inFilename提供輸入    ifstream fileIn(inFilename, ios::in);    if (!fileIn) {        cerr<<"\""<<infilename<<"\" could="" not="" open."<<endl;        exit(1);    }    char ch;    int pos;    //從檔案中讀入字元,並統計各個字元個數    fileIn>>ch;    while (fileIn && !fileIn.eof()) {        pos = findPosition(ch);        if (pos != -1)            arrayTree[pos].weight++;        else             insert(ch, 1);        fileIn>>ch;    }    createHuffmanTree(); //構造huffman樹    createHuffmanCode(); //對統計字元進行編碼    //開啟outFilename提供輸出    ofstream fileOut(outFilename, ios::out);    if (!fileOut) {        cerr<<"\""<<outfilename<<"\" could="" not="" open."<<endl;        exit(1);    }    fileIn.clear(); //重新整理輸入資料流, 註:ofstream沒有flush()方法,而ifstream則有flush()方法    fileIn.seekg(0, ios::beg);    //把從inFilename檔案中的字元進行編碼,並寫入outFilename檔案    fileIn>>ch;    while (fileIn && !fileIn.eof()) {        pos = findPosition(ch);        if (pos != -1)            fileOut<<codearray[pos].ptr;        fileIn>>ch;    }    fileIn.close();    fileOut.close();    //開啟outFilename, secondOutName,分別提供輸入輸出    fileIn.open(outFilename, ios::in);    fileOut.open(secondOutName, ios::out);    if (!fileIn || !fileOut) {        cerr<<"File could not open."<<endl;        exit(1);    }    //把outFileName檔案中的編碼進行解碼,並把解碼結果寫入secondOutName檔案    const int longestLen = getLongestCodeLength();    char *p = new char[longestLen+1];    int k=0;    fileIn>>ch;    while (fileIn && !fileIn.eof()) {        if (k < longestLen) {            p[k++]=ch;            p[k]='\0';            pos = isEqual(p);            if (pos != -1) {                fileOut<<arraytree[pos].info;                k=0;            }        }        else {            cerr<<"The code is wrong."<<endl;            exit(1);        }        fileIn>>ch;    }    fileIn.close();    fileOut.close();}        //huffman.cpp end //*****************************main.cpp*************************#include "huffman.h"int main() {    HuffmanTree tree;    //const char *inFileName="in.txt";    const char *inFileName="main.cpp";    const char *outFileName="out1.txt";    const char *secondOutName="out2.txt";    tree.run(inFileName, outFileName, secondOutName);    return 0;} //main.cpp end


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.