哈夫曼编码c语言实现

哈夫曼编码的原理看
百度百科
先生成一个哈夫曼树,参考
哈夫曼树c语言实现
生成接近等长码
须要注意的是,为了缩短码长方差,且编出的码更接近于等长码,排序的时候,第一优先级为概率大小,第二优先级为左节点是否为空

int cmp(left a, left b)
{

	if (a.data == b.data)
	{
		if (a.left != NULL)
		{
			return 1;
		}
		if (b.left != NULL)
		{
			return 0;
		}
	}
	else 
		return a.data > b.data ? 1 : 0;
}

用dfs读取哈夫曼编码
读取哈夫曼编码的时候,从树的根部开始读,能往左走,就读入一个‘1’,能往右走就读入一个‘0’,遇上左节点为空,说明已经读取了一个编码,同时,我们读到的这个节点的概率就是这个编码对应的概率。

void print_treef(left* root,int n,int *now,int len)//就是dfs,
//函数中参数的含义依次为当前节点,编码总数(实际没有用),当前读取的编码编号,深度。
{
	int t = 0;
		if (root->left != NULL)
		{
			sprintf(temp+len, "%d", 1);
			print_treef(root->left, n,now,len+1);
			t = 1;
		}
		 if (root->right != NULL)
		{
			 sprintf(temp + len, "%d", 0);//相当于temp[len]=‘0’;
			print_treef(root->right, n,now,len+1);
			t = 1;
		}
		 if (t == 0)
		 {
			 sprintf(ans[*now].code, "%s", temp);
			 ans[*now].p = root->data;
		//	 ans[*now].code[len]= '\0';
			 *now += 1;
		 }
}

源代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct hahahacode
{
	double p;
	char code[10];
}Code;
Code ans[10];
typedef struct hahahahahaha
{
	struct hahahahahaha* father;
	struct hahahahahaha* left;
	struct hahahahahaha* right;
	double data;
}left;
left* creat_left()
{
	left* s = (left*)malloc(sizeof(left));
	s->father = NULL;
	s->left = NULL;
	s->right = NULL;
	return s;
}
int cmp(left a, left b)
{

	if (a.data == b.data)
	{
		if (a.left != NULL)
		{
			return 1;
		}
		if (b.left != NULL)
		{
			return 0;
		}
	}
	else 
		return a.data > b.data ? 1 : 0;
}
void sortans(int n)
{
	int i = 0, j = 0, t;
	Code tt;
	for (i = 0; i < n - 1; i++)
	{
		for (j = 0; j < n - 1-i; j++)
		{
			if (ans[j].p == ans[j + 1].p)
			{
				if (strcmp(ans[j].code, ans[j + 1].code) >= 0)
				{
					tt = ans[j], ans[j] = ans[j + 1]; ans[j + 1] = tt;
				}
			}
			else if (ans[j].p<ans[j+1].p)
			{
				tt = ans[j], ans[j] = ans[j + 1]; ans[j + 1] = tt;
			}
		}
	}// 蹩脚插排
}
void sort(left* a[], int n)
{
	int i = 0, j = 0, t;
	left* tt;
	for (i = 0; i < n - 1; i++)
	{
		for (j = 0; j < n - 1-i; j++)
		{
			if (cmp(*a[j], *a[j + 1]))
			{
				tt = a[j], a[j] = a[j + 1]; a[j + 1] = tt;
			}
		}
	}// 蹩脚插排
}
left* built_tree(double* a, int n)
{
	int i = 0;
	left* b[205];
	while (i < n)
	{
		left* s = creat_left();
		s->data = a[i];

		b[i] = s;//printf("%d ", b[i]->data);
		i++;
	}
	int j = 0;
	while (j < 150)
	{
		b[i + j] = creat_left();
		j++;
	}
	i = n / 2 - 1;
	sort(b, n);
	//printf("%d", b[0]->data);
	left* s = NULL;
	while (n > 1)
	{
		double dad = b[0]->data + b[1]->data;
		s = creat_left();
		s->data = dad;
		b[0]->father = s;
		b[1]->father = s;
		s->left = b[0];
		s->right = b[1];
		b[0] = s;
		b[1] = b[n - 1];
		n--;
		sort(b, n);
	}
	return s;
}
void print_tree(left* root, int deep)
{
	int  i = 0;
	while (i < deep)
	{
		printf("-");
		i++;
	}
	printf("%.2f\n", root->data);
	if (root->left != NULL)
	{
		print_tree(root->left, deep * 2);
	}
	if (root->right != NULL)
	{
		print_tree(root->right, deep * 2);
	}
}
char temp[100];
void print_treef(left* root,int n,int *now,int len)
{
	int t = 0;
		if (root->left != NULL)
		{
			sprintf(temp+len, "%d", 1);
			print_treef(root->left, n,now,len+1);
			t = 1;
		}
		 if (root->right != NULL)
		{
			 sprintf(temp + len, "%d", 0);
			print_treef(root->right, n,now,len+1);
			t = 1;
		}
		 if (t == 0)
		 {
			 sprintf(ans[*now].code, "%s", temp);
			 ans[*now].p = root->data;
		//	 ans[*now].code[len]= '\0';
			 *now += 1;
		 }
}
int main()
{
	double a[10] = {0.4,0.1,0.2,0.2,0.1};
	left* root = built_tree(a, 5);
	int len = 0;
	printf("树\n");
	print_tree(root, 1);

	printf("编码\n");
	print_treef(root, 1,&len,0);
	sortans(5);
	for (int i = 0; i < 5; i++)
	{
		printf("u%d: p=%.2f ", i + 1,ans[i].p);
		printf("%s\n", ans[i].code);
	}
}

