按照严慰敏书P149页上的哈夫曼编码表具体算法为147页算法6.12
把书上的给改了。
typedef struct
{
int num;//编号
char data;//数据可存字母'abcdefgh';
int weight;//权值
int parent,lchild,rchild;//父亲和左右孩子所在位置
}HTNode,*HuffmanCode;
为树结点的存储结构,而且书上的例子不能把权值大的结点放在左叶子结点,因此和书上的不太一样。这个程序可以直接在VC中运行,可能还有些错误。输入的值为:
编号(num) | 数据(data) | 权值(weight) |
1 | a | 5 |
2 | b | 29 |
3 | c | 7 |
4 | d | 8 |
5 | e | 14 |
6 | f | 23 |
7 | g | 3 |
8 | h | 11 |
#include
<
stdio.h
>
#include < process.h >
#include < stdarg.h >
#include < stdlib.h >
#include < malloc.h >
#include < iostream.h >
#include < string .h >
#define NULL 0
#define MAXNODE 100
#define OVERFLOW -2
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR -1
typedef char TElemType;
typedef int Status;
typedef struct
{
int num; // 编号
char data; // 数据
int weight; // 权值
int parent,lchild,rchild; // 父亲和左右孩子所在位置
}HTNode, * HuffmanCode;
typedef char ** HuffmanTree;
typedef struct
{
int HFCLength;
char data;
char * HFC;
} HCode, * HList;
int ListLength; // 全局变量
int InitialLength; // 全局变量
Status CreateHTreeList(HuffmanCode & HN) // 假定有一个头结点不用
{
char c; int n; int i; int num; int length; // i为权值,num为编号,length为哈夫曼编码表中字母个数
printf( " 哈夫曼编码表的字母个数: " ); // scanf("%d",&length);
cin >> length;
HN = (HTNode * )malloc((length + 1 ) * sizeof (HTNode)); // 为字母表分配空间,头空间不用
HN -> num = 0 ;HN -> data = ' * ' ;HN -> weight = 0 ;HN -> lchild = 0 ;HN -> rchild = 0 ;HN -> parent = 0 ; // 初始化
int j;
printf( " %8d,%8c,%8d,%8d,%8d,%8d " ,HN -> num,HN -> data,
HN -> weight,HN -> parent,HN -> lchild,HN -> rchild);
for (j = 1 ;j <= length;j ++ )
{
printf( " 输入字母和权值: " );
// scanf("%c%d ",&c,&i); // 此处和输入字母个数不用scanf因为输入length时要打一个回车,
// scanf连回车都接收了,产生了乱码。可以考虑用getchar或cin
cin >> c;cin >> i;
num = j;
(HN + j) -> num = j;
(HN + j) -> data = c;(HN + j) -> weight = i;(HN + j) -> lchild = 0 ;(HN + j) -> rchild = 0 ;(HN + j) -> parent = 0 ;
}
ListLength = length;
for (j = 1 ;j <= ListLength;j ++ )
{
printf( " %8d,%8c,%8d,%8d,%8d,%8d " ,(HN + j) -> num,(HN + j) -> data,
(HN + j) -> weight,(HN + j) -> parent,(HN + j) -> lchild,(HN + j) -> rchild);
}
return OK;
} // CreateHTreeList建立结点的列表
Status Select(HuffmanCode & HN,HTNode & s1,HTNode & s2)
{
int i;HTNode * P, * M;HTNode p1,p2;
P = HN + 1 ;M = HN + 1 ;
s1.num = 0 ;s1.data = P -> data;s1.weight = P -> weight;
s1.lchild = P -> lchild;s1.rchild = P -> rchild;s1.parent = P -> parent;
P = HN + 1 ;
// M=P;
// M->data='#';
while (P -> parent != 0 )
{
P ++ ;
}
M = P;
P = HN + 1 ;
for (i = 1 ;i <= ListLength;i ++ )
{
if (((P -> weight) < (M -> weight)) &&
(P -> parent == 0 ) &&
(P -> weight > 0 ))
{
M = P;
}
P ++ ;
}
s1.data = M -> data;s1.num = M -> num;s1.weight = M -> weight;s1.lchild = 0 ;s1.rchild = 0 ;
s1.parent = 100 ;M -> parent = 100 ; // 标注M使下次不再选中M作最小的权值M->parent只是标识
P = HN + 1 ;
s2.num = 0 ;s2.data = P -> data;s2.weight = P -> weight;
s2.lchild = P -> lchild;s2.rchild = P -> rchild;s2.parent = P -> parent;
// M=P;
while (P -> parent != 0 )
{
P ++ ;
}
M = P;
P = HN + 1 ;
for (i = 1 ;i <= ListLength;i ++ )
{
if ( P -> weight < (M -> weight) &&
P -> weight != (s1.weight) &&
P -> parent == 0 &&
s1.num != s2.num)
// 若有两个权值相等的结点
{
M = P;
}
P ++ ;
}
s2.data = M -> data;s2.num = M -> num;s2.weight = M -> weight;s2.lchild = 0 ;s2.rchild = 0 ;
s2.parent = 100 ;M -> parent = 100 ;
printf( " Select Succeed " );
return OK;
} // Select 选出权值第一和第二小的结点
void PrintHTree(HuffmanCode HN)
{
int i;HTNode * P;P = HN;
printf( " num ,data ,weight ,parent ,lchild ,rchild " );
for (i = 1 ;i <= ListLength;i ++ )
{
P = HN + i;
printf( " %5d ,%5c ,%5d ,%5d ,%5d ,%5d " ,
P -> num,P -> data,P -> weight,P -> parent,P -> lchild,P -> rchild);
}
} // PrintHTree输出HN
Status CreateHTree(HuffmanCode & HT)
{
int TreeLength;TreeLength = ListLength * 2 - 1 ;
HTNode s1;HTNode s2;
HT = (HTNode * )realloc(HT,(TreeLength + 1 ) * sizeof (HTNode));
int i; int l = ListLength;
for (i = 1 ;i <= TreeLength;i ++ )
{
(HT + i) -> parent = 0 ;(HT + i) -> lchild = 0 ;(HT + i) -> rchild = 0 ;
}
for (i = 1 ;i <= (TreeLength - l);i ++ )
{
printf( " i=%d " ,i);
Select(HT,s1,s2);
(HT + ListLength + 1 ) -> num = ListLength + 1 ;
(HT + ListLength + 1 ) -> data = ' * ' ;
(HT + ListLength + 1 ) -> weight = s1.weight + s2.weight;
(HT + ListLength + 1 ) -> parent = 0 ;
(HT + s1.num) -> parent = l + i;
(HT + s2.num) -> parent = l + i;
(HT + ListLength + 1 ) -> rchild = s1.num;
(HT + ListLength + 1 ) -> lchild = s2.num;
if (s2.data == ' * ' )
{
(HT + ListLength + 1 ) -> rchild = s2.num;
(HT + ListLength + 1 ) -> lchild = s1.num;
}
if (s1.data == ' * ' && s2.data == ' * ' )
{
(HT + ListLength + 1 ) -> rchild = s1.num;
(HT + ListLength + 1 ) -> lchild = s2.num;
}
printf( " now ListLength=%d " ,ListLength);
ListLength ++ ;
PrintHTree(HT);
}
printf( " CreateHTreeSucceed " );
printf( " ListLength=%d " ,ListLength);
return OK;
}
Status TransCode(HuffmanCode HT,HCode & HC, int num)
{
// printf("this is TransCode ");
HTNode * P;HTNode * S, * M; char * ori, * des, * tmp;
P = HT;
int i; int CLength;CLength = 0 ;
i = num; int count;count = 0 ;
HC.data = (P + i) -> data;S = P + i;
M = S;
ori = ( char * )malloc( sizeof ( char ));
tmp = ori;
while (S -> parent != 0 )
{
M = S;
S = S + ((S -> parent) - (S -> num));
if ((S -> lchild) == (M -> num))
{
tmp = ori + count; * tmp = ' 0 ' ;CLength ++ ;
}
if ((S -> rchild) == (M -> num))
{
tmp = ori + count; * tmp = ' 1 ' ;CLength ++ ;
}
count ++ ;
ori = ( char * )realloc(ori, sizeof ( char ) * (count + 1 ));
tmp = ori + count - 1 ;
}
des = ( char * )malloc( sizeof ( char ) * (count + 1 ));
for ( int x = 0 ;x < count;x ++ )
{
printf( " %c " , * ori);
* (des + count - x - 1 ) =* ori;
ori ++ ;
}
printf( " (P+i)->data=%c " ,(P + i) -> data);
HC.HFC = ( char * )malloc( sizeof ( char ) * count);
for (x = 0 ;x < count;x ++ )
{
* (HC.HFC + x) =* (des + x);
}
HC.data = (P + i) -> data;
HC.HFCLength = count;
return OK;
} // TransCode把字母转换成对应的字符串.
#include < process.h >
#include < stdarg.h >
#include < stdlib.h >
#include < malloc.h >
#include < iostream.h >
#include < string .h >
#define NULL 0
#define MAXNODE 100
#define OVERFLOW -2
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR -1
typedef char TElemType;
typedef int Status;
typedef struct
{
int num; // 编号
char data; // 数据
int weight; // 权值
int parent,lchild,rchild; // 父亲和左右孩子所在位置
}HTNode, * HuffmanCode;
typedef char ** HuffmanTree;
typedef struct
{
int HFCLength;
char data;
char * HFC;
} HCode, * HList;
int ListLength; // 全局变量
int InitialLength; // 全局变量
Status CreateHTreeList(HuffmanCode & HN) // 假定有一个头结点不用
{
char c; int n; int i; int num; int length; // i为权值,num为编号,length为哈夫曼编码表中字母个数
printf( " 哈夫曼编码表的字母个数: " ); // scanf("%d",&length);
cin >> length;
HN = (HTNode * )malloc((length + 1 ) * sizeof (HTNode)); // 为字母表分配空间,头空间不用
HN -> num = 0 ;HN -> data = ' * ' ;HN -> weight = 0 ;HN -> lchild = 0 ;HN -> rchild = 0 ;HN -> parent = 0 ; // 初始化
int j;
printf( " %8d,%8c,%8d,%8d,%8d,%8d " ,HN -> num,HN -> data,
HN -> weight,HN -> parent,HN -> lchild,HN -> rchild);
for (j = 1 ;j <= length;j ++ )
{
printf( " 输入字母和权值: " );
// scanf("%c%d ",&c,&i); // 此处和输入字母个数不用scanf因为输入length时要打一个回车,
// scanf连回车都接收了,产生了乱码。可以考虑用getchar或cin
cin >> c;cin >> i;
num = j;
(HN + j) -> num = j;
(HN + j) -> data = c;(HN + j) -> weight = i;(HN + j) -> lchild = 0 ;(HN + j) -> rchild = 0 ;(HN + j) -> parent = 0 ;
}
ListLength = length;
for (j = 1 ;j <= ListLength;j ++ )
{
printf( " %8d,%8c,%8d,%8d,%8d,%8d " ,(HN + j) -> num,(HN + j) -> data,
(HN + j) -> weight,(HN + j) -> parent,(HN + j) -> lchild,(HN + j) -> rchild);
}
return OK;
} // CreateHTreeList建立结点的列表
Status Select(HuffmanCode & HN,HTNode & s1,HTNode & s2)
{
int i;HTNode * P, * M;HTNode p1,p2;
P = HN + 1 ;M = HN + 1 ;
s1.num = 0 ;s1.data = P -> data;s1.weight = P -> weight;
s1.lchild = P -> lchild;s1.rchild = P -> rchild;s1.parent = P -> parent;
P = HN + 1 ;
// M=P;
// M->data='#';
while (P -> parent != 0 )
{
P ++ ;
}
M = P;
P = HN + 1 ;
for (i = 1 ;i <= ListLength;i ++ )
{
if (((P -> weight) < (M -> weight)) &&
(P -> parent == 0 ) &&
(P -> weight > 0 ))
{
M = P;
}
P ++ ;
}
s1.data = M -> data;s1.num = M -> num;s1.weight = M -> weight;s1.lchild = 0 ;s1.rchild = 0 ;
s1.parent = 100 ;M -> parent = 100 ; // 标注M使下次不再选中M作最小的权值M->parent只是标识
P = HN + 1 ;
s2.num = 0 ;s2.data = P -> data;s2.weight = P -> weight;
s2.lchild = P -> lchild;s2.rchild = P -> rchild;s2.parent = P -> parent;
// M=P;
while (P -> parent != 0 )
{
P ++ ;
}
M = P;
P = HN + 1 ;
for (i = 1 ;i <= ListLength;i ++ )
{
if ( P -> weight < (M -> weight) &&
P -> weight != (s1.weight) &&
P -> parent == 0 &&
s1.num != s2.num)
// 若有两个权值相等的结点
{
M = P;
}
P ++ ;
}
s2.data = M -> data;s2.num = M -> num;s2.weight = M -> weight;s2.lchild = 0 ;s2.rchild = 0 ;
s2.parent = 100 ;M -> parent = 100 ;
printf( " Select Succeed " );
return OK;
} // Select 选出权值第一和第二小的结点
void PrintHTree(HuffmanCode HN)
{
int i;HTNode * P;P = HN;
printf( " num ,data ,weight ,parent ,lchild ,rchild " );
for (i = 1 ;i <= ListLength;i ++ )
{
P = HN + i;
printf( " %5d ,%5c ,%5d ,%5d ,%5d ,%5d " ,
P -> num,P -> data,P -> weight,P -> parent,P -> lchild,P -> rchild);
}
} // PrintHTree输出HN
Status CreateHTree(HuffmanCode & HT)
{
int TreeLength;TreeLength = ListLength * 2 - 1 ;
HTNode s1;HTNode s2;
HT = (HTNode * )realloc(HT,(TreeLength + 1 ) * sizeof (HTNode));
int i; int l = ListLength;
for (i = 1 ;i <= TreeLength;i ++ )
{
(HT + i) -> parent = 0 ;(HT + i) -> lchild = 0 ;(HT + i) -> rchild = 0 ;
}
for (i = 1 ;i <= (TreeLength - l);i ++ )
{
printf( " i=%d " ,i);
Select(HT,s1,s2);
(HT + ListLength + 1 ) -> num = ListLength + 1 ;
(HT + ListLength + 1 ) -> data = ' * ' ;
(HT + ListLength + 1 ) -> weight = s1.weight + s2.weight;
(HT + ListLength + 1 ) -> parent = 0 ;
(HT + s1.num) -> parent = l + i;
(HT + s2.num) -> parent = l + i;
(HT + ListLength + 1 ) -> rchild = s1.num;
(HT + ListLength + 1 ) -> lchild = s2.num;
if (s2.data == ' * ' )
{
(HT + ListLength + 1 ) -> rchild = s2.num;
(HT + ListLength + 1 ) -> lchild = s1.num;
}
if (s1.data == ' * ' && s2.data == ' * ' )
{
(HT + ListLength + 1 ) -> rchild = s1.num;
(HT + ListLength + 1 ) -> lchild = s2.num;
}
printf( " now ListLength=%d " ,ListLength);
ListLength ++ ;
PrintHTree(HT);
}
printf( " CreateHTreeSucceed " );
printf( " ListLength=%d " ,ListLength);
return OK;
}
Status TransCode(HuffmanCode HT,HCode & HC, int num)
{
// printf("this is TransCode ");
HTNode * P;HTNode * S, * M; char * ori, * des, * tmp;
P = HT;
int i; int CLength;CLength = 0 ;
i = num; int count;count = 0 ;
HC.data = (P + i) -> data;S = P + i;
M = S;
ori = ( char * )malloc( sizeof ( char ));
tmp = ori;
while (S -> parent != 0 )
{
M = S;
S = S + ((S -> parent) - (S -> num));
if ((S -> lchild) == (M -> num))
{
tmp = ori + count; * tmp = ' 0 ' ;CLength ++ ;
}
if ((S -> rchild) == (M -> num))
{
tmp = ori + count; * tmp = ' 1 ' ;CLength ++ ;
}
count ++ ;
ori = ( char * )realloc(ori, sizeof ( char ) * (count + 1 ));
tmp = ori + count - 1 ;
}
des = ( char * )malloc( sizeof ( char ) * (count + 1 ));
for ( int x = 0 ;x < count;x ++ )
{
printf( " %c " , * ori);
* (des + count - x - 1 ) =* ori;
ori ++ ;
}
printf( " (P+i)->data=%c " ,(P + i) -> data);
HC.HFC = ( char * )malloc( sizeof ( char ) * count);
for (x = 0 ;x < count;x ++ )
{
* (HC.HFC + x) =* (des + x);
}
HC.data = (P + i) -> data;
HC.HFCLength = count;
return OK;
} // TransCode把字母转换成对应的字符串.