C语言实现哈夫曼编码
作者:_yxy_ 发布时间:2022-07-25 07:35:04
标签:C语言,哈夫曼编码
本文实例为大家分享了C语言实现哈夫曼编码的具体代码,供大家参考,具体内容如下
代码来自于《小甲鱼C++快速入门》
主程序main.cpp
#include "stdafx.h"
#include <stdlib.h>
#include "huffman.h"
int main()
{
htTree *codeTree = buildTree("I love wwwwwwwwwFishC.com!");//建立哈夫曼树
hlTable *codeTable = buildTable(codeTree);//建立编码表
encode(codeTable,"I love FishC.com!");//对输入的字符串进行编码
decode(codeTree,"0011111000111");//解码
system("pause");
return 0;
}
两个头文件:
huffman.h:定义了哈夫曼树和编码表的结构
#pragma once
#ifndef _HUFFMAN_H
#define _HUFFMAN_H
typedef struct _htNode{
char symbol;
struct _htNode *left,*right;
}htNode;
typedef struct _htTree{
htNode *root;
}htTree;
typedef struct _hlNode{
char symbol;
char *code;
struct _hlNode *next;
}hlNode;
typedef struct _hlTable{
hlNode *first;
hlNode *last;
}hlTable;
htTree *buildTree(char *str);
hlTable *buildTable(htTree *huffmanTree);
void encode(hlTable *table, char *stringToEncode);
void decode(htTree *tree, char *stringToDecode);
#endif
queue.h:定义了有序队列的结构,将字符按优先级排列,即频率从小到大排列,val是树节点,直接由队列建立起哈夫曼树
#pragma once
#ifndef _PQUEUE_H
#define _PQUEUE_H
#include "huffman.h"
#define MAX_SZ 256
#define TYPE htNode *
typedef struct _pQueueNode{
TYPE val;
unsigned int priority;
struct _pQueueNode *next;
}pQueueNode;
typedef struct _pQueue{
unsigned int size;
pQueueNode *first;
}pQueue;
void initPQueue(pQueue **queue);
void addPQueue(pQueue **queue, TYPE val, unsigned int priority);
TYPE getQueue(pQueue **queue);
#endif
两个cpp文件实现两个头文件声明的函数:
huffman.cpp
#include "stdafx.h"
#include "queue.h"
#include "huffman.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
htTree *buildTree(char *str)
{
int *probability = (int *)malloc(sizeof(int) * 256);
//初始化
for (int i = 0; i < 256; i++)
{
probability[i] = 0;
}
//统计待编码的字符串各个字符出现的次数
for (int j = 0; str[j] != '\0'; j++)
{
probability[str[j]]++;
}
//定义队列的头指针
pQueue *huffmanQueue;
initPQueue(&huffmanQueue);
//填充队列
for (int k = 0; k < 256; k++)
{
if (probability[k] != 0)
{
htNode *aux = (htNode *)malloc(sizeof(htNode));
aux->left = NULL;
aux->right = NULL;
aux->symbol = (char)k;
addPQueue(&huffmanQueue, aux, probability[k]);
}
}
free(probability);
//生成哈夫曼树
while (huffmanQueue->size != 1)
{
unsigned int newPriority = huffmanQueue->first->priority + huffmanQueue->first->next->priority;
htNode *aux = (htNode *)malloc(sizeof(htNode));
aux->left = getQueue(&huffmanQueue);
aux->right = getQueue(&huffmanQueue);
addPQueue(&huffmanQueue, aux, newPriority);
}
htTree *tree = (htTree *)malloc(sizeof(htTree));
tree->root = getQueue(&huffmanQueue);
return tree;
}
void traverseTree(htNode *treeNode,hlTable **table,int k,char code[256])
{
if (treeNode->left == NULL&&treeNode->right == NULL)
{
code[k] = '\0';
hlNode *aux = (hlNode *)malloc(sizeof(hlNode));
aux->code = (char *)malloc(sizeof(char)*(strlen(code) + 1));
strcpy(aux->code,code);
aux->symbol = treeNode->symbol;
aux->next = NULL;
if ((*table)->first == NULL)
{
(*table)->first = aux;
(*table)->last = aux;
}
else
{
(*table)->last->next = aux;
(*table)->last = aux;
}
}
if (treeNode->left != NULL)
{
code[k] = '0';
traverseTree(treeNode->left,table,k+1,code);
}
if (treeNode->right != NULL)
{
code[k] = '1';
traverseTree(treeNode->right, table, k + 1, code);
}
}
hlTable *buildTable(htTree *huffmanTree)
{
hlTable *table = (hlTable *)malloc(sizeof(hlTable));
table->first = NULL;
table->last = NULL;
char code[256];
int k = 0;
traverseTree(huffmanTree->root,&table,k,code);
return table;
}
void encode(hlTable *table, char *stringToEncode)
{
hlNode *traversal;
printf("Encoding......\n\nInput string:\n%s\n\nEncoded string :\n",stringToEncode);
for (int i = 0; stringToEncode[i] != '\0'; i++)
{
traversal = table->first;
while (traversal->symbol != stringToEncode[i])
traversal = traversal->next;
printf("%s", traversal->code);
}
printf("\n");
}
void decode(htTree *tree,char *stringToDecode)
{
htNode *traversal = tree->root;
printf("\n\nDecoding......\n\nInput string: \n%s\n\nDecoded string: \n",stringToDecode);
for (int i = 0; stringToDecode[i] != '\0'; i++)
{
if (traversal->left == NULL&&traversal->right == NULL)
{
printf("%c", traversal->symbol);
traversal = tree->root;
}
if (stringToDecode[i] == '0')
traversal = traversal->left;
else if (stringToDecode[i] == '1')
traversal = traversal->right;
else
{
printf("The input string is not coded correctly!\n");
return;
}
}
printf("\n\n");
return;
}
queue.cpp:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
void initPQueue(pQueue **queue)
{
*queue = (pQueue *)malloc(sizeof(pQueue));
(*queue)->first = NULL;
(*queue)->size = 0;
return;
}
void addPQueue(pQueue **queue, TYPE val, unsigned int priority)
{
if ((*queue)->size == MAX_SZ)
{
printf("\n Queue is full. \n");
return;
}
pQueueNode *aux = (pQueueNode *)malloc(sizeof(pQueueNode));
aux->priority = priority;
aux->val = val;
if ((*queue)->size == 0||(*queue)->first==NULL)
{
aux->next = NULL;
(*queue)->first = aux;
(*queue)->size = 1;
return;
}
else
{
if (priority <= (*queue)->first->priority)
{
aux->next = (*queue)->first;
(*queue)->first = aux;
(*queue)->size++;
return;
}
else
{
pQueueNode *iterator = (*queue)->first;
while (iterator->next!=NULL)
{
if (priority <= iterator->next->priority)
{
aux->next = iterator->next;
iterator->next = aux;
(*queue)->size++;
return;
}
iterator = iterator->next;
}
if (iterator->next == NULL)
{
aux->next = NULL;
iterator->next = aux;
(*queue)->size++;
return;
}
}
}
}
TYPE getQueue(pQueue **queue)
{
TYPE returnValue;
if ((*queue)->size > 0)
{
returnValue = (*queue)->first->val;
(*queue)->first = (*queue)->first->next;
(*queue)->size--;
}
else
{
returnValue = NULL;
printf("\n Queue is empty \n");
}
return returnValue;
}
运行结果:
来源:https://blog.csdn.net/u011643312/article/details/53983278


