(原创)哈夫曼树(1)

 按照严慰敏书P149页上的哈夫曼编码表具体算法为147页算法6.12

把书上的给改了。

typedef struct
{
 int num;//编号
 char data;//数据可存字母'abcdefgh';
 int weight;//权值
 int parent,lchild,rchild;//父亲和左右孩子所在位置
}HTNode,*HuffmanCode;

为树结点的存储结构,而且书上的例子不能把权值大的结点放在左叶子结点,因此和书上的不太一样。这个程序可以直接在VC中运行,可能还有些错误。输入的值为:

编号(num)数据(data)权值(weight)
1a5
2b29
3c7
4d8
5e14
6f23
7g3
8h11

 

#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把字母转换成对应的字符串.

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值