首先感叹,Huffman真牛逼!!
尽量把文件压缩到最小
通过最优排序,大数据把人们最常用的字符放到树前面,以实现最小编码。
大致说一下原理,贴一下代码
1:用户提供常用字符,建立一棵最优树
2:得到每一个字符的编码code
3:用户输入0和1,通过遍历最优树实现解码
说起来很容易,编码设计到队列和二叉树,确实不容易敲出来
接下来敲一下代码:/*注:没使用头文件,分文件写,考虑看家看的明白*/
/*还有就是头节点应该和普通节点不一样的,但是Debug时候出现不同struct类型不能赋值,所以干脆使用同一个struct了,比较占用空间,各位看官知道就行,当然可以优化*/
/*
输入文本,建立队列
生成huffman 树
输入编码,输出字符文本
*/
#include <malloc.h>
#include <iostream>
using namespace std;
typedef struct ht_node//huffman树节点
{
char data;
struct ht_node *left,*right;
}*TYPE;
typedef struct quene_node//队列节点
{
TYPE val;//树类型
unsigned int size;
unsigned int priority;//优先级
struct quene_node *next;//后继
}*Q_node;
typedef struct table_node
{
char symbol;//字符存放
char *code;
struct table_node *next;
}Table_node;
typedef struct table
{
Table_node *first,*next;
}*Table;
void add_quene(Q_node &hufquene,TYPE &aux,unsigned int priority)//参数:队列头节点,树节点,优先级
{
if(hufquene->size==256)
{
cout<<"Quene is full !!";
return;
}//否则建立队列节点
Q_node temp=(Q_node)malloc(sizeof(quene_node));
temp->priority=priority;
temp->val=aux;
///DEBUG/
if(hufquene->size==0||hufquene->next==NULL)//只有头节点
{
//把元素插入队列
temp->next=NULL;
hufquene->next=temp;
hufquene->size++;
}else
{
//要进行比较后按顺序优先级从小到大排列
Q_node itertor=hufquene;//建立迭代节点,指向第一个节点
while(itertor->next!=NULL)//队列中存在元素
{
if(priority<=itertor->next->priority)//从第二个节点开始比较
{
hufquene->size++;
temp->next=itertor->next;
itertor->next=temp;//头插法
return;
}
itertor=itertor->next;
}
if(itertor->next==NULL)
{
temp->next=NULL;
itertor->next=temp;
hufquene->size++;
return;
}
}
}
TYPE getquene(Q_node &hufquene)
{
TYPE returnvalue;
if(hufquene->size>0)
{
Q_node tree_node= hufquene->next;
returnvalue=tree_node->val;
hufquene->next=tree_node->next;
hufquene->size--;
}else
{
cout<<"Empty!!";
}
return returnvalue;//返回树节点
}
TYPE buildtree(char *inputstring)
{
int *probablity=(int *)malloc(sizeof(int)*256);//分配地址
for(int i=0;i<256;i++)
probablity[i]=0;//初始化
for(int j=0;inputstring[j]!='\0';j++)
{
probablity[(inputstring[j])]++;
}//统计字符出现次数
Q_node hufquene;//定义一个头节点
//初始化头节点
hufquene=(Q_node)malloc(sizeof(quene_node));
hufquene->next=NULL;
hufquene->size=0;
///
//生成队列
for(int k=0;k<256;k++)
{
if(probablity[k]!=0)//存在字符
{
TYPE aux=(TYPE)malloc(sizeof(ht_node));
aux->data=(char)k;
aux->left=NULL;
aux->right=NULL;//为每一个字符分配一个树节点
//插入队列
add_quene(hufquene,aux,probablity[k]);
}
}
//生成Huffman树
while(hufquene->size!=1)
{
Q_node tyust=hufquene->next;
unsigned int num=tyust->priority;
num+=tyust->next->priority;
TYPE left=getquene(hufquene);
TYPE right=getquene(hufquene);
TYPE huff_tree=(TYPE)malloc(sizeof(ht_node));
huff_tree->left=left;
huff_tree->right=right;
add_quene(hufquene,huff_tree,num);//再次插入
}
TYPE root=(TYPE)malloc(sizeof(ht_node));
root=getquene(hufquene);
return root;
}
void travertree(TYPE tree_node,Table &link,int k,char code[256])
{
if(tree_node->left==NULL&&tree_node->right==NULL)//叶子
{
code[k]='\0';//添加结束
Table_node *aux=(Table_node*)malloc(sizeof(Table_node));
aux->code=(char*)malloc(sizeof(char)*(strlen(code)+1));
strcpy(aux->code,code);
aux->symbol=tree_node->data;
aux->next=NULL;
if(link->first==NULL)
{
link->first=link->next=aux;
}else
{
link->next->next=aux;
link->next=aux;
}
}
if(tree_node->left!=NULL)//左子树不为0
{
code[k]='0';
travertree(tree_node->left,link,k+1,code);
}
if(tree_node->right!=NULL)
{
code[k]='1';
travertree(tree_node->right,link,k+1,code);
}
}
Table build_table(TYPE tree_node)//建立
{
Table tytable=(Table)malloc(sizeof(table));
tytable->first=NULL;
tytable->next=NULL;
char code[256];
int k=0;
travertree(tree_node,tytable,k,code);
return tytable;
}
void decode(TYPE root,char *str)//解码
{
int j=0;
TYPE temp=root;
cout<<"你输入的编码是:"<<endl;
while(str[j]!='\0')
{
cout<<str[j++];
}cout<<endl;
cout<<"解码:"<<endl;
for(int i=0;str[i]!='\0';i++)
{
if(temp->left==NULL&&temp->right==NULL)
{
cout<<temp->data;
temp=root;//碰到叶子后从根重新开始
}
if(str[i]=='0')
{
temp=temp->left;//0向左走
}
if(str[i]=='1')
{
temp=temp->right;
}
}
}
void main()
{
TYPE root=buildtree("Hello world I am CPP");//根据大数据生成最优树
Table mark_table=build_table(root);//返回生成的最优排列
decode(root,"00011101111101");//还没找到对应编码多出的舍弃不要
cout<<endl;
}