⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 哈夫曼编码.cpp

📁 贪心算法解一系列算法经典问题
💻 CPP
字号:
// 哈夫曼编码(算法)

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

typedef char *HuffmanCode;  //动态分配数组,存储哈夫曼编码

typedef struct
{
	unsigned int weight;  //用来存放各个结点的权值
	unsigned int parent,LChild,RChild;  //指向双亲、孩子结点的指针
} HTNode, *HuffmanTree;  //动态分配数组,存储哈夫曼树

//选择两个parent为0,且weight最小的结点s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
	int i,min;
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent==0)
		{
			min=i;
			break;
		}
	}
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent==0)
		{
			if((*ht)[i].weight<(*ht)[min].weight)
				min=i;
		}
	}
	*s1=min;
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent==0 && i!=(*s1))
		{
			min=i;
			break;
		}
	}
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent==0 && i!=(*s1))
		{
			if((*ht)[i].weight<(*ht)[min].weight) min=i;
		}
	}
	*s2=min;
}

//构造哈夫曼树ht。w存放已知的n个权值
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
	int m,i,s1,s2;
	m=2*n-1;
	*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	for(i=1; i<=n; i++)  //1--n号存放叶子结点,初始化
	{
		(*ht)[i].weight=w[i];
		(*ht)[i].LChild=0;
		(*ht)[i].parent=0;
		(*ht)[i].RChild=0;
	}
	for(i=n+1; i<=m; i++)
	{
		(*ht)[i].weight=0;
		(*ht)[i].LChild=0;
		(*ht)[i].parent=0;
		(*ht)[i].RChild=0;
	} //非叶子结点初始化
	printf("\nHuffmanTree: \n");
	for(i=n+1; i<=m; i++)   //创建非叶子结点,建哈夫曼树
	{	//在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0
		//且weight最小的结点,其序号分别赋值给s1、s2
		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;
		printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight);
	}
	printf("\n");
} //哈夫曼树建立完毕

//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
{
	char *cd;
	int i,start,p;
	unsigned int c;
	hc=(HuffmanCode *)malloc((n+1)*sizeof(char *));  //分配n个编码的头指针
	cd=(char *)malloc(n*sizeof(char));  //分配求当前编码的工作空间
	cd[n-1]='\0';  //从右向左逐位存放编码,首先存放编码结束符
	for(i=1; i<=n; i++)  //求n个叶子结点对应的哈夫曼编码
	{
		start=n-1;  //初始化编码起始指针
		for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent)  //从叶子到根结点求编码
			if( (*ht)[p].LChild==c) cd[--start]='0';  //左分支标0
			else cd[--start]='1';  //右分支标1
		hc[i]=(char *)malloc((n-start)*sizeof(char));  //为第i个编码分配空间
		strcpy(hc[i],&cd[start]);
	}
	free(cd);
	for(i=1; i<=n; i++)
		printf("HuffmanCode of %3d is %s\n",(*ht)[i].weight,hc[i]);
	printf("\n");
}

void main()
{
	HuffmanTree HT;
	HuffmanCode HC;
	int *w,i,n,wei,m;

	printf("\nn = " );
	scanf("%d",&n);
	w=(int *)malloc((n+1)*sizeof(int)); 
	printf("\ninput the %d element's weight:\n",n); 
	for(i=1; i<=n; i++)
	{ 
		printf("%d: ",i); 
		fflush(stdin);
		scanf("%d",&wei);
		w[i]=wei;
	}
	CrtHuffmanTree(&HT,w,n);
	CrtHuffmanCode(&HT,&HC,n);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -