(编程训练)再回首,数据结构——哈夫曼编码的实现

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会。

希望这些能提供给初学者一些参考。

在VC++6.0下可运行,当初还写了不少注释。

【问题描述】

根据给定字符的使用频率,为其设计哈夫曼编码

【基本要求】

·功能:求出n个字符的哈夫曼编码

·输入:输入n个字符和字符在电文中的使用频率

·输出:n个字符的哈夫曼编码

【模块划分】

1.    初始化哈夫曼树函数 InitHuffmanTree()

2.    输入权值函数 InputWeight()

3.    选择两个权值最小的根节点函数SelectMin()

4.    构造哈夫曼树函数 CreateHuffmanTree()

5.求哈夫曼编码函数 Huffmancode()

/*设计哈夫曼编码*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//Huffman树的数据结构
#define n 8			//叶子数目
#define m (n*2-1)		//Huffman树的节点数

//Huffman树的节点
typedef struct
{
	int weight;
	int lchild,rchild,parent;
}HTNode;

//Huffman树的节点数组
typedef HTNode HuffmanTree[m+1];

//Huffman编码的节点
typedef struct
{
	char ch;
	char code[n+1];
}CodeNode;

//Huffman编码的节点数组
typedef CodeNode HuffmanCode[n+1];

//初始化输入HuffmanTree树的节点
void InitHuffmanTree (HuffmanTree ht)
{
	int i;
	for(i=0;i<=m;i++)
	{
		ht[i].weight=0;
		ht[i].lchild=ht[i].rchild=ht[i].parent=0;
	}
}

//输入HuffmanTree树各节点的权值
void InputHuffmanTree (HuffmanTree ht)
{
	int i;
	for(i=1;i<=n;i++)
	{
		printf("请输入第 %d 个权值: ",i);
		scanf("%d",&ht[i].weight);
	}
	getchar();
}

/*
 * 在ht[1..i]中选择2个权值最小的节点,
 * p1、*p2分别存放最小节点、次小节点的下标
 */
void SelectMin(HuffmanTree ht, int i, int *p1, int *p2)
{
	int j,min1,min2;
	min1=min2=4294967295;
	*p1=*p2=0;
	for(j=1;j<=i;j++)
		if(0==ht[j].parent)
			if(ht[j].weight<min1 || 4294967295==min1)
			{
				if(4294967295!=min1)
				{
					min2=min1;
					*p2=*p1;
				}
				min1=ht[j].weight;
				*p1=j;
			}
			else
				if(ht[j].weight<min2 || 4294967295==min2)
				{
					min2=ht[j].weight;
					*p2=j;
				}
}

//构建Huffman树
void CreateHuffmanTree (HuffmanTree ht)
{
	int i,p1,p2;

	//初始化Huffman树
	InitHuffmanTree(ht);

	//输入Huffman树的权值
	InputHuffmanTree(ht);

	for(i=n+1;i<=m;i++)
	{
		SelectMin(ht,i-1,&p1,&p2);
		ht[p1].parent=ht[p2].parent=i;
		ht[i].lchild=p1;
		ht[i].rchild=p2;
		ht[i].weight=ht[p1].weight+ht[p2].weight;
	}

}

//根据Huffman树求Huffman编码
void CreateHuffmanCode (HuffmanTree ht, HuffmanCode hcd)
{
	int c,p,s,i,j;	//c、p、s分别代表孩子节点、双亲节点、编码开始位置
	char cd[n+1];
	cd[n]='\0';
	printf("请输入字符: ");
	for(i=1;i<=n;i++)
	{
		hcd[i].ch=getchar();
		c=i;
		s=n;
		while(0!=(p=ht[c].parent))	//一直回溯到根节点
		{
			cd[--s]=(c==ht[p].lchild)?'0':'1';
			c=p;
		}
//		strcpy(hcd[i].code,&cd[s]);
		j=0;
		while((hcd[i].code[j++]=cd[s++])!='\0')
			;
	}
	printf("\n");

	//输出各字符的编码
	for(i=1;i<=n;i++)
		printf("第 %d 个字符 %c 的编码为 %s\n",i,hcd[i].ch,hcd[i].code);
}

int main()
{
	HuffmanTree t;
	HuffmanCode h;
	printf("请输入 %d 个权值\n",n);
	CreateHuffmanTree(t);
	CreateHuffmanCode(t,h);
	return 0;
}

时间: 2024-12-06 18:36:41

(编程训练)再回首,数据结构——哈夫曼编码的实现的相关文章

