求用c语言实现霍夫曼编码的程序,最好能带讲解的程序。感谢!

求用c语言实现霍夫曼编码的程序,最好能带讲解的程序。感谢!,第1张

//* * * * * * * * * * * * * * * * * * * * * * * *

/敬竖弊/哈夫曼树的构造哈夫曼树,哈夫曼编码 *

//* * * * * * * * * * * * * * * * * * * * * * * *

#include <dos.h>

#include <conio.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

typedef struct

{unsigned int weight //结点权值

unsigned int parent,lchild,rchild//结点的父指针,左右孩子指针

}HTNode,*HuffmanTree //动态分配数组存储哈夫曼树

typedef char **HuffmanCode//动态分配数组亮族存储哈夫曼编码表

void CreateHuffmanTree(HuffmanTree &,unsigned int*,int )//生成一棵哈夫曼树

void HuffmanCoding(HuffmanTree,HuffmanCode &,int ) //对哈夫曼树进行编码

void PrintHuffmanCode(HuffmanCode,unsigned int*,int)//显示哈夫曼编码

void Select(HuffmanTree,int,int&,int&)//在数组中寻找权值最小的两个结点

void main()

{HuffmanTree HT //哈夫曼树HT

HuffmanCode HC //哈夫曼编码表HC

int n,i//n是哈夫曼树叶子结点数

unsigned int *w//w存放叶子结点权值

char j='y'

textbackground(3) //设定屏幕颜色纤羡

textcolor(15)

clrscr()

//程序解说

printf("本程序将演示构造哈夫曼树.\n")

printf("首先输入叶子结点数目.\n例如:8\n")

printf("然后输入每个叶子结点的权值.\n")

printf("例如:5 29 7 8 14 23 3 11\n")

printf("程序会构造一棵哈夫曼树并显示哈夫曼编码.\n")

printf(" 5---0110\n 29---10\n 7---1110\n 8---1111\n 14---110\n")

printf(" 23---00\n 3---0111\n 11---010\n")

while(j!='N'&&j!='n')

{printf("请输入叶子结点数目:")

scanf("%d",&n) //输入叶子结点数

if(n<=1) {printf("该数不合理!\n")continue}

w=(unsigned int*)malloc(n*sizeof(unsigned int))//开辟空间存放权值

printf("请输入各叶子结点的权值:\n")

for(i=0i<ni++) scanf("%d",&w[i]) //输入各叶子结点权值

CreateHuffmanTree(HT,w,n) //生成哈夫曼树

HuffmanCoding(HT,HC,n) //进行哈夫曼编码

PrintHuffmanCode(HC,w,n) //显示哈夫曼编码

printf("哈夫曼树构造完毕,还要继续吗?(Y/N)")

scanf(" %c",&j)

}

}

void CreateHuffmanTree(HuffmanTree &HT,unsigned int *w,int n)

{//w存放n个结点的权值,将构造一棵哈夫曼树HT

int i,m

int s1,s2

HuffmanTree p

if(n<=1) return

m=2*n-1 //n个叶子结点的哈夫曼树,有2*n-1个结点

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode))//开辟2*n各结点空间,0号单元不用

for(p=HT+1,i=1i<=n++i,++p,++w) //进行初始化

{p->weight=*w

p->parent=0

p->lchild=0

p->rchild=0

}

for(i<=m++i,++p)

{p->weight=0

p->parent=0

p->lchild=0

p->rchild=0

}

for(i=n+1i<=m++i) //建哈夫曼树

{Select(HT,i-1,s1,s2)

//从HT[1...i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2

HT[s1].parent=iHT[s2].parent=i//修改s1和s2结点的父指针parent

HT[i].lchild=s1HT[i].rchild=s2//修改i结点的左右孩子指针

HT[i].weight=HT[s1].weight+HT[s2].weight//修改权值

}

}

void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n)

{//将有n个叶子结点的哈夫曼树HT进行编码, 所编的码存放在HC中

//方法是从叶子到根逆向求每个叶子结点的哈夫曼编码

int i,c,f,start

char *cd

HC=(HuffmanCode)malloc((n+1)*sizeof(char *))//分配n个编码的头指针向量

cd=(char *)malloc(n*sizeof(char)) //开辟一个求编码的工作空间

cd[n-1]='\0' //编码结束符

for(i=1i<=n++i) //逐个地求哈夫曼编码

{start=n-1 //编码结束位置

for(c=i,f=HT[i].parentf!=0c=f,f=HT[f].parent) //从叶子到根逆向求编码

if(HT[f].lchild==c) cd[--start]='0' //若是左孩子编为'0'

else cd[--start]='1' //若是右孩子编为'1'

HC[i]=(char *)malloc((n-start)*sizeof(char)) //为第i个编码分配空间

strcpy(HC[i],&cd[start])//将编码从cd复制到HC中

}

free(cd)//释放工作空间

}

