(原创)哈夫曼树(1)

来源:互联网 发布:excel表格提取部分数据 编辑:程序博客网 时间:2024/05/22 17:27

 按照严慰敏书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把字母转换成对应的字符串.

 

 

 

原创粉丝点击