哈夫曼树(C语言简单实现)

本文介绍了哈夫曼树的原理和C语言实现,包括哈夫曼算法描述、哈夫曼编码、算法分析和简单代码实现。通过构建带权路径长度最小的二叉树,实现哈夫曼编码,对给定字符串输出哈夫曼编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈夫曼树(C语言简单实现)

本文参考自《大话数据结构》,至于原理图那些,这里就不赘述了,网上很多,自己找。下面做了简单代码实现,代码依然存在较多缺陷,但是基本可运行,不喜勿喷,有改进和建议欢迎评论区评价。

树的路径长度就是从树根到每一结点的路径长度之和。

结点的带权的路径长度为从该结点到树根之间的路径长度与结点上权的乘积。树的带权路径长度为树中所有叶子结点的带权路径长度之和。假设有n个权值{w1,w2,…,wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权wk,每个叶子的路径长度为1k,我们通常记作WLP,其中带权路径长度WLP最小的二叉树称为哈夫曼树(最优二叉树)

哈夫曼算法描述

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

哈夫曼编码

将左孩子编码为0,右孩子编码为1。

编码中非0即1,若要设计长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码的前缀,这种编码称为前缀编码

编码和解码都要用到哈夫曼树,否则解不出码。

一般地,设需要编码的字符集为{d1,d2,…,dn},各个字符在电文中出现的次数或频率集合为{w1,w2,…,wn},以d1,d2,…,dn作为叶子结点,以w1,w2,…,wn作为相应叶子结点的权值来构造一棵哈夫曼树。规定哈夫曼的左分支代表0,右分支代表1,则从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码,这就是哈夫曼编码。

算法分析

主要就是在构建哈夫曼树的时候,分了4种情况:

  • 生成3个新结点:父结点,左右孩子结点;
  • 生成2个结点:父结点和左孩子或者父结点和右孩子;
  • 生成1个结点:父结点,左右孩子直接链接结点;

另一个就是编码的时候,采用的是二叉树遍历+栈的先进后出机制来存储0和1编码。

最后一个就是这份代码还有很多可以优化的地方,比如:

  • 构建树的时候4种情况里,可以把出现情况比较多的放前面,减少判断的次数;
  • 左右孩子大小问题;
  • 构建树的过程比较复杂,可以优化;
  • 设定的哈夫曼树结构复杂,可以拆分等…

简单实现

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

typedef char TElemType;	//数据域类型 

/* 栈 */
struct StackNode{
   
	char chs;
	StackNode* next;
};

struct Stack{
   
	StackNode* top;
	int count;
};

//声明一个全局栈,用来存储编码 
Stack* s = (Stack*)malloc(sizeof(Stack));

struct HaffmanNode{
   
	TElemType data;	//数据域 
	int weight;	//权重
	HaffmanNode *lchild, *rchild;	//左右孩子 
	//编码值,因为main函数里设置的字符串s长度为20
	char code[10];
	int born;	//标志,该结点是不是生成的
	int codeLength;
};

/* 出栈 */
void pop(){
   
	if(s->count != 0){
   
		StackNode* temp = (StackNode*)malloc(sizeof(StackNode));
		temp = s->top;
		s->top = temp->next;
		free(temp);
		s->count--;
	}
}

/* 入栈 */
void push(char ch){
   
	StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
	newNode->chs = ch;
	newNode->next = s->top;
	s->top = newNode;
	s->count++;
} 

/* 交换函数 */
void swap(HaffmanNode* haffman, int i, int j){
   
	HaffmanNode temp;
	temp.data = haffman[i
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值