huffman编码函数


虽然东西简单了点,可能还有错,读者们别介意它太啰嗦,有更好的建议欢迎交流的。放出来希望对像我一样学习编程的人有帮助(虽然看别人的代码貌似是件很痛苦的事啊)。


这里没有用模板函数(人比较懒),,节点的权值都是int,,类函数定义都在类的内部

//哈夫曼树类
class Node
{
public:
	Node *rchild;
	Node *lchild;
	Node *parent;
	int weight;  //权值
	char ch;     //叶子字符
	char node_code;  //每个字符对应的路径(左0右1)
	Node(){};
};
class HuffmanTree
{
protected:
	Node *root;   //根节点
	vector<char> leaf_char;    //从叶节点得到字符
	vector<string>  leaf_code ;   //保存每个字符的编码
public:
	HuffmanTree(int p ,char c){root=new Node();root->weight=p;root->ch=c;}
	HuffmanTree(){root=new Node();}
	void build_tree(int pro[],char cha[],int count)
	{
		HuffmanTree *r[26];
		for(int j=0;j<count;j++)     //初始化每个字符形成的树
		{
			r[j]=new HuffmanTree() ;
			r[j]->root->ch=cha[j];
			r[j]->root->weight=pro[j];
			
		}
		for(int j=0;j<count-1;j++)    //找出数组中根节点权值最小的两个 合并
		{
			for(int i=j+1;i<count;i++)      //找出最小权值的树放入r[j]
			{
				if(r[j]->root->weight>r[i]->root->weight)
				{
					HuffmanTree *temp;
					temp=r[i];
					r[i]=r[j];
					r[j]=temp;
				}
			}
			for(int i=j+2;i<count;i++)     //找出最小权值的树放入r[j+1]
			{
				if(r[j+1]->root->weight>r[i]->root->weight)
				{
					HuffmanTree *temp;
					temp=r[i];
					r[i]=r[j+1];
					r[j+1]=temp;
				}
			}
			HuffmanTree *t_r=new HuffmanTree();    //过渡用的t_r 生成新的树赋给r[j+1]
			t_r->root->lchild=r[j]->root;
			r[j]->root->parent=t_r->root;
			r[j]->root->node_code='0';      //是parent的左孩子,赋予路径0
			t_r->root->rchild=r[j+1]->root;
			r[j+1]->root->parent=t_r->root;
			r[j+1]->root->node_code='1';      //是parent的左孩子,赋予路径1
			t_r->root->weight = r[j]->root->weight+r[j+1]->root->weight;       //左右孩子的权值和
			r[j+1]=t_r;
			if(j+1==count-1)
			root=r[j+1]->root;
		}
	}
	void turn_char_code(Node *h)      //输出每个字符的编码
	{
		string s;
		Node *temp=h;
		if(temp->lchild==NULL && temp->rchild==NULL)  //测到根节点
		{
			char c=temp->ch;
			leaf_char.push_back(temp->ch);
			while (temp->parent!=NULL)   //有父节点则推测哈夫曼编码
			{
				s=temp->node_code+s;
				temp=temp->parent;
			}
			leaf_code.push_back(s);
			cout<<c<<"的哈夫曼编码:"<<s<<endl;

		}
		if(h->lchild!=NULL)
		{
			turn_char_code(h->lchild);
		}
		if(h->rchild!=NULL)
		{
			turn_char_code(h->rchild);
		}
	}
	string turn_string_code(string src)  //返回字符串的哈夫曼编码
	{
		string h_string;
		turn_char_code(root);
		for(int j=0;j<src.length();j++)
		{
			for(int k=0;k<leaf_char.size();k++)
			{
				if(src[j]==leaf_char[k])
				h_string=h_string+leaf_code[k];
			}
		}
		return h_string;
	}
	string deCode(string src)
	{
		string s;
		for(int j=0;j<src.length();)
		{
			for(int k=0;k<leaf_char.size();k++)
			{
				int code_length=leaf_code[k].length();
				if(src.substr(j,code_length)==leaf_code[k])     //以j开头的code_length个字符为字串与leaf_code对比
				{
					s=s+leaf_char[k];
					j=j+code_length;
				}
			}
		}
		return s;
	}
};
string huffmancoding(const string &src)
{
	cout << "=========== Huffman coding ===========" << endl;
	cout << "Input string   : " << src << endl;

	string destCode;
	/// 在此处添加编码代码,输入为src,输出为destCode
	
	int p[26]; 
	char c[26];
	c[0]=src[0];      
	  //字符串的各字符不重复地放入c[]
		int c_count=1;  //数组c[]的数量
		for(int j=0;j<src.length();j++)
		{
			int k=0;
			for(k=0;k<c_count;k++)    //寻找当前的字符在c[]中是否有记录
			{
				if(c[k]==src[j])       //有记录则跳出循环 且k=0
				{
					k=0;
					break;
				}
			}
			if(k>0)         //在c[]中未找到当前字符
			{
				c_count++;
				c[c_count-1]=src[j];
				
			}
		
		}
	  //计算src中各字符的出现次数 相对应记录于p[]
		for(int j=0;j<=c_count;j++)
		{
			p[j]=0;
			for(int h=0;h<src.length();h++)
			{
				if(src[h]==c[j])
					p[j]++;
			}
		}

	
		HuffmanTree h_tree;
		h_tree.build_tree(p,c,c_count);
	cout << "===== Code for each char :" << endl;	
	destCode=h_tree.turn_string_code(src);			
	cout << "Coded string   : " << destCode << endl;

	/// 此处输出每个字符的编码

	//哈夫曼树类
class Node
{
public:
<span style="white-space:pre">	</span>Node *rchild;
<span style="white-space:pre">	</span>Node *lchild;
<span style="white-space:pre">	</span>Node *parent;
<span style="white-space:pre">	</span>int weight;  //权值
<span style="white-space:pre">	</span>char ch;     //叶子字符
<span style="white-space:pre">	</span>char node_code;  //每个字符对应的路径(左0右1)
<span style="white-space:pre">	</span>Node(){};
};
class HuffmanTree
{
protected:
<span style="white-space:pre">	</span>Node *root;   //根节点
<span style="white-space:pre">	</span>vector<char> leaf_char;    //从叶节点得到字符
<span style="white-space:pre">	</span>vector<string>  leaf_code ;   //保存每个字符的编码
public:
<span style="white-space:pre">	</span>HuffmanTree(int p ,char c){root=new Node();root->weight=p;root->ch=c;}
<span style="white-space:pre">	</span>HuffmanTree(){root=new Node();}
<span style="white-space:pre">	</span>void build_tree(int pro[],char cha[],int count)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>HuffmanTree *r[26];
<span style="white-space:pre">		</span>for(int j=0;j<count;j++)     //初始化每个字符形成的树
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>r[j]=new HuffmanTree() ;
<span style="white-space:pre">			</span>r[j]->root->ch=cha[j];
<span style="white-space:pre">			</span>r[j]->root->weight=pro[j];
<span style="white-space:pre">			</span>
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>for(int j=0;j<count-1;j++)    //找出数组中根节点权值最小的两个 合并
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>for(int i=j+1;i<count;i++)      //找出最小权值的树放入r[j]
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(r[j]->root->weight>r[i]->root->weight)
<span style="white-space:pre">				</span>{
<span style="white-space:pre">					</span>HuffmanTree *temp;
<span style="white-space:pre">					</span>temp=r[i];
<span style="white-space:pre">					</span>r[i]=r[j];
<span style="white-space:pre">					</span>r[j]=temp;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>for(int i=j+2;i<count;i++)     //找出最小权值的树放入r[j+1]
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(r[j+1]->root->weight>r[i]->root->weight)
<span style="white-space:pre">				</span>{
<span style="white-space:pre">					</span>HuffmanTree *temp;
<span style="white-space:pre">					</span>temp=r[i];
<span style="white-space:pre">					</span>r[i]=r[j+1];
<span style="white-space:pre">					</span>r[j+1]=temp;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>HuffmanTree *t_r=new HuffmanTree();    //过渡用的t_r 生成新的树赋给r[j+1]
<span style="white-space:pre">			</span>t_r->root->lchild=r[j]->root;
<span style="white-space:pre">			</span>r[j]->root->parent=t_r->root;
<span style="white-space:pre">			</span>r[j]->root->node_code='0';      //是parent的左孩子,赋予路径0
<span style="white-space:pre">			</span>t_r->root->rchild=r[j+1]->root;
<span style="white-space:pre">			</span>r[j+1]->root->parent=t_r->root;
<span style="white-space:pre">			</span>r[j+1]->root->node_code='1';      //是parent的左孩子,赋予路径1
<span style="white-space:pre">			</span>t_r->root->weight = r[j]->root->weight+r[j+1]->root->weight;       //左右孩子的权值和
<span style="white-space:pre">			</span>r[j+1]=t_r;
<span style="white-space:pre">			</span>if(j+1==count-1)
<span style="white-space:pre">			</span>root=r[j+1]->root;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>void turn_char_code(Node *h)      //输出每个字符的编码
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>string s;
<span style="white-space:pre">		</span>Node *temp=h;
<span style="white-space:pre">		</span>if(temp->lchild==NULL && temp->rchild==NULL)  //测到根节点
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>char c=temp->ch;
<span style="white-space:pre">			</span>leaf_char.push_back(temp->ch);
<span style="white-space:pre">			</span>while (temp->parent!=NULL)   //有父节点则推测哈夫曼编码
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>s=temp->node_code+s;
<span style="white-space:pre">				</span>temp=temp->parent;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>leaf_code.push_back(s);
<span style="white-space:pre">			</span>cout<<c<<"的哈夫曼编码:"<<s<<endl;


<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if(h->lchild!=NULL)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>turn_char_code(h->lchild);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if(h->rchild!=NULL)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>turn_char_code(h->rchild);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>string turn_string_code(string src)  //返回字符串的哈夫曼编码
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>string h_string;
<span style="white-space:pre">		</span>turn_char_code(root);
<span style="white-space:pre">		</span>for(int j=0;j<src.length();j++)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>for(int k=0;k<leaf_char.size();k++)
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(src[j]==leaf_char[k])
<span style="white-space:pre">				</span>h_string=h_string+leaf_code[k];
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return h_string;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>string deCode(string src)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>string s;
<span style="white-space:pre">		</span>for(int j=0;j<src.length();)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>for(int k=0;k<leaf_char.size();k++)
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>int code_length=leaf_code[k].length();
<span style="white-space:pre">				</span>if(src.substr(j,code_length)==leaf_code[k])     //以j开头的code_length个字符为字串与leaf_code对比
<span style="white-space:pre">				</span>{
<span style="white-space:pre">					</span>s=s+leaf_char[k];
<span style="white-space:pre">					</span>j=j+code_length;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return s;
<span style="white-space:pre">	</span>}
};
string huffmancoding(const string &src)
{
<span style="white-space:pre">	</span>cout << "=========== Huffman coding ===========" << endl;
<span style="white-space:pre">	</span>cout << "Input string   : " << src << endl;


<span style="white-space:pre">	</span>string destCode;
<span style="white-space:pre">	</span>/// 在此处添加编码代码,输入为src,输出为destCode
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>int p[26]; 
<span style="white-space:pre">	</span>char c[26];
<span style="white-space:pre">	</span>c[0]=src[0];      
<span style="white-space:pre">	</span>  //字符串的各字符不重复地放入c[]
<span style="white-space:pre">		</span>int c_count=1;  //数组c[]的数量
<span style="white-space:pre">		</span>for(int j=0;j<src.length();j++)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>int k=0;
<span style="white-space:pre">			</span>for(k=0;k<c_count;k++)    //寻找当前的字符在c[]中是否有记录
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(c[k]==src[j])       //有记录则跳出循环 且k=0
<span style="white-space:pre">				</span>{
<span style="white-space:pre">					</span>k=0;
<span style="white-space:pre">					</span>break;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>if(k>0)         //在c[]中未找到当前字符
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>c_count++;
<span style="white-space:pre">				</span>c[c_count-1]=src[j];
<span style="white-space:pre">				</span>
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>  //计算src中各字符的出现次数 相对应记录于p[]
<span style="white-space:pre">		</span>for(int j=0;j<=c_count;j++)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>p[j]=0;
<span style="white-space:pre">			</span>for(int h=0;h<src.length();h++)
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(src[h]==c[j])
<span style="white-space:pre">					</span>p[j]++;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}


<span style="white-space:pre">	</span>
<span style="white-space:pre">		</span>HuffmanTree h_tree;
<span style="white-space:pre">		</span>h_tree.build_tree(p,c,c_count);
<span style="white-space:pre">	</span>cout << "===== Code for each char :" << endl;<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>destCode=h_tree.turn_string_code(src);<span style="white-space:pre">			</span>
<span style="white-space:pre">	</span>cout << "Coded string   : " << destCode << endl;

<span style="white-space:pre">	</span><pre code_snippet_id="314458" snippet_file_name="blog_20140427_1_8226741" name="code" class="cpp"><span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space:pre">		</span>string destDecode;</span>

/// 此处输出每个字符的编码

/// 在此处添加解码代码,输入为destCode,输出为destDecode
destDecode=h_tree.deCode(destCode);
cout << "Decoded string : " << destDecode << endl;
return destDecode;
}
 


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值