哈夫曼树的构造规则为:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
huffman_tree.c
/************************************************************************/
/* 哈夫曼树(最优二叉树) */
/* 对给定的一串字符串按字符出现的频率对其进行编、解码 */
/* ziven 20131024 */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"
#include "list.h"
#define MAX 500
typedef struct _huff_node huffman_node_t;
typedef struct _huff_node *huffman_tree_t;
typedef struct _node_info node_info_t;
struct _node_info
{
char c;
int wei;
char code[20];
huffman_node_t *node;
};
struct _huff_node
{
node_info_t *node_info;
struct _huff_node *parent;
struct _huff_node *lchild;
struct _huff_node *rchild;
};
typedef struct
{
node_info_t info[MAX];
int cout;
}node_t;
void huffman_count(char *s , int len, node_t *node)
{
int i = 0, j = 0;
node->cout = 0;
for (i = 0; i < len; i++)
{
for (j = 0; j < node->cout; j++)
{
if (s[i] == node->info[j].c)
{
node->info[j].wei++;
break;
}
}
if (j == node->cout)
{
node->info[node->cout].c = s[i];
node->info[node->cout].wei = 1;
memset(node->info[node->cout].code, 0, sizeof(node->info[node->cout].code));
node->info[node->cout].node = NULL;
node->cout++;
}
}
}
int huffman_cmp(huffman_node_t *n1, huffman_node_t *n2)
{
if (n1->node_info->wei > n2->node_info->wei)
{
return 1;
}
else if (n1->node_info->wei == n2->node_info->wei)
{
return 0;
}
else
{
return -1;
}
}
void huffman_create(node_t *node, huffman_tree_t *tree)
{
int i = 0;
huffman_node_t *huffman_node = NULL;
huffman_node_t *node1 = NULL, *node2 = NULL;
list_t *list = list_new();
list->cmp = (list_cmp_f)huffman_cmp;
for (i = 0; i < node->cout; i++)
{
huffman_node = (huffman_node_t *)malloc(sizeof(huffman_node_t));
huffman_node->node_info = &node->info[i];
huffman_node->lchild = NULL;
huffman_node->rchild = NULL;
huffman_node->parent = NULL;
node->info[i].node = huffman_node;
listnode_add_sort(list, (void *)huffman_node);
}
while (list->count != 1)
{
node1 = (huffman_node_t *)(list->head->data);
node2 = (huffman_node_t *)(list->head->next->data);
huffman_node = (huffman_node_t *)malloc(sizeof(huffman_node_t));
huffman_node->node_info = (node_info_t *)malloc(sizeof(node_info_t));
memset(huffman_node->node_info, 0, sizeof(node_info_t));
huffman_node->lchild = node1;
huffman_node->rchild = node2;
huffman_node->parent = NULL;
huffman_node->node_info->wei = node1->node_info->wei + node2->node_info->wei;
node1->parent = huffman_node;
node2->parent = huffman_node;
listnode_delete(list, (void *)node1);
listnode_delete(list, (void *)node2);
listnode_add_sort(list, (void *)huffman_node);
}
*tree = (huffman_tree_t)(list->head->data);
}
void huffman_code(huffman_tree_t tree)
{
if (tree == NULL)
{
return;
}
if (tree->parent != NULL)
{
strcpy(tree->node_info->code, tree->parent->node_info->code);
if (tree->parent->lchild == tree)
{
tree->node_info->code[strlen(tree->node_info->code)] = '1';
}
else
{
tree->node_info->code[strlen(tree->node_info->code)] = '0';
}
}
huffman_code(tree->lchild);
huffman_code(tree->rchild);
}
void huffman_recode(node_t node, char *s, int len)
{
int i = 0;
int j = 0;
for (i = 0; i < len;)
{
for (j = 0; j < node.cout; j++)
{
if (!strncmp(node.info[j].code, s, strlen(node.info[j].code)))
{
s += strlen(node.info[j].code);
printf("%c ", node.info[j].c);
i += strlen(node.info[j].code);
break;
}
}
if (j == node.cout)
{
printf("解析失败!\n");
break;
}
}
}
void huffman_pre_reverse(huffman_tree_t tree)
{
if (tree == NULL)
{
return;
}
printf("%c(%d) ", tree->node_info->c, tree->node_info->wei);
huffman_pre_reverse(tree->lchild);
huffman_pre_reverse(tree->rchild);
}
void huffman_test()
{
node_t node;
huffman_tree_t tree;
int i = 0;
char s[MAX];
memset(s, 0, sizeof(s));
printf("输入字符串:\n");
gets(s);
huffman_count(s, strlen(s), &node);
for (i = 0; i < node.cout; i++)
{
printf("%c 出现次数为:%d \n", node.info[i].c, node.info[i].wei);
}
huffman_create(&node, &tree);
//huffman_pre_reverse(tree);printf("\n");
huffman_code(tree);
for (i = 0; i < node.cout; i++)
{
printf("%c 的哈夫曼编码为:%s \n", node.info[i].c, node.info[i].code);
}
printf("输入1、0组成的字符串:\n");
gets(s);
huffman_recode(node, s, strlen(s));
}
list.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
list_t *list_new()
{
list_t *node;
node = (list_t *)malloc(sizeof(list_t));
memset(node, 0, sizeof(list_t));
return node;
}
listnode_t *listnode_new()
{
listnode_t *node;
node = (listnode_t *)malloc(sizeof(listnode_t));
if (node == NULL)
{
return NULL;
}
memset(node, 0, sizeof(listnode_t));
return node;
}
listnode_t *listnode_add(list_t *list, void *v)
{
listnode_t *node = listnode_new();
if (node == NULL)
{
return NULL;
}
node->prev = list->tail;
node->data = v;
if (list->head == NULL)
{
list->head = node;
}
else
{
list->tail->next = node;
}
list->tail = node;
list->count++;
return node;
}
listnode_t *listnode_add_sort(list_t *list, void *v)
{
listnode_t *n;
listnode_t *node = listnode_new();
if (node == NULL)
{
return NULL;
}
node->data = v;
if (list->cmp)
{
for (n = list->head; n; n = n->next)
{
if ((*list->cmp)(v, n->data) < 0)
{
node->next = n;
node->prev = n->prev;
if (n->prev)
{
n->prev->next = node;
}
else
{
list->head = node;
}
n->prev = node;
list->count++;
return node;
}
}
}
node->prev = list->tail;
if (list->tail)
{
list->tail->next = node;
}
else
{
list->head = node;
}
list->tail = node;
list->count++;
return node;
}
void listnode_delete (list_t *list, void *val)
{
listnode_t *node;
for (node = list->head; node; node = node->next)
{
if (node->data == val)
{
if (node->prev)
node->prev->next = node->next;
else
list->head = node->next;
if (node->next)
node->next->prev = node->prev;
else
list->tail = node->prev;
list->count--;
free(node);
return;
}
}
}
运行结果: