Haffman1

#include <stdio.h>
#include <malloc.h>
#include <string.h>

typedef struct{
	unsigned int weight;
	unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char** HuffmanCode;

void MinTwoSelect(HuffmanTree HT,int endindex,int &s1,int &s2);
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n);
void PrintHuffmanCode(HuffmanCode HC,int n);

int main()
{
	HuffmanTree HT;
	int w[8] = {7,19,2,6,32,3,21,10};
	HuffmanCode HC; 
	HuffmanCoding(HT,HC,w,8);
	PrintHuffmanCode(HC,8);
	return 0;
}

void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
{
	if(n<=1) return;   //如果只有1个字符需要编码,则无需操作
	
	int m = 2 * n - 1;    //n个字符(叶子节点也为n个)需要2n-1个存储空间
	
	HT = (HuffmanTree) malloc ( ( m + 1 ) * sizeof(HTNode));  //0号空间不用
		
	//初始化HT,前n个节点保存Huffman树权重信息,后面直接初始化为0 
	for(int i = 1;i<=n;++i,++w)
	{
		HT[i].weight = *w;
		HT[i].parent = 0;
		HT[i].lchild = 0;
		HT[i].rchild = 0;
	} 
	
	for(int i=n+1;i<=m;i++)
	{
		HT[i].weight = 0;
		HT[i].parent = 0;
		HT[i].lchild = 0;
		HT[i].rchild = 0;
	} 
	
	//构造Huffman树
	//在HT[1]至HT[i-1]选择parent为0且weight最小的两个节点,其序号分别为S1和S2
	int s1,s2;
	
	for(int i=n+1; i<=m;i++)
	{
		MinTwoSelect(HT,i-1,s1,s2);
				
		HT[s1].parent = i;
		HT[s2].parent = i;
		HT[i].lchild = s2;
		HT[i].rchild = s1;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
	}
	
	/*
	//从叶子节点到根逆向求每个字符的Huffman编码
	HC = (HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量 
	char* cd = (char*)malloc(n*sizeof(char)); //分配求编码的工作空间
	cd[n-1] = '\0' ;//编码结束符号
	
	
	int start;
	for(int i = 1;i<= n;i++)   //逐个字符求编码 
	{
		start = n-1;   //编码结束符的位置
		
		for(int c = i,f = HT[i].parent; f!=0; c = f, f = HT[f].parent)  //从叶子节点到根节点逆向求编码
		{
		 	if(HT[f].lchild == c) 
			 {
			 	cd[--start] = '1';	
			 } 
			 else
			 {
			 	cd[--start] = '0';
			 }
		} 
		
		
		HC[i] = (char*)malloc((n-start)*sizeof(char)); //为第i个字符编码分配空间
		
		strcpy(HC[i],&cd[start]); 
	}
	
	free(cd);	
	
	*/
	
	//无栈非递归遍历Huffman树,求Huffman编码
	HC =   (HuffmanCode)malloc((n+1)*sizeof(char*));
	
	char* cd = (char*)malloc(n*sizeof(char)); //分配求编码的工作空间
	//cd[n-1] = '\0' ;//编码结束符号
	
	int p = m,cdlen = 0;
	
	for(int i = 1; i<= m; ++i)
	{
		HT[i].weight = 0;   //用于遍历Huffman树时保存节点状态标志 		
	}
	
	
	
	while(p)
	{
		if(HT[p].weight == 0)  //向左 
		{
			HT[p].weight = 1;
			
			if(HT[p].lchild != 0)
			{
				p = HT[p].lchild;
				cd[cdlen] = '0';
				cdlen++;
			} 
			else if(HT[p].rchild == 0)  //登记叶子节点的字符编码 
			{
				HC[p] = (char*) malloc ((cdlen+1)*sizeof(char));
				cd[cdlen] = '\0';
				strcpy(HC[p],cd);   //复制编码串 
			}
		}
		else if(HT[p].weight == 1)  //向右 
		{
			HT[p].weight = 2;
			
			if(HT[p].rchild != 0)
			{
				p = HT[p].rchild;
				cd[cdlen] = '1';
				cdlen++;
			}
		}
		else
		{  //HT[p].weight == 2 代表退回 
			HT[p].weight = 0;      //退回到父节点,编码长度减1 
			p = HT[p].parent;
			--cdlen;
		} 		
	} 		
}


void MinTwoSelect(HuffmanTree HT,int endindex,int &s1,int &s2)
{			
	HuffmanTree p = HT;
	
	HT[0].weight = 10000;  //初始化第一个空间为“权重和”不可能到达的值 
		
	s1 = s2 = 0;    //s1保存第二小数据,s2保存第一小数据 
	
	for(int i =1; i <= endindex; i++)
	{		
		
		if(HT[i].parent != 0 || HT[i].weight > HT[s1].weight)  //如果有父节点,则代表已经处理过,则跳过 
			continue;
		
		if(HT[i].weight < HT[s1].weight)
		{
			s1 = i; 
		} 
				
		if(HT[s1].weight < HT[s2].weight)
		{
			int temp = s1;
			s1 = s2;
			s2 = temp;	
		} 
	}
}

void PrintHuffmanCode(HuffmanCode HC,int n)
{
	for(int i=1;i<=n;i++)
	{
		printf("第%d个字符的编码为:%s\n",i,HC[i]);	
	}	
} 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值