#include<iostream>
#include<string>
#include<cstring>
#include<fstream>
using namespace std;
const int MAXBIT=100;
const int MAXVALUE=1000000;
const int MAXLEAF=30;
const int MAXNODE=MAXLEAF*2-1;
class Node
{
double weight;
int parent,lchild,rchild;
char value;
friend class HF;
}; //node class
class Code
{
int bit[MAXBIT];
int start;
friend class HF;
}; //code class
class HF
{
Node HuffNode[MAXNODE];
Code HuffCode[MAXLEAF];
public:
HF(int arr[],int n);
void HuffmanCode(int n);
void HuffmanDeCode(string arr,int n);
}; //huffman tree
HF::HF(int arr[],int n)
{
double min1,min2;
int z;
int p1,p2;
//init code and weight
for(int i=0;i<n;i++)
{
HuffNode[i].weight=0;
HuffNode[i].parent = -1;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
}
z=0;
for(int i=0; i<256; i++)
{
if(arr[i]!=0){
HuffNode[z].value = (char)i;
HuffNode[z].weight = arr[i];
z++;
}
}
cout << "add" <<"\t" << "min1" << "\t" << "min2" <<endl;
//find min1 and min2
for(int i=0; i<n-1; i++)
{
min1=min2=MAXVALUE;
p1=p2=0;
for (int j=0; j<n+i; j++)
{
if (HuffNode[j].weight<min1 && HuffNode[j].parent==-1)
{
min2 = min1;
p2 = p1;
min1 = HuffNode[j].weight;
p1 = j;
}
else if (HuffNode[j].weight < min2 && HuffNode[j].parent==-1)
{
min2=HuffNode[j].weight;
p2=j;
}
}
HuffNode[p1].parent = n+i;
HuffNode[p2].parent = n+i;
HuffNode[n+i].parent = -1;
HuffNode[n+i].weight = min1+min2;
HuffNode[n+i].lchild = p1;
HuffNode[n+i].rchild = p2;
cout << HuffNode[n+i].weight <<"\t" << HuffNode[p1].weight << "\t" << HuffNode[p2].weight <<endl;
}
} //create huffman tree
void HF::HuffmanCode(int n)
{
Code temp;
int c,p;
for(int i=0;i<n;i++)
{
temp.start=n-1;
c=i;
p=HuffNode[c].parent;
while(p!=-1)
{
if(HuffNode[p].lchild==c)
temp.bit[temp.start]=0; //leftchild 0
else
temp.bit[temp.start]=1; //rightchild 1
temp.start--;
c=p;
p=HuffNode[c].parent;
}
for (int j=temp.start+1; j<n; j++)
HuffCode[i].bit[j]=temp.bit[j];
HuffCode[i].start=temp.start;
}
//show huffman code
for(int i=0;i<n;i++)
{
cout<<HuffNode[i].value<<": Huffman code is: ";
for(int j=HuffCode[i].start+1;j<n;j++)
cout<<HuffCode[i].bit[j];
cout<<endl;
}
} //huffman code
void HF::HuffmanDeCode(string arr,int n)
{
//show the text huffman code
cout << "Huffman decode: " << endl;
int arrcount = arr.length();
int codecount = 0 ;
for(int i=0; i<arr.length(); i++){
for (int j=0; j<n; j++) {
if ( arr[i] == HuffNode[j].value) {
for(int z=HuffCode[j].start+1;z < n; z++){
cout<<HuffCode[j].bit[z];
codecount++;
}
}
}
}
cout << endl;
}
int main()
{
string str;
int count=0; //the number of code
cout<<"read text"<<endl;
ifstream inFile("test.txt");
getline(inFile,str); //read in file
int ascii[256]={};
for(int i=0;i<str.length();i++)
{
ascii[(int)str[i]]++;
if(ascii[(int)str[i]]==1)
count++;
}
HF hf(ascii,count);
hf.HuffmanCode(count);
hf.HuffmanDeCode(str,count);
}