当前位置:文档之家› 哈夫曼编码源程序最新解释

哈夫曼编码源程序最新解释

哈夫曼编码

一、源程序

#include

#include

#include

#include

/* Huffman 树的存储结构*/

#define n 8 /*叶子数目根据需要设定*/

#define m 2*n-1 /* Huffman 树中结点总数*/

typedef struct

{int weight; /*结点的权值*/

int lchild,rchild,parent; /*左、右孩子及双亲的下标*/

}htnode;

typedef htnode huffmantree[m+1];/* huffmantree是结构数组类型,其0号单元不用,存储哈夫曼树*/

typedef struct

{char ch; /*存储字符*/

char code[n+1]; /*存放编码位串*/

}codenode;

typedef codenode huffmancode[n+1];/*huffmancode是结构数组类型,其0号单元不用,存储哈夫曼编码*/

void inithuffmantree(huffmantree ht) /*初始化哈夫曼树函数inithuffmantree()*/

{int i;

for(i=0;i<=m;i++)

{ht[i].weight=0;

ht[i].lchild=ht[i].rchild=ht[i].parent=0;

}

}

void inputweight(huffmantree ht) /*输入权值函数*/

{int i;

for(i=1;i<=n;i++)

{printf("请输入第%d个权值: ",i);

scanf("%d",&ht[i].weight);

}

}

void selectmin(huffmantree ht, int i, int *p1, int *p2)

/* 在ht[1..i]中选两个权值最小的根结点,其序号为*p1和*p2,*p1中放权值最小的根结点的序号,*p2中放权值次小的根结点的序号*/

