简单的Huffman霍夫曼编码。用C语言实现。

Python010

简单的Huffman霍夫曼编码。用C语言实现。,第1张

#include<stdio.h>

#include<conio.h>

#include<iostream.h>

#include<string.h>

#include<stdlib.h>

#define

MAXVALUE

10000

/*权值最大值*/

#define

MAXLEAF

30

/*叶子最多个数*/

#define

MAXNODE

MAXLEAF*2-1

/*

结点数的个数*/

#define

MAXBIT

50

/*编码的最大位数*/

typedef

struct

node

/*结点类型定义*/

{

char

letter

int

weight

int

parent

int

lchild

int

rchild

}HNodeType

typedef

struct

/*编码类型定义*/

{

char

letter

int

bit[MAXBIT]

int

start

}HCodeType

typedef

struct

/*输入符号的类型*/

{

char

s

int

num

}lable

void

HuffmanTree(HNodeType

HuffNode[],int

n,lable

a[])

{

int

i,j,m1,m2,x1,x2,temp1

char

temp2

for

(i=0i<2*n-1i++)

/*结点初始化*/

{

HuffNode[i].letter=0

HuffNode[i].weight=0

HuffNode[i].parent=-1

HuffNode[i].lchild=-1

HuffNode[i].rchild=-1

}

for

(i=0i<n-1i++)

for

(j=i+1j<n-1j++)

/*对输入字符按权值大小进行排序*/

if

(a[j].num>a[i].num)

{

temp1=a[i].num

a[i].num=a[j].num

a[j].num=temp1

temp2=a[i].s

a[i].s=a[j].s

a[j].s=temp2

}

for

(i=0i<ni++)

{

HuffNode[i].weight=a[i].num

HuffNode[i].letter=a[i].s

}

for

(i=0i<n-1i++)

/*构造huffman树*/

{

m1=m2=MAXVALUE

x1=x2=0

for

(j=0j<n+ij++)/*寻找权值最小与次小的结点*/

{

if

(HuffNode[j].parent==-1&&HuffNode[j].weight<m1)

{

m2=m1

x2=x1

m1=HuffNode[j].weight

x1=j

}

else

if

(HuffNode[j].parent==-1&&HuffNode[j].weight<m2)

{

m2=HuffNode[j].weight

x2=j

}

}

HuffNode[x1].parent=n+i

HuffNode[x2].parent=n+i

/*权值最小与次小的结点进行组合*/

HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight

HuffNode[n+i].lchild=x1

HuffNode[n+i].rchild=x2

}

}

void

HuffmanCode(int

n,lable

a[])

{

HNodeType

HuffNode[MAXNODE]

HCodeType

HuffCode[MAXLEAF],cd

int

i,j,c,p

HuffmanTree(HuffNode,n,a)

for

(i=0i<ni++)

/*按结点位置进行编码*/

{

cd.start=n-1

c=i

p=HuffNode[c].parent

while

(p!=-1)

{

if

(HuffNode[p].lchild==c)

cd.bit[cd.start]=0

else

cd.bit[cd.start]=1

cd.start--

c=p

p=HuffNode[c].parent

}

for

(j=cd.start+1j<nj++)

/*储存编码*/

HuffCode[i].bit[j]=cd.bit[j]

HuffCode[i].start=cd.start

}

for

(i=0i<ni++)

{

HuffCode[i].letter=HuffNode[i].letter

printf("

%c

",HuffCode[i].letter)

for

(j=HuffCode[i].start+1j<nj++)

printf("%d",HuffCode[i].bit[j])

printf("\n")

}

}

int

main()

{

lable

data[30]

char

s[100],*p

int

i,count=0

for

()

{

cout<<"

/

求哈夫曼编码,直到输入为end结束!

/"<<endl

printf("

Input

some

letters:")

scanf("%s",s)

if

(!strcmp(s,"end"))

exit(0)

for

(i=0i<30i++)

{

data[i].s=0

data[i].num=0

}

p=s

while

(*p)

/*计算字符个数与出现次数(即权值)*/

{

for

(i=0i<=count+1i++)

{

if

(data[i].s==0)

{

data[i].s=*p

data[i].num++

count++

break

}

else

if

(data[i].s==*p)

{

data[i].num++

break

}

}

p++

}

printf("\n")

printf("

different

letters:%d\n",count)

for

(i=0i<counti++)

{

printf("

%c

",data[i].s)

printf("weight:%d\n",data[i].num)

}

HuffmanCode(count,data)

count=0

}

getch()

}

这是我们的软件实习答案,希望对你有帮助!

由于哈夫曼树中没有度为1的结点,则一棵有n个叶子的哈夫曼树共有2n-1个结点,可以用一个大小为2n-1的一维数组存放哈夫曼树的各个结点。在哈夫曼树构造好后,为了求得哈夫曼编码需要走一条从根结点出发到叶子结点的路径,则对每个结点既要知道其双亲还要知道孩子结点的信息。所以一维数组的每个元素包括四个数据项:结点的权值、结点的双亲结点下标号、左右孩子结点下标号。数据类型的定义如下:

typedef struct Node

{

int weight

int parent, LChild,RChild

} HTNode, * HTree

typedef char *HuffmanCode

创建哈夫曼树并求哈夫曼编码的算法如下:

viod CreatHTree(HTree ht , HuffmanCode hc,int * w, int n)

{ /*w存放n个权值,构造哈夫曼树ht,并求出哈夫曼编码hc */

int start

m=2*n-1

ht=(HTree)malloc((m+1)*sizeof(HTNode))

for(i=1i<=ni++)

ht[i] ={ w[i],0,0,0}

for(i=n+1i<=mi++)(* ht)[i] ={0,0,0,0}/* 初始化*/

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

{

select(ht,i-1,&s1,&s2)

/* 在ht[1]~ht[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回,select函数要求在上机调试使补充定义*/

ht[s1].parent=i

ht[s2].parent=i

ht[i].LChild=s1

ht[i].RChild=s2

ht[i].weight=ht[s1].weight+ht[s2].weight

} /*哈夫曼树建立完毕*/

/*以下程序是从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码的过程*/

hc=(HuffmanCode)malloc((n+1)*sizeof(char *))

cd=(char * )malloc(n * sizeof(char))

cd[n-1]=’\0’;

for(i=1i<=ni++)

{

start=n-1

for(c=i,p=ht[i].parentp!=0c=p,p=ht[p].parent)

if(ht[p].LChild==c) cd[--start]=‘0’

else cd[--start]=‘1’

hc[i]=(char *)malloc((n-start)*sizeof(char))

strcpy(hc[i],&cd[start])

}

free(cd)

}

数组ht的前n个单元存放叶子结点的信息,最后一个单元存放的是根结点。

自己写个主程序,把八个字符的频率读入,调用CreatHTree就可以了