求帮忙用C语言写哈夫曼编码

Python014

求帮忙用C语言写哈夫曼编码,第1张

由于哈夫曼树中没有度为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就可以了

以前写的,证明最优子结构,随便一本算法书上就有.

#include<stdio.h>

#include<stdlib.h>

#define

NIL

-2

#define

Size_Max_bm

30

#define

left(i)

(2*(i)+1)

#define

right(i)

(2*(i)+2)

#define

swap(a,b)

{cjys

tt=(a)(a)=(b)(b)=t}

#define

parent(i)

((i)%2?((i)-1)/2:((i)-2)/2)typedef

struct

cjys

{

char

sj

int

pl

struct

cjys

*left

struct

cjys

*right

}cjystypedef

struct

cjdl

{

int

size

int

leapsize

cjys

*p

}cjdl

cjys

*fpnn(void)

void

input(cjdl

*p)

cjys

*fpnn(void)

void

zxdwh(cjys

*p,

int

i,

int

leapsize)

void

rd(cjdl

*p,

cjys

tp)

cjys

cd(cjdl

*p)

void

hbs(cjdl

*p)

cjys

*cjs(cjdl

*p)

void

bls(cjys

*p,int

*jl,

int

i)

void

disp(char

*tp,

cjys

*p)int

main()

{

cjdl

p

char

x[255]

cjys

*re=NULL

int

jl[Size_Max_bm]

input(&p)

re=cjs(&p)

printf("对照编码图为:\n")

bls(re,jl,0)

freopen("CON","r",stdin)

printf("输入Huffman码(VLC):")

scanf("%s",x)

disp(x,re)

system("pause")

}

void

input(cjdl

*p)

