Huffman编码

Huffman算法描述如下:

(1)根据给定的n个权值{w1,w2,...,wn}构成n棵二叉树的集合F={T1,T2,...,Tn},其中每棵二叉树Ti中只有一个带权为wi的根节点,其中左右子树为空。
(2)在F中选取两棵根节点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根节点的权值为其左右子树节点权值之和。
(3)在F中删除这两棵树,同时将新得到的二叉树加入F中.
(4)重复(2)和(3),直到只含一棵树为止。这棵树就是哈夫曼树。


 
#include<iostream>
using namespace std;
//存储树的节点
typedef struct {
	int weight;
	int parent,lchild,rchild;
}HTNode,*HuffmanTree;
//找到s1,s2,tmp(下标)中,值更小的两个节点
//权重更小的节点下标存在s1,次小存在s2
//以下程序类似对三个数进行排序
void compare(HuffmanTree &HT,int &s1,int &s2,int temp)
{
	
	if(HT[s1].weight <=HT[temp].weight &&HT[s1].weight<=HT[s2].weight )
	{
		if(HT[s2].weight >HT[temp].weight )
		s2=temp;
	}
	else if(HT[s2].weight <=HT[temp].weight &&HT[s2].weight <=HT[s1].weight )
	{  
		if(HT[s1].weight >HT[temp].weight )
	
		{    s1=s2;
		     s2=temp;
	
		}
		else
		{
			temp=s1;
			s1=s2;
			s2=temp;
		}
	}
	else
	{
		if(HT[s1].weight <HT[s2].weight )
			s2=s1;
		s1=temp;
	}

}
//在n个节点中选择权重更小的两个节点
void Select(HuffmanTree&HT,int n,int &s1,int &s2)
{
	int i=1,temp;
	while(HT[i].parent !=0) i++;
		s1=i++;
	while(HT[i].parent !=0) i++;
	s2=i++;
	for(;i<=n;i++)
	{
		while(HT[i].parent !=0)i++;
	    temp=i;
		compare(HT,s1 ,s2,temp );
	}
}
//w存储1-n个节点的权重
void HuffmanCoding(HuffmanTree&HT,char**&HC,int*w,int n)
{
	if(n<=1)return;
	int i;
	int s1,s2;
	int m=2*n-1;
	//m+1是因为下标0未被使用
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	//1-n个节点初始化
	for(i=1;i<=n;i++,w++)
	{
		HT[i].weight =*w;
		HT[i].parent =0;
		HT[i].lchild =0;
		HT[i].rchild =0;
	}
	//节点n+1-m初始化为空
	for(;i<=m;i++)
	{
		HT[i].weight =0;
		HT[i].parent =0;
		HT[i].lchild =0;
		HT[i].rchild =0;
	}
	
	for(i=n+1;i<=m;i++){
		//在1-n棵树中选择
		Select(HT,i-1,s1,s2);
		HT[s1].parent=i;HT[s2].parent=i;
		HT[i].lchild=s1;HT[i].rchild=s2;
		HT[i].weight =HT[s1].weight+HT[s2].weight;
	}
	//
	HC=(char**)malloc((n+1)*sizeof(char*));
	char *cd=(char*)malloc(n*sizeof(char));
	cd[n-1]='\0';
	//n为函数的参数
	for(i=1;i<=n;i++)
	{
		int start=n-1;//因为是从叶子到根逆向求编码,所以这里从n-1开始存编码
		//c为当前节点,f为c的父节点,f=HT[f].parent继续得到父节点
		for(int c=i,f=HT[i].parent ;f!=0;c=f,f=HT[f].parent )
			//如果是父节点的左孩子,则记录0
			if(HT[f].lchild ==c)
				cd[--start]='0';
			else
				cd[--start]='1';
		
		HC[i]=(char*)malloc((n-start)*sizeof(char));
		//从位置start开始复制到HC[i]中
		strcpy(HC[i],&cd[start]);
	}
	//释放分配给cd的空间
	free(cd);
}

int main()
{
	HuffmanTree HT;
	int *w;
	int n;
	char **HC;
	cin>>n;
	w=new int[n];
	for(int i=0;i<n;i++)
		cin>>w[i];
	HuffmanCoding(HT,HC,w,n);
	for(i=1;i<=n;i++)
		cout<<HC[i]<<endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值