(编程训练)再回首,数据结构——二叉树的前序、中序、后序遍历(非递归)

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. 可以和(编程训练)再回首,数据结构--二叉树的前序.中序.后序遍历(递归)对比着看 [问题描述] 根据顺序存储结构建立二叉树的二叉链表,并对二叉树进行先序.中序.后序遍历. [基本要求] ·功能:根据顺序存储结构建立二叉树的二叉链表,并进行先序.中序.后序遍历. ·输入:输入二叉树的顺序存储. ·输出:二叉树的先序.中序.后序遍历序

(编程训练)再回首,数据结构——(升级版)使用栈判断括号匹配

点击打开 基础版 最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. /* ********************************************************** * 3-2 * 设在一个算术表达式中允许使用3种括号:圆括号"(".")",方 * 括号"["."]",花括号"

(编程训练)再回首,数据结构——无向图的邻接矩阵表示、DFS、BFS

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. [问题描述] 建立图的邻接矩阵存储结构,实现图的遍历 [基本要求] ·功能:建立图的邻接矩阵存储结构,实现图的BFS.DFS ·输入:输入连通图的顶点数.顶点信息.边数.顶点对序列及遍历的起始顶点序号 ·输出:图的广度优先搜索序列.深度优先搜索 [模块划分] 1. 建立有向图的邻接表 CreateAdjMatrix() 2. 以邻接

(编程训练)再回首,数据结构——二叉排序树的建立

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. [问题描述] 以输入的一组整数作为关键字的值,构造其对应的二叉排序树,并对给点的值在该二叉排序树上进行查找 [基本要求] ·输入:输入一组关键字(整数)及要查找的值 ·输出:排好序的关键字及查找的结果 样例输入 60 35 69 84 96 13 66 34 21 -1 40 样例输出 13 21 34 35 60 66 69 84

【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找--方法一:顺序查找(时间复杂度O(n)) int SequentialSearch(St

【数据结构与算法】二叉树——哈夫曼编码

最近有很多的小朋友问我什么是哈夫曼编码,哈夫曼编码是一种可变字长的编码,那什么是可变字长呢?就是一句话里的每一个字符(ASCII码)它的位数(长度)是不一样的.就像我们一句话(AAAACCCCCDDDDBBE)有A,B,C,D,E五种字符,在这里我们可以用01表示A字符,用001表示B字符,用11表示C字符,用10表示D字符,用000表示E字符.如下图: 既然知道了哈夫曼编码是什么了,那又有好奇的小朋友又会问了:那么哈夫曼编码是按照什么原理生成的呢? 在这里我就要告诉大家,哈夫曼编码是根据哈夫曼

《数据结构复习笔记》--哈夫曼树,哈夫曼编码

先来了解一下哈夫曼树. 带权路径长度(WPL):设二叉树有n个叶子结点,每个叶子结点带有权值 wk,从根结点到每个叶子结点的长度为 lk,则每个叶子结点的带权路径长度之和就是: 最优二叉树或哈夫曼树: WPL最小的二叉树. [例]有五个叶子结点,它们的权值为{1,2,3,4,5},用此权值序列可以构造出形状不同的多个二叉树. 其中结果wpl最小值的是:33=(1+2)*3+(3)*2+(4+5)*2: 哈夫曼树的构造: 每次把权值最小的两棵二叉树合并, 代码: typedef struct Tr

数据结构(java语言描述)哈夫曼编码

原理:哈夫曼编码是根据将已给出的权值作为叶子结点,生成一颗哈夫曼树,然后使得权重最小. 首先生成已给权重的所有的叶子结点,然后取所有节点中最小和次小的结点作为左右孩子生成一个哈夫曼树,计算出父节点的权重放入给出的权重森林中,并把之前的最小和次小的结点从森林中删除,再在种种森林中找最小和次小的结点生成权重树....直到最终只剩下一个树为止. 哈夫曼树的结点用如下结点表示: (有权重,左右孩子,父节点,然后设置一个标识符标志结点是否已经放入哈夫曼树) package tree;/**********

【Matlab编程】哈夫曼编码的Matlab实现

在前年暑假的时候,用C实现了哈夫曼编译码的功能,见文章<哈夫曼树及编译码>.不过在通信仿真中,经常要使用到Matlab编程,所以为了方便起见,这里用Matlab实现的哈夫曼编码的功能.至于哈夫曼编译码的基本原理,我们可以参考之前的文章<哈夫曼树及编译码>,里面有详细的说明及图解过程.下面直接给出具体的Matlab实现的哈夫曼编码函数,由于程序中注释还算比较详细,在此就不予与说明: function [ h,e ] = Huffman_code( p ) %p为概率分布,此函数功能是