{

int

i

cjys

*tp

tp=fpnn()

printf("输入字母个数:")

scanf("%d",

&p->size)

p->p=malloc(sizeof(cjys)*p->size)

p->leapsize=0

for(i

=

0

i

<

p->sizei++)

{

printf("输入第%d字母:",i+1),scanf("

%c",&tp->sj)

printf("输入出现次数(频率整数):"),scanf("%d",&tp->pl)

rd(p,*tp)

}

free(tp)

}

cjys

*fpnn(void)

{

cjys

*p=NULL

p=malloc(sizeof(cjys))

p->left=NULL

p->right=NULL

return

p

}

void

zxdwh(cjys

*p,

int

i,

int

leapsize)

{

int

l=left(i),

r=right(i),

mini=i

if(l<leapsize

&&

p[l].pl<p[mini].pl)

mini=l

if(r<leapsize

&&

p[r].pl<p[mini].pl)

mini=r

if(mini

!=

i)

{

swap(p[i],p[mini])

zxdwh(p,mini,leapsize)

}

}

void

rd(cjdl

*p,

cjys

tp)

{

if(p->leapsize

==

p->size)

{

printf("队列已满!")

exit(0)

}

p->p[p->leapsize]=tp

int

j=p->leapsize,k=parent(j)

while(k>=0

&&

p->p[j].pl

<

p->p[k].pl)

{

swap(p->p[j],p->p[k])

j=k

k=parent(j)

}

p->leapsize++

}

cjys

cd(cjdl

*p)

{

if(p->leapsize

==

0)

{

printf("队列已空!")

exit(0)

}

cjys

tp=p->p[0]

p->leapsize--

p->p[0]=p->p[p->leapsize]

zxdwh(p->p,0,p->leapsize)

return

tp

}

void

hbs(cjdl

*p)

{

cjys

*p1=NULL,

*p2=NULL

cjys

tp

p1=fpnn()

p2=fpnn()

*p1=cd(p)

*p2=cd(p)

tp.left=p1

tp.right=p2

tp.pl=p1->pl+p2->pl

tp.sj=NIL

rd(p,tp)

}cjys

*cjs(cjdl

*p)

{

int

i,

n=p->leapsize

cjys

*tp=NULL

tp=fpnn()

for(i

=

0

i

<

n-1

i++)

hbs(p)

*tp=p->p[0]

return

tp

}

void

bls(cjys

*p,

int

*jl,

int

i)

{

if(p

==

NULL)

return

if(p->sj!=NIL)

{

int

i2

printf("%c:",p->sj)

for(i2

=

0

i2

<

i

i2++)

printf("%d",jl[i2])

printf("\n")

}

jl[i]=0

bls(p->left,jl,i+1)

jl[i]=1

bls(p->right,jl,i+1)

}

void

disp(char

*tp,

cjys

*p)

{

cjys

*ttp=NULL

int

pd=0

while(1)

{

ttp=p

while(1)

{

if(ttp->sj

!=

NIL)

{

printf("%c",ttp->sj)

break

}

if(*tp

==

'\0')

{

pd=1

break

}

if(*tp++

==

'0'

)

ttp=ttp->left

else

ttp=ttp->right

}

if(pd)

break

}

}

#include<stdio.h>

#include<stdlib.h>

#define MAXSIZE 20

typedef struct TreeNode *HuffmanTree

typedef HuffmanTree ElemType

typedef struct code Code

struct TreeNode{

char c

int Weight

HuffmanTree Left,Right

}

typedef struct Heap{

ElemType Data[MAXSIZE]

int Size

int Capacity

}*MinHeap

struct code{

char c

char code[10]

}

struct TNode{

int Data

struct TNode* lchild

struct TNode* rchild

}

MinHeap BuildHeap()

{

MinHeap tmpH

tmpH=(MinHeap)malloc(sizeof(struct Heap))

ElemType Min=(ElemType)malloc(sizeof(ElemType))

Min->Weight=-1,Min->Left=Min->Right=NULL

tmpH->Size=0

tmpH->Capacity=MAXSIZE

tmpH->Data[0]=Min

return tmpH

}

int isFull(MinHeap H)

{

return H->Size>=H->Capacity

}

int isEmpty(MinHeap H)

{

return H->Size==0

}

void Insert(MinHeap H,ElemType T)

{

int i

if(isFull(H)){

printf("MinHeap is Full")

return

}

i=++H->Size

for(H->Data[i/2]->Weight>T->Weighti/=2)

H->Data[i]=H->Data[i/2]

H->Data[i]=T

}

ElemType DeleteMin(MinHeap H){

int Parent,child

ElemType min,tmp

if(isEmpty(H)){

printf("The Heap is Empty")

return NULL

}

min=H->Data[1]

tmp=H->Data[H->Size--]

for(Parent=1Parent*2<H->SizeParent=child)

{

child=Parent*2

if(child!=H->Size-1&&H->Data[child]->Weight>H->Data[child+1]->Weight)

child++

if(tmp->Weight>H->Data[child]->Weight)

{

H->Data[Parent]=H->Data[child]

}else break

}

H->Data[Parent]=tmp

return min

}

void InitHeap(MinHeap H,int n)

{

ElemType tmp

for(int i=0i<ni++)

{ getchar()

tmp=(ElemType)malloc(sizeof(ElemType))

scanf("%c,%d",&tmp->c,&tmp->Weight)

tmp->Left=tmp->Right=NULL

Insert(H,tmp)

}

}

HuffmanTree Huffman(MinHeap H)

{

int i

HuffmanTree T

for(i=1i<H->Sizei++)

{

T=(HuffmanTree)malloc(sizeof(HuffmanTree))

T->Left=DeleteMin(H)

T->Right=DeleteMin(H)

T->Weight=T->Left->Weight+T->Right->Weight

Insert(H,T)

}

T=DeleteMin(H)

return T

}

int main()

{

int n

scanf("%d",&n)

Code ans[n]

MinHeap H=BuildHeap()

HuffmanTree T

InitHeap(H,n)

T=Huffman(H)

return 0

}

哈夫曼树的构造,编码有01左右子树之分,稍微复杂