Huffman树,是一类带权路径长度最短的树。
从树中一个节点到另一个节点之间的分支构成这二个节点之间的路径,路径上的分支数目称为路径的长度。
树的路径长度是从树根到每一个节点之间的路径长度之和。
//
----------Huffman----------------
#include < iostream >
#include < cstring >
#include < cstdlib >
using namespace std;
// =========Huffman节点================
typedef struct
{
unsigned int weight;//权值
unsigned int Parent,LChild,RChild;
} HTNode, * HuffmanTree;
// --------------------------------
typedef char ** HuffmanCode;
const int MAX_SIZE = 100 ;
// 查询此e字符是否已出现
int search( char difchar[], int n, char e)
{
for(int i = 1; i <= n; i++)
if(difchar[i] == e)
return i;
return -1;
}
// 计算相应字符出现的频率
int stat( char data[], char difchar[], int w[])
{
int n = 0, i, len = strlen(data);
int xx;
for(i = 0; i < len; i++)
{
xx = search(difchar, n, data[i]);
if(xx == -1)
{
difchar[++n] = data[i];
w[n] = 0;
}
else
w[xx]++;
}
return n;
}
int GetMin(HuffmanTree t, int i)
{//返回i个结点中权值最小的且没有父节点的节点序号
int j=1,flag,k;
while(t[j].Parent!=0)
j++;
flag=j;k=t[j].weight;//flag为t中第一个没有父节点的节点序号
for(j++;j<=i;j++)
if(t[j].weight<k&&t[j].Parent==0)
{ k=t[j].weight;
flag=j;
}
t[flag].Parent=1;
return flag;
}
void select(HuffmanTree t, int i, int & s1, int & s2)
{//在i个节点中选择2个权值最小的树的根节点序号
int j;
s1=GetMin(t,i);
s2=GetMin(t,i);
if(t[s1].weight>t[s2].weight)
{
j=s1;
s1=s2;
s2=j;
}
}
void HuffmanCoding(HuffmanTree & HT,HuffmanCode & HC, int * w, int n)
{
//w存放n个字符的权值,构造Huffman树HT,并求出n个字符的Huffman编码HC
int s1,s2,start,m,i;
unsigned c,f;
char *cd;
HuffmanTree p;
if(n<=1)return;
m=2*n-1;//节点的总数
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//节点0空
for(p=HT+1,i=1;i<=n;i++,p++,w++)
{
p->weight=*w;
(*p).Parent=(*p).LChild=(*p).RChild=0;
}
for(;i<=m;i++,p++)
(*p).Parent=0;
for(i=n+1;i<=m;i++)
{
select(HT,i-1,s1,s2);//寻找权值最小的二棵子树
HT[s1].Parent=HT[s2].Parent=i;
HT[i].LChild=s1;
HT[i].RChild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++)
{
start=n-1;
for(c=i,f=HT[i].Parent;f!=0;c=f,f=HT[f].Parent)
{
if(HT[f].LChild==c)
cd[--start]='0';
else
cd[--start]='1';
}
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
int main()
{//主函数
HuffmanTree HT;
HuffmanCode HC;
int n = 0,i;//n表示输入文字中不同字符的个数
char data[MAX_SIZE];
char difchar[MAX_SIZE];
int w[MAX_SIZE];
cout<<"=====-请输入预编码的文字-====="<<endl;
cout<<"仅限英文字符,输入Ctrl+Z结束输入"<<endl;
while(cin.getline(data,MAX_SIZE,'\n'))
{
n = stat(data, difchar,w);
HuffmanCoding(HT,HC,w+1,n);
cout<<"=============字符与相应编码为============="<<endl;
for(i=1;i<=n;i++)
{
cout<<difchar[i]<<":";
puts(HC[i]);
}
cout<<endl<<"===============编码文字==============="<<endl;
for(i = 0; i < strlen(data);i++)
cout<<HC[search(difchar,n,data[i])];
cout<<endl<<endl;
system("PAUSE");
cout<<"=====-请输入预编码的文字-====="<<endl;
cout<<"仅限英文字符,输入Ctrl+Z结束输入"<<endl;
}
return 0;
}
#include < iostream >
#include < cstring >
#include < cstdlib >
using namespace std;
// =========Huffman节点================
typedef struct
{
unsigned int weight;//权值
unsigned int Parent,LChild,RChild;
} HTNode, * HuffmanTree;
// --------------------------------
typedef char ** HuffmanCode;
const int MAX_SIZE = 100 ;
// 查询此e字符是否已出现
int search( char difchar[], int n, char e)
{
for(int i = 1; i <= n; i++)
if(difchar[i] == e)
return i;
return -1;
}
// 计算相应字符出现的频率
int stat( char data[], char difchar[], int w[])
{
int n = 0, i, len = strlen(data);
int xx;
for(i = 0; i < len; i++)
{
xx = search(difchar, n, data[i]);
if(xx == -1)
{
difchar[++n] = data[i];
w[n] = 0;
}
else
w[xx]++;
}
return n;
}
int GetMin(HuffmanTree t, int i)
{//返回i个结点中权值最小的且没有父节点的节点序号
int j=1,flag,k;
while(t[j].Parent!=0)
j++;
flag=j;k=t[j].weight;//flag为t中第一个没有父节点的节点序号
for(j++;j<=i;j++)
if(t[j].weight<k&&t[j].Parent==0)
{ k=t[j].weight;
flag=j;
}
t[flag].Parent=1;
return flag;
}
void select(HuffmanTree t, int i, int & s1, int & s2)
{//在i个节点中选择2个权值最小的树的根节点序号
int j;
s1=GetMin(t,i);
s2=GetMin(t,i);
if(t[s1].weight>t[s2].weight)
{
j=s1;
s1=s2;
s2=j;
}
}
void HuffmanCoding(HuffmanTree & HT,HuffmanCode & HC, int * w, int n)
{
//w存放n个字符的权值,构造Huffman树HT,并求出n个字符的Huffman编码HC
int s1,s2,start,m,i;
unsigned c,f;
char *cd;
HuffmanTree p;
if(n<=1)return;
m=2*n-1;//节点的总数
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//节点0空
for(p=HT+1,i=1;i<=n;i++,p++,w++)
{
p->weight=*w;
(*p).Parent=(*p).LChild=(*p).RChild=0;
}
for(;i<=m;i++,p++)
(*p).Parent=0;
for(i=n+1;i<=m;i++)
{
select(HT,i-1,s1,s2);//寻找权值最小的二棵子树
HT[s1].Parent=HT[s2].Parent=i;
HT[i].LChild=s1;
HT[i].RChild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++)
{
start=n-1;
for(c=i,f=HT[i].Parent;f!=0;c=f,f=HT[f].Parent)
{
if(HT[f].LChild==c)
cd[--start]='0';
else
cd[--start]='1';
}
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
int main()
{//主函数
HuffmanTree HT;
HuffmanCode HC;
int n = 0,i;//n表示输入文字中不同字符的个数
char data[MAX_SIZE];
char difchar[MAX_SIZE];
int w[MAX_SIZE];
cout<<"=====-请输入预编码的文字-====="<<endl;
cout<<"仅限英文字符,输入Ctrl+Z结束输入"<<endl;
while(cin.getline(data,MAX_SIZE,'\n'))
{
n = stat(data, difchar,w);
HuffmanCoding(HT,HC,w+1,n);
cout<<"=============字符与相应编码为============="<<endl;
for(i=1;i<=n;i++)
{
cout<<difchar[i]<<":";
puts(HC[i]);
}
cout<<endl<<"===============编码文字==============="<<endl;
for(i = 0; i < strlen(data);i++)
cout<<HC[search(difchar,n,data[i])];
cout<<endl<<endl;
system("PAUSE");
cout<<"=====-请输入预编码的文字-====="<<endl;
cout<<"仅限英文字符,输入Ctrl+Z结束输入"<<endl;
}
return 0;
}