7-4哈夫曼编码

7-4 哈夫曼编码

本题要求字符的哈夫曼编码,注意建立的哈夫曼树严格按照左小右次小的顺序,并且哈夫曼编码时严格按照左‘0’右‘1’进行编码。

输入格式:

输入是各个字符在通信中出现的频率

输出格式:

输出是各个字符的哈夫曼编码,每个字母占一行

输入样例

A:2
B:3
C:6
D:7
E:10
F:19
G:21
H:32

输出样例

A:10000
B:10001
C:1001
D:1010
E:1011
F:00
G:01
H:11

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

#define MAX 100;
#define CHARLEN 50;

typedef char **HuffmanCode;
//字符串数组类型
struct HuffNode		          //定义哈夫曼树结点
{
	int weight;			         //权值
	char name;
	int parent, leftchild, rightchild;  //父结点与左右孩子
};
typedef struct HuffNode *HtNode;
typedef struct HuffTreeNode   //定义哈夫曼树
{
	int n;	            //哈夫曼树叶子结点个数
	int root;           //哈夫曼树树根
	HtNode  ht;         //指向哈夫曼树的指针
}*HuffTree;

int count=0;

int *GetFrequency(int num, char * name) //读入自选文件或默认文件进行字频分析。
{
	int i;
	int LEN = CHARLEN  //50
	int *freq = (int *)malloc(sizeof(int)*LEN);
	//初始化fre数组
	for (i = 0; i < LEN; i++){
		freq[i] = 0;
	}
	char ch;
	int n;
	for(i = 0;i<num;i++){
		scanf("%c", &ch);
		getchar();
		scanf("%d", &n);
		getchar();
		freq[ch - 0x41] = n;
		name[ch - 0x41] = ch;
	}
	return freq;
}


//n为叶结点个数
HuffTree CreateHuffmanTree(int n, int *w, char*name)
{
	HuffTree pht;
	int i, j, x1, x2, min1, min2;
	pht = (HuffTree)malloc(sizeof(struct HuffTreeNode));
	if (pht == NULL){
		printf("Out of space!!\n");
		return pht;
	}
	//为哈夫曼树申请2*N-1个空间
	pht->ht = (HtNode)malloc(sizeof(struct HuffNode)*(2 * n - 1));
	
	if (pht->ht == NULL){
		printf("Out of space!!\n");
		return pht;
	}
	//初始化哈夫曼树
	for (i = 0; i < 2 * n - 1; i++){
		pht->ht[i].leftchild = -1;	//初始化叶结点左孩子
		pht->ht[i].rightchild = -1;	//初始化叶结点右孩子
		pht->ht[i].parent = -1;	//初始化叶结点的父亲
		if (i < n){
			pht->ht[i].weight = w[i];
			pht->ht[i].name = name[i];
		}
			
		else
			pht->ht[i].weight = -1;
	}
	for (i = 0; i < n - 1; i++){
		min1 = MAX;			//m1代表极小值
		min2 = MAX;			//m2代表次小值
		x1 = -1;			//极小值下标
		x2 = -1;			//次小值下标
		//找到极小值下标x1并把极小值赋值给m1
		for (j = 0; j < n + i; j++){
			if (pht->ht[j].weight < min1&&pht->ht[j].parent == -1){
				min2 = min1;
				x2 = x1;
				min1 = pht->ht[j].weight;
				x1 = j;
			}
			//找到次小值下标x2并把次小值赋值给min2
			else if (pht->ht[j].weight < min2&&pht->ht[j].parent == -1){
				min2 = pht->ht[j].weight;
				x2 = j;
			}
		}
		
		//构建x1,x2的父结点
		pht->ht[x1].parent = n + i;	//x1父结点下标
		pht->ht[x2].parent = n + i;	//x2父结点下标
		pht->ht[n + i].weight = min1 + min2;//父结点的权值为极小值加次小值
		pht->ht[n + i].leftchild = x1;	//父结点的左孩子为x1
		pht->ht[n + i].rightchild = x2;	//父结点的右孩子的x2
	}
	pht->root = 2 * n - 2;//哈夫曼树根结点位置
	pht->n = n;
	return pht;

}

void  CreateHuffmanCode(HuffTree pht,HuffmanCode *HC, int n)
{
	//分配n个字符串编码的空间
	*HC = (HuffmanCode)malloc(sizeof(char*)*(n));
	//开辟一个长度为n的字符数组用来临时存放编码
	char* cd = (char*)malloc(sizeof(char)*n);
	cd[n-1] = '\0';  //字符串结束符
	int i;
	for(i = 0; i < n; i++)
	{
		int start = n-1; //从字符数组的末尾开始赋值
		int c = i;       //
		int f = pht->ht[i].parent; //找出父节点
		//当父结点为-1时,说明到达根节点,编码结束
		while(f != -1)
		{
			start--;
			//结点c是f的左孩子,则生成代码0,否则就是右孩子生成代码1
			if(pht->ht[f].leftchild == c)
				cd[start] = '0';
			else
				cd[start] = '1';
			//将父结点作为新的子树,f为新子树的父节点
			c = f;
			f = pht->ht[f].parent;
		}
		//为第i个字符串编码分配大小合适的空间,把临时存放的复制进去
		(*HC)[i] = (char*)malloc(sizeof(char)*(n-start));
		//从start的位置开始复制
		strcpy((*HC)[i], &cd[start]);
	}
	free(cd);
}


int main()
{
	int i;
	int *text;//存放字符的频率
	char name[50];//存放字符的名字
	int num = 8;//节点数量
	text = GetFrequency(num, name);//获得字符频率
	HuffTree pht;           //定义哈夫曼树
	HuffmanCode HC;   //哈夫曼编码指针(二重指针)
	pht = CreateHuffmanTree(num, text, name);    //创建哈夫曼树
	CreateHuffmanCode(pht,&HC,num);  //创建哈夫曼编码表
	for(i = 0;i < num;i++)   //位置一样的,所以遍历即可
	{
		if(i<num-1){
			printf("%c:%s\n",pht->ht[i].name, HC[i]);
		}
		else{
			printf("%c:%s",pht->ht[i].name, HC[i]);
		}
		
	}
	return 0;
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值