猜你喜欢
- 这篇文章主要介绍了如何使用Spring工具类动态匹配url,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- 在Eclipse中创建Android项目,利用之前学过的WebView控件和中国天气网提供的天气数据接口,实现获取指定城市的天气预报。布局文
- 本文实例为大家分享了Android自定义广播接收的具体代码,供大家参考,具体内容如下实现效果:MainActivity.java代码:pac
- spring cloud 配置中心客户端启动先启动了配置中心,然后启动客户端,发现打印的日志是这样的2020-04-29 11:13:02.
- 抛出问题:Long a = 4l;Long b = 4l;a == b //trueLong a = 128l;Long b = 128l;
- 一、List<T>对象中的T是值类型的情况(int 类型等)对于值类型的List直接用以下方法就可以复制:List<T&g
- 本文介绍Android平台进行数据存储的五大方式,分别如下:1 使用SharedPreferences存储数据2 文件存储数据 &
- 一、变量C#共有其中变量类型有:静态变量、实类变量、数组元素、数值参数、引用参数、输出参数和局部变量先定义一个简单的类来说明,如下:publ
- Android在布局文件中为View提供了onClick属性,使用方法如下:<TextView android:id=&
- 本文实例讲述了C#对图片文件的压缩、裁剪操作方法,在C#项目开发中非常有实用价值。分享给大家供大家参考。具体如下:一般在做项目时,对图片的处
- 设立一个定时器tmrMonitor,该定时器会在程序运行时不断把程序的占用内存和占用线程数写到LOG\MEM目录下。我设置的定时器间隔是30
- 方法一:递归算法/// <summary>/// 一列数的规则如下: 1、1、2、3、5、8、13、21、34求第30位数是多少
- 将JavaDoc 注释 生成API文档1. 打开java代码,编写JavaDoc 注释,只有按照java的规范编写注释,才能很好的生成API
- 1、图的定义我们知道,前面讨论的数据结构都有一个框架,而这个框架是由相应的算法实现的,比如二叉树搜索树,左子树上所有结点的值均小于它的根结点
- 前言本文主要给大家介绍了关于JDK8新增的原子性操作类LongAdder的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的
- android新特性页面,ViewPager拖拽到最后一页再拖拽打开其他Activity.实现的方式有很多,效果比较好的就是到了
- SpringCloud Zuul 是SpringCloud系列的网关实现,具有均衡负载,将非业务性校验剥离出来,使微服务专注于业务的一个组件
- ☆代码示例:代码块语法遵循标准markdown代码,例如:package cas;import org.htmlparser.Node;im
- 今天对接一个海康监控的sdk,其中sdk 是以aar的形式提供的,并且我需要用到此aar的模块是个library。所以按照正常的在appli
- 一、常量用final修饰(也称最终变量)常量在声明时必须赋初值,赋值后不能再修改值常量名通常用全大写字母表示声明时需要添加final或sta