void PrintHuffmanCode(HuffmanCode HC,unsigned int *w,int n)

{//显示有n个叶子结点的哈夫曼树的编码表

int i

printf("HuffmanCode is :\n")

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

{printf(" %3d---",w[i-1])

puts(HC[i])

}

printf("\n")

}

void Select(HuffmanTree HT,int t,int&s1,int&s2)

{//在HT[1...t]中选择parent不为0且权值最小的两个结点,其序号分别为s1和s2

int i,m,n

m=n=10000

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

{if(HT[i].parent==0&&(HT[i].weight<m||HT[i].weight<n))

if(m<n)

{n=HT[i].weights2=i}

else {m=HT[i].weights1=i}

}

if(s1>s2) //s1放较小的序号

{i=s1s1=s2s2=i}

}

#include<string.h>

#include<stdlib.h>

#include<stdio.h>

int m,s1,s2

typedef struct {

unsigned int weight

unsigned int parent,lchild,rchild

}HTNode,*HuffmanTree//动态分配数组存储哈夫曼树

typedef char *HuffmanCode//动态分配数组存储哈夫曼编码表

void Select(HuffmanTree HT,int n) {

int i,j

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

if(!HT[i].parent){s1 = ibreak}

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

if(!HT[j].parent){s2 = jbreak}

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

if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))s1=i

for(j = 1j <= nj++)

if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j

}

void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) {

// 算法6.13

// w存放n个字符的权值(均>0),构造哈夫曼树HT,

// 并求出n个字符派培猜的哈夫曼编码HC

int i, j

char *cd

int p

int cdlen

if (n<=1) return

m = 2 * n - 1

HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode))// 0号单元未用

for (i=1i<=ni++) { //初始化

HT[i].weight=w[i-1]

HT[i].parent=0

HT[i].lchild=0

HT[i].rchild=0

}

for (i=n+1i<=mi++) { //初始化

HT[i].weight=0

HT[i].parent=0

HT[i].lchild=0

HT[i].rchild=0

}

puts("\n哈夫曼树的构造过程如下所示:")

printf("HT初态:\n 结点 weight parent lchild rchild")

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

printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,

HT[i].parent,HT[i].lchild, HT[i].rchild)

printf(" 按任意键,继续 ...")

getchar()

for (i=n+1i<=mi++) { // 建哈夫曼树

// 在HT[1..i-1]中选择parent为0且weight最小的两个结点中散,

// 其序号分别为s1和s2。

Select(HT, i-1)

HT[s1].parent = iHT[s2].parent = i

HT[i].lchild = s1HT[i].rchild = s2

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

printf("\nselect: s1=%d s2=%d\n", s1, s2)

printf(" 结点 weight parent lchild rchild")

for (j=1j<=ij++)

printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight,

HT[j].parent,HT[j].lchild, HT[j].rchild)

printf(" 按任意键,继续 ...")

getchar()

}

//------无栈非递尘型归遍历哈夫曼树,求哈夫曼编码

cd = (char *)malloc(n*sizeof(char))// 分配求编码的工作空间

p = mcdlen = 0

for (i=1i<=m++i) // 遍历哈夫曼树时用作结点状态标志

HT[i].weight = 0

while (p) {

if (HT[p].weight==0) { // 向左

HT[p].weight = 1

if (HT[p].lchild != 0) { p = HT[p].lchildcd[cdlen++] ='0'}

else if (HT[p].rchild == 0) { // 登记叶子结点的字符的编码

HC[p] = (char *)malloc((cdlen+1) * sizeof(char))

cd[cdlen] ='\0'strcpy(HC[p], cd)// 复制编码(串)

}

} else if (HT[p].weight==1) { // 向右

HT[p].weight = 2

if (HT[p].rchild != 0) { p = HT[p].rchildcd[cdlen++] ='1'}

} else { // HT[p].weight==2,退回退到父结点,编码长度减1

HT[p].weight = 0p = HT[p].parent--cdlen

}

}

} // HuffmanCoding

void main() {

HuffmanTree HTHuffmanCode *HCint *w,n,i

puts("输入结点数:")

scanf("%d",&n)

HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode))

w = (int *)malloc(n*sizeof(int))

printf("输入%d个结点的权值\n",n)

for(i = 0i <ni++)

scanf("%d",&w[i])

HuffmanCoding(HT,HC,w,n)

puts("\n各结点的哈夫曼编码:")

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

printf("%2d(%4d):%s\n",i,w[i-1],HC[i])

getchar()

}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12531684.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存