主题:[原创]赫夫曼编码实现 (ANSI C)
欢迎拍砖,提出不足之处,我好提高 hoho
下面贴出我写的求赫夫曼编码的实现,是个头文件:
#ifndef _HuffmanTree_h
#define _HuffmanTree_h
/*----------------------------------------------------------------*/
/* HuffmanTree CreateHuffmanTree(WEIGHT w[], int n) 创建赫夫曼树 */
/* void DestroyHuffmanTree(HuffmanTree HT) 摧毁赫夫曼树 */
/* HuffmanCode GetHuffmanCode(HuffmanTree HT) 获得赫夫曼编码 */
/* void DestroyHuffmanCode(HuffmanCode HC) 摧毁赫夫曼编码 */
/*----------------------------------------------------------------*/
/*-----------------------示范例程开始-------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "HuffmanTree.h"
int main(int argc, char *argv[])
{
int w[8] = {5, 29, 7, 8, 14, 23, 3, 11};
int i;
HuffmanTree tree = CreateHuffmanTree(w, 8);
HuffmanCode code = GetHuffmanCode(tree);
for (i=0; i < 8; ++i)
{
printf("%d\t%s\n", w[i], code[i]);
}
system("pause");
DestroyHuffmanTree(tree);
DestroyHuffmanCode(code);
return 0;
}
-------------------------示范例程结束-----------------------------*/
#include <stdlib.h>
typedef unsigned int WEIGHT; //权
#define WEIGHT_0 ( 0 ) //空权
#define HTP_NULL ( -1 ) //赫夫曼树结点接地标志
typedef struct _HuffmanTreeNode //定义赫夫曼树节点
{
int parent;
int lchild;
int rchild;
WEIGHT weight;
} HuffmanTreeNode;
typedef struct _HuffmanTree
{
HuffmanTreeNode* nodes; //树节点数组
int how_many_leaves; //叶子数
}* HuffmanTree;
typedef char** HuffmanCode;
void SelectTwoMinNodes(int two_min[2], HuffmanTreeNode nodes[],int n);
//选择nodes中无parent且weight最小的两个节点的编号到min
HuffmanTree CreateHuffmanTree(WEIGHT w[], int n)
{//创建赫夫曼树,其权值信息在数组w[n]中
HuffmanTree HT = NULL;
int two_min_nodes[2]; //权最小的两个节点,[0]最小,[1]第二小
int how_many_nodes;
int i;
if (n < 2)
{
return NULL;
}
HT = (HuffmanTree)malloc(sizeof(struct _HuffmanTree));
//内存溢出处理省略
HT->how_many_leaves = n;
how_many_nodes = n + n - 1;
HT->nodes = (HuffmanTreeNode *)malloc
(how_many_nodes * sizeof(struct _HuffmanTreeNode));
//内存溢出处理省略
for (i=0; i < n; ++i) //初始化前n个节点
{
HT->nodes[i].weight = w[i];
HT->nodes[i].parent = HTP_NULL;
HT->nodes[i].lchild = HTP_NULL;
HT->nodes[i].rchild = HTP_NULL;
}
for (i=n; i < how_many_nodes; ++i) //初始化剩下的节点
{
HT->nodes[i].weight = WEIGHT_0;
HT->nodes[i].parent = HTP_NULL;
HT->nodes[i].lchild = HTP_NULL;
HT->nodes[i].rchild = HTP_NULL;
}
for (i=n; i < how_many_nodes; ++i) //建立赫夫曼树
{
SelectTwoMinNodes(two_min_nodes, HT->nodes, i);
HT->nodes[ two_min_nodes[0] ].parent = i;
HT->nodes[ two_min_nodes[1] ].parent = i;
HT->nodes[i].lchild = two_min_nodes[0];
HT->nodes[i].rchild = two_min_nodes[1];
HT->nodes[i].weight =
HT->nodes[ two_min_nodes[0] ].weight
+ HT->nodes[ two_min_nodes[1] ].weight;
}
return HT;
}
void DestroyHuffmanTree(HuffmanTree HT)
{//摧毁赫夫曼树
free(HT->nodes);
free(HT);
}
void SelectTwoMinNodes(int min[2], HuffmanTreeNode nodes[], int n)
{//选择nodes中无parent且weight最小的两个节点的编号到min
int i;
WEIGHT min_weight;
//1.找到最小的
min[0] = 0;
min_weight = 0;
for (i=0; i < n; ++i)
{
if ( (HTP_NULL == nodes[i].parent)
&& ((0 == min_weight)
||(nodes[i].weight < min_weight)) )
{
min[0] = i;
min_weight = nodes[i].weight;
}
}
//2.找到第二小的
min[1] = 0;
min_weight = 0;
for (i=0; i < n; ++i)
{
if ((i != min[0])
&& (HTP_NULL == nodes[i].parent)
&& ((0 == min_weight)
||(nodes[i].weight < min_weight)))
{
min[1] = i;
min_weight = nodes[i].weight;
}
}
return;
}
HuffmanCode GetHuffmanCode(HuffmanTree HT)
{//求赫夫曼树HT对应的赫夫曼编码
HuffmanCode code = NULL;
char *temp = NULL;
int n;
int start;
int parent, child;
int i,j;
n = HT->how_many_leaves;
code = (HuffmanCode)malloc((n + 1) * sizeof(char *));
temp = (char *)malloc((n + 1) * sizeof(char)); //内存溢出错误处理省略
temp[n] = '\0';
for (i=0; i < n; ++i)
{
start = n;
child = i;
parent = HT->nodes[child].parent;
while ( HTP_NULL != parent )
{
temp[--start] = HT->nodes[parent].lchild == child ? '0' : '1';
child = parent;
parent = HT->nodes[child].parent;
}
code[i] = (char *)malloc((n - start + 1) * sizeof(char));
for (j=0; '\0' != temp[start+j]; ++j) //将temp复制到code[i]
{
code[i][j] = temp[start+j];
}
code[i][j] = '\0';
}
code[n] = NULL; //做结尾标记
free(temp);
return code;
}
void DestroyHuffmanCode(HuffmanCode HC)
{//摧毁赫夫曼编码
int i = 0;
while (NULL != HC[i])
{
free(HC[i++]);
}
free(HC);
}
#endif
下面贴出我写的求赫夫曼编码的实现,是个头文件:
#ifndef _HuffmanTree_h
#define _HuffmanTree_h
/*----------------------------------------------------------------*/
/* HuffmanTree CreateHuffmanTree(WEIGHT w[], int n) 创建赫夫曼树 */
/* void DestroyHuffmanTree(HuffmanTree HT) 摧毁赫夫曼树 */
/* HuffmanCode GetHuffmanCode(HuffmanTree HT) 获得赫夫曼编码 */
/* void DestroyHuffmanCode(HuffmanCode HC) 摧毁赫夫曼编码 */
/*----------------------------------------------------------------*/
/*-----------------------示范例程开始-------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "HuffmanTree.h"
int main(int argc, char *argv[])
{
int w[8] = {5, 29, 7, 8, 14, 23, 3, 11};
int i;
HuffmanTree tree = CreateHuffmanTree(w, 8);
HuffmanCode code = GetHuffmanCode(tree);
for (i=0; i < 8; ++i)
{
printf("%d\t%s\n", w[i], code[i]);
}
system("pause");
DestroyHuffmanTree(tree);
DestroyHuffmanCode(code);
return 0;
}
-------------------------示范例程结束-----------------------------*/
#include <stdlib.h>
typedef unsigned int WEIGHT; //权
#define WEIGHT_0 ( 0 ) //空权
#define HTP_NULL ( -1 ) //赫夫曼树结点接地标志
typedef struct _HuffmanTreeNode //定义赫夫曼树节点
{
int parent;
int lchild;
int rchild;
WEIGHT weight;
} HuffmanTreeNode;
typedef struct _HuffmanTree
{
HuffmanTreeNode* nodes; //树节点数组
int how_many_leaves; //叶子数
}* HuffmanTree;
typedef char** HuffmanCode;
void SelectTwoMinNodes(int two_min[2], HuffmanTreeNode nodes[],int n);
//选择nodes中无parent且weight最小的两个节点的编号到min
HuffmanTree CreateHuffmanTree(WEIGHT w[], int n)
{//创建赫夫曼树,其权值信息在数组w[n]中
HuffmanTree HT = NULL;
int two_min_nodes[2]; //权最小的两个节点,[0]最小,[1]第二小
int how_many_nodes;
int i;
if (n < 2)
{
return NULL;
}
HT = (HuffmanTree)malloc(sizeof(struct _HuffmanTree));
//内存溢出处理省略
HT->how_many_leaves = n;
how_many_nodes = n + n - 1;
HT->nodes = (HuffmanTreeNode *)malloc
(how_many_nodes * sizeof(struct _HuffmanTreeNode));
//内存溢出处理省略
for (i=0; i < n; ++i) //初始化前n个节点
{
HT->nodes[i].weight = w[i];
HT->nodes[i].parent = HTP_NULL;
HT->nodes[i].lchild = HTP_NULL;
HT->nodes[i].rchild = HTP_NULL;
}
for (i=n; i < how_many_nodes; ++i) //初始化剩下的节点
{
HT->nodes[i].weight = WEIGHT_0;
HT->nodes[i].parent = HTP_NULL;
HT->nodes[i].lchild = HTP_NULL;
HT->nodes[i].rchild = HTP_NULL;
}
for (i=n; i < how_many_nodes; ++i) //建立赫夫曼树
{
SelectTwoMinNodes(two_min_nodes, HT->nodes, i);
HT->nodes[ two_min_nodes[0] ].parent = i;
HT->nodes[ two_min_nodes[1] ].parent = i;
HT->nodes[i].lchild = two_min_nodes[0];
HT->nodes[i].rchild = two_min_nodes[1];
HT->nodes[i].weight =
HT->nodes[ two_min_nodes[0] ].weight
+ HT->nodes[ two_min_nodes[1] ].weight;
}
return HT;
}
void DestroyHuffmanTree(HuffmanTree HT)
{//摧毁赫夫曼树
free(HT->nodes);
free(HT);
}
void SelectTwoMinNodes(int min[2], HuffmanTreeNode nodes[], int n)
{//选择nodes中无parent且weight最小的两个节点的编号到min
int i;
WEIGHT min_weight;
//1.找到最小的
min[0] = 0;
min_weight = 0;
for (i=0; i < n; ++i)
{
if ( (HTP_NULL == nodes[i].parent)
&& ((0 == min_weight)
||(nodes[i].weight < min_weight)) )
{
min[0] = i;
min_weight = nodes[i].weight;
}
}
//2.找到第二小的
min[1] = 0;
min_weight = 0;
for (i=0; i < n; ++i)
{
if ((i != min[0])
&& (HTP_NULL == nodes[i].parent)
&& ((0 == min_weight)
||(nodes[i].weight < min_weight)))
{
min[1] = i;
min_weight = nodes[i].weight;
}
}
return;
}
HuffmanCode GetHuffmanCode(HuffmanTree HT)
{//求赫夫曼树HT对应的赫夫曼编码
HuffmanCode code = NULL;
char *temp = NULL;
int n;
int start;
int parent, child;
int i,j;
n = HT->how_many_leaves;
code = (HuffmanCode)malloc((n + 1) * sizeof(char *));
temp = (char *)malloc((n + 1) * sizeof(char)); //内存溢出错误处理省略
temp[n] = '\0';
for (i=0; i < n; ++i)
{
start = n;
child = i;
parent = HT->nodes[child].parent;
while ( HTP_NULL != parent )
{
temp[--start] = HT->nodes[parent].lchild == child ? '0' : '1';
child = parent;
parent = HT->nodes[child].parent;
}
code[i] = (char *)malloc((n - start + 1) * sizeof(char));
for (j=0; '\0' != temp[start+j]; ++j) //将temp复制到code[i]
{
code[i][j] = temp[start+j];
}
code[i][j] = '\0';
}
code[n] = NULL; //做结尾标记
free(temp);
return code;
}
void DestroyHuffmanCode(HuffmanCode HC)
{//摧毁赫夫曼编码
int i = 0;
while (NULL != HC[i])
{
free(HC[i++]);
}
free(HC);
}
#endif