//*******************************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