HuffmanTree的创建及编码
typedef
struct
_HTNode {
unsigned int weight; /* 权值 */
unsigned int parent; /* 父节点索引 */
unsigned int lchild; /* 左孩子索引 */
unsigned int rchild; /* 右孩子索引 */
} HTNode, * HuffmanTree; /* 动态分配数组存储哈夫曼树 */
typedef char ** HuffmanCode; /* 动态分配数组存储哈夫曼编码表 */
/* 从ht的1~n的节点中找出权值最小的两个节点,分别存于s1, s2中 */
void Select(HuffmanTree ht, int n, int * s1, int * s2)
{
int i;
* s1 = 0 ;
* s2 = 0 ;
/* 设置s1, s2到开始两个parent等于0的节点位置 */
for (i = 1 ; i <= n; ++ i) {
if ( * s1 != 0 && * s2 != 0 )
break ;
if (ht[i].parent == 0 )
* s1 == 0 ? * s1 = i : * s2 = i;
}
/* 找出ht中parent等于0,且权值最小的两个节点位置,分别存于s1, s2中 */
for ( ; i <= n; ++ i) {
if (ht[i].parent != 0 ) continue ;
if ( (ht[ * s1].weight > ht[ * s2].weight) && (ht[ * s1].weight > ht[i].weight))
* s1 = i;
else if ( (ht[ * s2].weight > ht[ * s1].weight) && (ht[ * s2].weight > ht[i].weight))
* s2 = i;
}
}
/* 通过w存储的n个权值,来创建一颗哈夫曼树, ht_ptr指向这颗哈夫曼树 */
void CreateHuffmanTree(HuffmanTree * ht_ptr, int * w, int n)
{
int m;
int i;
int s1, s2;
HuffmanTree p;
if (n <= 1 ) return ;
m = 2 * n - 1 ; /* n个字符,需要2n-1个空间来存储整颗huffman tree */
* ht_ptr = (HuffmanTree)malloc( (m + 1 ) * sizeof (HTNode)); /* 0号单元不用 */
for (p = * ht_ptr + 1 , i = 1 ; i <= n; ++ i, ++ p, ++ w) { /* 初始化数组中前n个单元存储的字符 */
p -> weight = * w;
p -> parent = 0 ;
p -> lchild = 0 ;
p -> rchild = 0 ;
}
for ( ; i <= m; ++ i, ++ p) { /* 初始化数组中剩余的单元 */
p -> weight = 0 ;
p -> parent = 0 ;
p -> lchild = 0 ;
p -> rchild = 0 ;
}
for (i = n + 1 ; i <= m; ++ i) {
Select( * ht_ptr, i - 1 , & s1, & s2);
/* 设置s1, s2的父亲为i */
( * ht_ptr + s1) -> parent = i;
( * ht_ptr + s2) -> parent = i;
/* 设置i的左孩子为s1, 右孩子为s2 */
( * ht_ptr + i) -> lchild = s1;
( * ht_ptr + i) -> rchild = s2;
/* 设置i的权值为s1, s2之和 */
( * ht_ptr + i) -> weight = ( * ht_ptr + s1) -> weight + ( * ht_ptr + s2) -> weight;
}
}
/* 对ht_ptr存储的哈夫曼树的n个叶子节点进行哈夫曼编码 */
void HuffmanCoding(HuffmanTree * ht_ptr, HuffmanCode * hc_ptr, int n)
{
int i;
int start;
char * cd = NULL;
* hc_ptr = (HuffmanCode)malloc( (n + 1 ) * sizeof ( char * ));
cd = ( char * )malloc(n * sizeof ( char ));
cd[n - 1 ] = ' \0 ' ;
for (i = 1 ; i <= n; ++ i) {
start = n - 1 ;
int current, father;
for (current = i, father = ( * ht_ptr + i) -> parent; /* 从叶子节点开始,并取得父节点father */
father != 0 ; /* 父节点为0时及到达了根节点 */
current = father, father = ( * ht_ptr + father) -> parent) { /* 逐渐向根节点靠拢 */
if ( ( * ht_ptr + father) -> lchild == current) /* 当前节点为左孩子 */
cd[ -- start] = ' 0 ' ;
else
cd[ -- start] = ' 1 ' ;
}
* ( * hc_ptr + i) = ( char * )malloc( (n - start) * sizeof ( char ));
strcpy( * ( * hc_ptr + i), & cd[start]);
}
free(cd);
}
unsigned int weight; /* 权值 */
unsigned int parent; /* 父节点索引 */
unsigned int lchild; /* 左孩子索引 */
unsigned int rchild; /* 右孩子索引 */
} HTNode, * HuffmanTree; /* 动态分配数组存储哈夫曼树 */
typedef char ** HuffmanCode; /* 动态分配数组存储哈夫曼编码表 */
/* 从ht的1~n的节点中找出权值最小的两个节点,分别存于s1, s2中 */
void Select(HuffmanTree ht, int n, int * s1, int * s2)
{
int i;
* s1 = 0 ;
* s2 = 0 ;
/* 设置s1, s2到开始两个parent等于0的节点位置 */
for (i = 1 ; i <= n; ++ i) {
if ( * s1 != 0 && * s2 != 0 )
break ;
if (ht[i].parent == 0 )
* s1 == 0 ? * s1 = i : * s2 = i;
}
/* 找出ht中parent等于0,且权值最小的两个节点位置,分别存于s1, s2中 */
for ( ; i <= n; ++ i) {
if (ht[i].parent != 0 ) continue ;
if ( (ht[ * s1].weight > ht[ * s2].weight) && (ht[ * s1].weight > ht[i].weight))
* s1 = i;
else if ( (ht[ * s2].weight > ht[ * s1].weight) && (ht[ * s2].weight > ht[i].weight))
* s2 = i;
}
}
/* 通过w存储的n个权值,来创建一颗哈夫曼树, ht_ptr指向这颗哈夫曼树 */
void CreateHuffmanTree(HuffmanTree * ht_ptr, int * w, int n)
{
int m;
int i;
int s1, s2;
HuffmanTree p;
if (n <= 1 ) return ;
m = 2 * n - 1 ; /* n个字符,需要2n-1个空间来存储整颗huffman tree */
* ht_ptr = (HuffmanTree)malloc( (m + 1 ) * sizeof (HTNode)); /* 0号单元不用 */
for (p = * ht_ptr + 1 , i = 1 ; i <= n; ++ i, ++ p, ++ w) { /* 初始化数组中前n个单元存储的字符 */
p -> weight = * w;
p -> parent = 0 ;
p -> lchild = 0 ;
p -> rchild = 0 ;
}
for ( ; i <= m; ++ i, ++ p) { /* 初始化数组中剩余的单元 */
p -> weight = 0 ;
p -> parent = 0 ;
p -> lchild = 0 ;
p -> rchild = 0 ;
}
for (i = n + 1 ; i <= m; ++ i) {
Select( * ht_ptr, i - 1 , & s1, & s2);
/* 设置s1, s2的父亲为i */
( * ht_ptr + s1) -> parent = i;
( * ht_ptr + s2) -> parent = i;
/* 设置i的左孩子为s1, 右孩子为s2 */
( * ht_ptr + i) -> lchild = s1;
( * ht_ptr + i) -> rchild = s2;
/* 设置i的权值为s1, s2之和 */
( * ht_ptr + i) -> weight = ( * ht_ptr + s1) -> weight + ( * ht_ptr + s2) -> weight;
}
}
/* 对ht_ptr存储的哈夫曼树的n个叶子节点进行哈夫曼编码 */
void HuffmanCoding(HuffmanTree * ht_ptr, HuffmanCode * hc_ptr, int n)
{
int i;
int start;
char * cd = NULL;
* hc_ptr = (HuffmanCode)malloc( (n + 1 ) * sizeof ( char * ));
cd = ( char * )malloc(n * sizeof ( char ));
cd[n - 1 ] = ' \0 ' ;
for (i = 1 ; i <= n; ++ i) {
start = n - 1 ;
int current, father;
for (current = i, father = ( * ht_ptr + i) -> parent; /* 从叶子节点开始,并取得父节点father */
father != 0 ; /* 父节点为0时及到达了根节点 */
current = father, father = ( * ht_ptr + father) -> parent) { /* 逐渐向根节点靠拢 */
if ( ( * ht_ptr + father) -> lchild == current) /* 当前节点为左孩子 */
cd[ -- start] = ' 0 ' ;
else
cd[ -- start] = ' 1 ' ;
}
* ( * hc_ptr + i) = ( char * )malloc( (n - start) * sizeof ( char ));
strcpy( * ( * hc_ptr + i), & cd[start]);
}
free(cd);
}