{int j,min1,min2; /* min1,min2分别是最小权值和次小权值*/

min1=min2=32767;

*p1=*p2=0;

for(j=1;j<=i;j++)

{if(ht[j].parent==0) /* j 为根结点*/

if(ht[j].weight

{

if(min1!=32767) {min2=min1; *p2=*p1;}

min1=ht[j].weight;

*p1=j;

}

else

if(ht[j].weight

{min2=ht[j].weight;

*p2=j;}

}

}

void createhuffmantree(huffmantree ht) /*构造huffman树,ht[m]为其根结点*/

{

int i,p1,p2;

inithuffmantree(ht); /* 将ht初始化*/

inputweight(ht); /* 输入叶子权值至ht [1..n]的weight域*/

for(i=n+1;i<=m;i++) /* 共进行n-1次合并,新结点依次存于ht[i]中*/ {selectmin(ht,i-1,&p1,&p2); /*在ht [1.. i-1]中选择两个权值最小的根结点,其序号分别为p1和p2*/

ht[p1].parent=ht[p2].parent=i;

ht[i].lchild=p1; /* 最小权值的根结点是新结点的左孩子*/

ht[i].rchild=p2; /* 次小权值的根结点是新结点的右孩子*/

ht[i].weight=ht[p1].weight+ht[p2].weight;

}

}

void huffmancodes(huffmantree ht,huffmancode hcd) /*根据huffman树ht求huffman编码*/ {

int c,p,i; /* c和p分别指示ht中孩子和双亲的位置*/

char cd[n+1]; /* 临时存放编码*/

int start; /* 指示编码在cd 中的起始位置*/

cd[n]='\0';

getchar(); /* 编码结束符*/

printf("请输入字符");

for(i=1;i<=n;i++) /* 依次求叶子ht [i]的编码*/

{ hcd[i].ch=getchar(); /* 读入叶子ht [i]对应的字符*/

start=n; /* 编码起始位置的初值*/

c=i; /* 从叶子ht [i]开始上溯*/

while((p=ht[c].parent)!=0) /* 直至上溯到ht [ c]是树根为止*/

{ cd[--start]=(ht[p].lchild==c)?'0':'1'; /*若ht [ c]是ht[p]的左孩子,则生成代码0,否则生成代码1*/

c=p; /* 继续上溯*/

}

strcpy(hcd[i].code,&cd[start]); /* 复制编码位串*/

}

printf("\n");

for(i=1;i<=n;i++)

printf("第%d个字符%c的编码为%s\n",i,hcd[i].ch,hcd[i].code);

}

void main()

{huffmantree t;

huffmancode h;

printf("\n请输入%d个权值\n",n);

createhuffmantree(t); /* 构造huffman树*/

huffmancodes(t,h); /* 构造huffman编码*/

}

运行结果

心得

getch与getchar基本功能相同,差别是getch直接从键盘获取键值,不等待用户按回车,只要用户按一个键,getch就立刻返回, getch返回值是用户输入的ASCII码,出错返回-1.输入的字符不会回显在屏幕上.

getch函数常用于程序调试中,在调试时,在关键位置显示有关的结果以待查看,然后用getch函数暂停程序运行,当按任意键后程序继续运行.

#include

using namespace std;

struct htnode //哈夫曼树结点结构定义

{

char ch; //结点值

int weight; //结点权值

int parent; //父结点下标

int lchild,rchild; //左、右孩子结点下标

};

class huffmantree //哈夫曼树类定义

{

public:

void code(char str1[],int w[],int n); //编码

void uncode(char str1[],char str2[],int n); //解码

private:

htnode ht[3000]; //用数组存储哈夫曼树

void creathuffmantree(char str1[],int w[],int n); // 创建哈夫曼树

void select(int pos,int &r1,int &r2);

};

//在数组ht中从0到pos位置,查找未加入哈夫曼树的权值最小的两个数的位置r1,r2

//r1为权值最小的位置,r2为权值第二小的位置

void huffmantree::select(int pos,int &r1,int &r2)

{

r1=r2=0; //初始化为0位置

for(int i=1;i<=pos;i++)

{

if(ht[i].parent!=0) //父结点不等于0,表示已加入哈夫曼树

continue; //继续向前查找

if(r1==0) //把r1设置为1

r1=i;

else if(r2==0) //把r2设置为2

r2=i;

//从i等于3开始比较。我认为这里程序有问题,无法得到权最小的两位置,你自己再改改else if(ht[i].weight

r1=i;

else if(ht[i].weight

r2=i;

}

}

// 创建哈夫曼树,str1[]为结点值数组,w[]为权值数组,共n个结点

void huffmantree::creathuffmantree(char str1[],int w[],int n)

{

int pos;

//把结点值和权值复制到数组ht

for(pos=1;pos<=n;pos++) //注意没有使用ht数组位置为0的空间

{

ht[pos].weight=w[pos-1]; //结点权值

ht[pos].ch=str1[pos-1]; //结点值

ht[pos].parent=ht[pos].lchild=ht[pos].rchild=0; //父结点为0表示未加入哈夫曼树,左右孩子都为0表示叶子结点

}

//这是构造哈夫曼树的过程,即设置数组ht的其他结点

for(pos=n+1;pos<=2*n-1;pos++) //注意用n个数值构造的哈夫曼树有2*n-1个结点

{

int r1,r2;

select(pos-1,r1,r2);

ht[r1].parent=ht[r2].parent=pos; //把r1,r2结点加入哈夫曼树,并设置他们的父结点位置为pos

ht[pos].lchild=r1; //设置pos结点的左孩子为r1

ht[pos].rchild=r2; //设置pos结点的右孩子为r2

ht[pos].weight=ht[r1].weight+ht[r2].weight; //设置pos结点的权值为左右孩子权值的和ht[pos].parent=0; //其父结点为0

}

}

//求哈夫曼编码

void huffmantree::code(char str1[],int w[],int n)

{

creathuffmantree(str1,w,n); //建立哈夫曼树

int start,c,i,f,j;

char *cd;

cd=new char[n]; //用于保存哈夫曼编码

cd[n-1]='\0'; //设置字符串结束符

for(i=1;i<=n;i++) //分别输出n个结点的哈夫曼编码

{

start=n-1; //注意从cd数组的末尾向前加入编码

for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[c].parent) //从叶子结点往上走到根结点为止

{

//左0,右1

if(ht[f].lchild==c)

cd[--start]='0';

else

cd[--start]='1';

}

cout<<"结点"<

for(j=start;j

cout<

cout<

}

delete []cd; //撤销

}

//翻译哈夫曼编码,str1[]为结点值,str2[]为哈夫曼编码,共n个结点

//输出哈夫曼编码为str2的结点值

void huffmantree::uncode(char str1[],char str2[],int n)

{

int i,f;

char c;

for(i=0;i

{

//根结点在数组ht最后一个位置

//从上往下也是左0右1

for(f=2*n-1;ht[f].lchild!=0&&ht[f].rchild!=0;)

{

c=str2[i];

if(c=='1') //等于1往右走

{

f=ht[f].rchild;

i++;

}

else //等于0往左走

{

f=ht[f].lchild;

i++;

}

}

cout<

}

cout<

}

//这个不用注释了吧

int main()

{

char str[27],str2[3000],c;

char ch[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; int cd[27],s,len,i,w[27];

sb1:

cout<<"请输入要编码的字符串"<

cin>>str;

huffmantree obj;

s=0;

memset(cd,0,sizeof(cd));

len=strlen(str);

for(i=0;i

{

cd[str[i]-'a']++;

}

for(i=0;i<26;i++)

{

if(cd[i])

{

str[s]=ch[i];

w[s]=cd[i];

s++;

}

}

cout<<"各节点编码如下:"<

obj.code(str,w,s);

sb2:

cout<<"请输入要解码的01串"<>str2;

cout<<"解码结果如下:"<

cout<<"是否继续解码?(Y/N)"<

c=getchar();

if(c=='Y')

goto sb2;

cout<<"是否继续编码?(Y/N)"<

c=getchar();

if(c=='Y')

goto sb1;

return 0;

}

相关主题
文本预览
相关文档 最新文档