(原创)哈夫曼树(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把字母转换成对应的字符串.
#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把字母转换成对应的字符串.
- (原创)哈夫曼树(1)
- (原创)哈夫曼树(2)
- 【原创】GCD编程 - 1
- 原创文章1
- 1、csdn 原创标题
- 原创!!!
- 原创
- 原创
- 原创
- [原创]
- 原创
- 原创
- 原创
- 原创
- 原创
- 原创
- 原创
- 原创
- javascript中的异常处理
- 你适合去外企工作吗?
- GridView中实现类邮件的CheckBox全选功能
- SQLserver2005中的分区表
- phpmyadmin连接mysql的问题
- (原创)哈夫曼树(1)
- snoopy——PHP版的网络客户端
- LOKI_TYPELIST的简单与复杂
- 开发大型高负载类网站应用的几个要点
- 25 种能马上改善网站、提高浏览量的方法
- php输出标准xml,php访问mysql数据库简单例子(可以被asp等程序读取)
- 使用FleaPHP框架构建简单留言本应用
- Mantis相关配置
- 我自己想的几道入门PHP笔试题