贪心算法---Huffman编码---神秘电报密码

贪心策略:每次从数的集合中取出没有双亲且权值最小的两棵树作为左右子树。

Huffman编码的基本思想:以字符的使用频率作为权构建一棵Huffman树,然后利用Huffman树对字符进行编码。

#include <bits/stdc++.h>
using namespace std;

#define MAXBIT 100
#define MAXVALUE 10000
#define MAXLEAF 30
#define MAXNODE MAXLEAF*2-1

typedef struct{
	double weight;//权值
	int parent;//双亲
	int lchild;//左孩子 
	int rchild;
	char value;//该节点表示的字符 
}HNodeType;//结点结构体 

typedef struct{
	int bit[MAXBIT];//存储编码的数组
	int start;//编码开始的标志 
}HCodeType;//编码结构体
HNodeType HuffNode[MAXNODE];//定一个结点结构体数组
HCodeType HuffCode[MAXLEAF];//定义一个编码结构体数组
//构造Huffman树
void HuffmanTree(HNodeType HuffNode[MAXNODE],int n)
{
	int i,j,x1,x2;
	double m1,m2;
	//i,j:循环变量,m1,m2:构造Huffman树不同过程中两个最小权值结点的权值,x1,x2:构造Huffman树不同过程中两个最小权值结点在数组中的序号。
	//初始化存放Huffman数组HuffNode[]中的结点
	for(i=0;i<2*n-1;i++)
	{
		HuffNode[i].weight=0;//权值
		HuffNode[i].parent=-1;//双亲
		HuffNode[i].lchild=-1;//左孩子 
		HuffNode[i].rchild=-1; 
	} 
	//输入n个叶子结点的权值
	for(i=0;i<n;i++)
	{
		cout<<"Please input value and weight of leaf node"<<i+1<<endl;
		cin>>HuffNode[i].value>>HuffNode[i].weight; 
	} 
	for(i=0;i<n-1;i++)//执行n-1次合并 
	{
		m1=m2=MAXVALUE;//m1,m2中存放两个无父结点且结点权值最小的两个点
		x1=x2=-1;//找出所有结点中权值最小,无父节点的两个结点并合并之为一棵二叉树
		for(j=0;j<n+i;j++)
		{
			if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1)
			{
				m2=m1;
				x2=x1;
				m1=HuffNode[j].weight;
				x1=j;
			}
			else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
			{
				m2=HuffNode[j].weight;
				x2=j;
			}
		} 
		//设置找到的两个子结点x1,x2的父结点信息
		//更新新树的信息
		HuffNode[x1].parent=n+i;//x1的父亲为新结点编号n+i
		HuffNode[x2].parent=n+i;//x2的父亲为新结点编号n+i
		HuffNode[n+i].weight=m1+m2;//新结点权值为两个最小权值之和m1+m2 
		HuffNode[n+i].lchild=x1;//新结点n+i的左孩子为x1
		HuffNode[n+i].rchild=x2;//新结点n+i的右孩子为x2
		cout<<"x1.weight and x2.weight in round"<<i+1<<"\t"<<HuffNode[x1].weight<<"\t"<<HuffNode[x2].weight<<endl;//用于测试 
	}
} 
//Huffman树编码
void HuffmanCode(HCodeType HuffCode[MAXLEAF],int n)
{
	HCodeType cd;//定义一个临时变量来存放求解编码时的信息
	int i,j,c,p;
	for(i=0;i<n;i++)
	{
		cd.start=n-1;
		c=i;//i为叶子结点编号
		p=HuffNode[c].parent;
		while(p!=-1)
		{
			if(HuffNode[p].lchild==c)
			   cd.bit[cd.start]=0;
			else
			   cd.bit[cd.start]=1;
			cd.start--;//求编码的低一位
			c=p;//c,p变量上移,准备下一循环
			p=HuffNode[c].parent;//设置下一循环条件 
		} 
		//把叶子结点的编码信息,从临时编码cd中复制出来,放入编码结构体数组
		for(j=cd.start+1;j<n;j++)
		    HuffCode[i].bit[j]=cd.bit[j];
		HuffCode[i].start=cd.start; 
	} 
} 
int main()
{
	int i,j,n;
	cout<<"Please input n:"<<endl;
	cin>>n;
	HuffmanTree(HuffNode,n);//构造Huffman树
	HuffmanCode(HuffCode,n);//Huffman树编码
	//输出已保存好的所有存在编码的Huffman编码
	for(i=0;i<n;i++)
	{
		cout<<HuffNode[i].value<<":HuffmanCode is:";
		for(j=HuffCode[i].start+1;j<n;j++)
		    cout<<HuffCode[i].bit[j];
		    cout<<endl;
	}	 
	return 0;
}
发布了106 篇原创文章 · 获赞 53 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43595030/article/details/104080973