运行结果

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
哈夫曼编码是一种用于数据压缩的算法。下面是C语言实现哈夫曼编码的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NODE_NUM 1000 typedef struct { int weight; int parent, lchild, rchild; } HuffmanNode; typedef struct { int bit[MAX_NODE_NUM]; int start; } HuffmanCode; void HuffmanCoding(HuffmanNode *huffmanTree, HuffmanCode *huffmanCode, int n) { int i, j, parent, left, right; for (i = 0; i < n; i++) { huffmanTree[i].parent = -1; huffmanTree[i].lchild = -1; huffmanTree[i].rchild = -1; } for (i = 0; i < n-1; i++) { int min1 = MAX_NODE_NUM, min2 = MAX_NODE_NUM; left = right = -1; for (j = 0; j < n+i; j++) { if (huffmanTree[j].parent == -1 && huffmanTree[j].weight < min1) { min2 = min1; right = left; min1 = huffmanTree[j].weight; left = j; } else if (huffmanTree[j].parent == -1 && huffmanTree[j].weight < min2) { min2 = huffmanTree[j].weight; right = j; } } huffmanTree[left].parent = n + i; huffmanTree[right].parent = n + i; huffmanTree[n + i].lchild = left; huffmanTree[n + i].rchild = right; huffmanTree[n + i].weight = min1 + min2; } for (i = 0; i < n; i++) { HuffmanCode *code = &huffmanCode[i]; code->start = n - 1; parent = huffmanTree[i].parent; while (parent != -1) { if (huffmanTree[parent].lchild == i) { code->bit[code->start] = 0; } else { code->bit[code->start] = 1; } code->start--; i = parent; parent = huffmanTree[parent].parent; } } } int main() { int i, n; HuffmanNode huffmanTree[MAX_NODE_NUM]; HuffmanCode huffmanCode[MAX_NODE_NUM]; printf("请输入叶子结点的个数:"); scanf("%d", &n); printf("请输入每个叶子结点的权重:"); for (i = 0; i < n; i++) { scanf("%d", &huffmanTree[i].weight); } HuffmanCoding(huffmanTree, huffmanCode, n); printf("哈夫曼编码表:\n"); for (i = 0; i < n; i++) { printf("结点%d的哈夫曼编码为:", i); int j; for (j = huffmanCode[i].start + 1; j < n; j++) { printf("%d", huffmanCode[i].bit[j]); } printf("\n"); } return 0; } ``` 该代码中定义了两个结构体:`HuffmanNode`表示哈夫曼树中的结点,包括权值、父结点、左孩子和右孩子;`HuffmanCode`表示哈夫曼编码,包括二进制位以及起始位置。 在`HuffmanCoding`函数中,首先初始化哈夫曼树的每个结点,然后依次求出每个非叶子结点,直到只剩下一个根结点。接着遍历每个叶子结点,求出其哈夫曼编码。最后输出哈夫曼编码表。 在主函数中,首先输入叶子结点的个数和权重,然后调用`HuffmanCoding`函数求出哈夫曼编码,最后输出哈夫曼编码表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值