哈夫曼编码实验报告.docx

上传人:b****3 文档编号:24852049 上传时间:2023-06-02 格式:DOCX 页数:26 大小:18.76KB
下载 相关 举报
哈夫曼编码实验报告.docx_第1页
第1页 / 共26页
哈夫曼编码实验报告.docx_第2页
第2页 / 共26页
哈夫曼编码实验报告.docx_第3页
第3页 / 共26页
哈夫曼编码实验报告.docx_第4页
第4页 / 共26页
哈夫曼编码实验报告.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

哈夫曼编码实验报告.docx

《哈夫曼编码实验报告.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码实验报告.docx(26页珍藏版)》请在冰豆网上搜索。

哈夫曼编码实验报告.docx

哈夫曼编码实验报告

哈夫曼编码实验报告:

数据结构的某项实验

①问题描述:

给定n个字符的权值数组w,根据哈夫曼编码与译码规则,实现一个哈夫曼编/译码系统(利用实验指导书上的27个字符的数据进行实验)。

②利用顺序表存储Huffman树,编码结果的存储方式采用书上的结构。

③Huffman树的构造约定如下:

根的权值较小的子树作为左子树,当权值相等时,则先生成的子树是左子树;

按照结点的生成次序选择权值较小的两棵子树构造Huffman树;

从叶子结点到根结点逆向求出每个字符的Huffman编码,不采用递归方法;

从根结点开始实现译码,要求被译码的字符数大于20个字符。

④采用文件方式存储n个权值和待翻译的二进制代码,其余数据均不采用文件存储。

序号字符权值双亲结点左孩子右孩子

1□186000

2A64000

3B13000

4C22000

5D32000

6E103000

7F21000

8G15000

9H47000

10I57000

11J1000

12K5000

13L32000

14M20000

15N57000

16O63000

17P15000

18Q1000

19R48000

20S51000

21T80000

22U23000

23V8000

24W18000

25X1000

26Y16000

27Z1000

1.实验过程与结果

完整代码:

(实验环境codeblock)

#include

#include

#include

//左0右1

typedefstruct

{

unsignedintweight;

unsignedintparent,lchild,rchild;

charc;

intlength;

}HTNode,*HuffmanTree;

typedefchar**HuffmanCode;

voidsave(intn,intw[],charcode[],charch[])

{

FILE*fp;

charfilename[20];

inti;

printf("请输入要保存的文件名称:

\n");

scanf("%s",filename);

if((fp=fopen(filename,"wb"))==NULL)//打开输出文件

{

printf("cannotopenfile:

\n");

return;

}

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

{

if(fwrite(&w[i],sizeof(int),1,fp)!

=1)//数组向磁盘文件写入各叶子节点权值

printf("filewriteerror!

\n");

}

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

{

if(fwrite(&ch[i],sizeof(char),1,fp)!

=1)//数组向磁盘文件写入各叶子字母代表

printf("filewriteerror!

\n");

}

for(i=0;i<=strlen(code);i++)

{

if(fwrite(&code[i],sizeof(char),1,fp)!

=1)//数组向磁盘文件写入待破解电码代码

printf("filewriteerror!

\n");

}

printf("保存文件成功!

!

!

");

fclose(fp);

}

voidread(intn,intw[],charcode[],charch[])

{

FILE*fp;

charfilename[20];

inti;

printf("请输入读入的文件名:

\n");

scanf("%s",filename);

if((fp=fopen(filename,"rb"))==NULL)//以只读方式打开二进制文件

{printf("cannotopenfile\n");

fclose(fp);

}

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

fread(&w[i],sizeof(int),1,fp);//磁盘文件向数组读入

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

fread(&ch[i],sizeof(char),1,fp);

for(i=0;i<=strlen(code);i++)

fread(&code[i],sizeof(char),1,fp);

printf("读入数据成功!

");

fclose(fp);

}

voidcreateHuffmanTree(HuffmanTree\*HT,intw[],intn,charch[])

{

intm=2*n-1;

ints1,s2,i;

\*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

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

{(\*HT)[i].weight=w[i];(\*HT)[i].lchild=0;

(\*HT)[i].parent=0;(\*HT)[i].rchild=0;

(\*HT)[i].c=ch[i];(\*HT)[i].length=0;

}

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

{(\*HT)[i].weight=0;(\*HT)[i].lchild=0;

(\*HT)[i].parent=0;(\*HT)[i].rchild=0;

(\*HT)[i].c='\0';(\*HT)[i].length=0;

}

printf("\n构建哈夫曼树:

\n");

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

{select(HT,i-1,&s1,&s2);(\*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;

}printf("\n");

}

voidselect(HuffmanTree\*HT,intn,int\*s1,int\*s2)

{inti=0,min;

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

{if((\*HT)[i].parent==0)

{min=i;break;

}

}

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

{if((\*HT)[i].parent==0)

{if((\*HT)[i].weight<(\*HT)[min].weight)

{min=i;

}

}

}\*s1=min;

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

{if((\*HT)[i].parent==0&&i!

=(\*s1))

{min=i;break;

}

}

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

{if((\*HT)[i].parent==0&&i!

=(\*s1))

{if((\*HT)[i].weight<(\*HT)[min].weight)

{min=i;

}

}\*s2=min;

}

}

//从叶子到根逆向求每个字符的哈夫曼编码

voidcreatHuffmanCode(HuffmanTreeHT,HuffmanCodeHC,intn)

{

inti,j,c;

intstart;

intf;

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

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

cd[n-1]='\0';//从右向左逐位存放编码,先存放编码结束符

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

{start=n-1;

for(c=i,f=HT[i].parent;f!

=0;c=f,f=HT[f].parent)

{if(HT[f].lchild==c)

cd[--start]='0';

else

cd[--start]='1';

}

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

HT[i].length=n-start-1;//求编码长度

strcpy(HC[i],&cd[start]);

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

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

{

printf("权值为%3d对应字母为%c的叶子节点的哈夫曼编码是%s长度为%d\n",HT[i].weight,HT[i].c,HC[i],HT[i].length);}

}

//定义编码解码函数

voidTranslatecode(HuffmanTreeHT,HuffmanCodeHC,intn,charcode[])

{inti,j,m,c,choice;

intstart;

intf;

charzcode[100];//存放输入的字母字符串

m=2*n-1;

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

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

cd[n-1]='\0';//从右向左逐位存放编码,先存放编码结束符

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

{start=n-1;

for(c=i,f=HT[i].parent;f!

=0;c=f,f=HT[f].parent)

{if(HT[f].lchild=\=c)

cd[--start]='0';

else

cd[--start]='1';

}

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

strcpy(HC[i],&cd[start]);

}

while

(1)

{printf("\n是否进行编译操作。

1-执行2-退出:

\n");

scanf("%d",&choice);

getchar();

if(choice=\=1)

{printf("请输入需要编码的字母字符串:

\n");

gets(zcode);

printf("编译好的二进制编码为:

\n");

for(i=0;zcode[i]!

='\0';i++)

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

if(HT[j].c=\=zcode[i])

printf("%s",HC[j]);

}

elseif(choice=\=2)

break;

}

while

(1){printf("\n是否进行解码操作。

1-执行2-退出\n");

scanf("%d",&choice);

if(choice=\=1)

{j=0;

while(code[j]!

='\0')

{if(code[j]=\='0')

m=HT[m].lchild;

elsem=HT[m].rchild;

if(HT[m].lchild=\=0)//找到叶子节点m

{printf("%c",HT[m].c);

m=2\*n-1;//回到根节点

}j++;

}

getchar();

printf("\n原电码为:

\n");

printf("%s",code);

printf("\n请输入已破译的电文:

\n");

gets(zcode);

printf("反编译的电码为:

\n");

for(i=0;zcode[i]!

='\0';i++)

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

if(HT[j].c=\=zcode[i])

printf("%s",HC[j]);

printf("\n判断电文输入正确否1-正确2-错误:

\n");

scanf("%d",&choice);

if(choice=\=1)

printf("\n电文输入正确!

\n");

elseprintf("\n电文输入错误!

\n");}

elseif(choice=\=2)

break;}

}

//定义获取叶子节点权值和字母的函数

voidgetcode(charch[],intw[],intN[]){

inti,j,count;

intk=1;

chartemp;

charzcode[50];//字母字符串

printf("请输入字母字符串:

\n");

scanf("%s",zcode);

for(i=0;zcode[i]!

='\0';i++)

{if(zcode[i]=='*')

continue;

temp=zcode[i];

count=0;

for(j=i;zcode[j]!

='\0';j++)

{if(temp==zcode[j])

{zcode[j]='*';

count++;

}

ch[k]=temp;//记录叶子节点代表的字母

w[k]=count;//权值为字母出现频率

}

k++;}

N[0]=k-1;}

voidmain()

{HuffmanTreeHT;

HuffmanCodeHC;//各叶子节点的哈夫曼编码

charch[30];//各叶子节点的字符代表

charcode[400];//存放输入的二进制编码字符串

intw[30];//w数组存储权值

inti,j,n,m,c;

intN[1];//当执行0号操作时,作用等价于n的值

HC=(HuffmanCode*)malloc((n+1)*sizeof(char*));

while

(1)

{printf("\n0-输入叶子节点个数(采用2号方法建树时使用)");printf("\n1-输入字母字符创建哈夫曼树");//0号操作与1号操作选择一个

printf("\n2-输入数据的权值和相应的字符代表创建哈夫曼树");

printf("\n3-输入要破解的电文密码");

printf("\n4-文件存储信息");

printf("\n5-文件读取信息");

printf("\n6-构建哈夫曼树并打印哈夫曼树");

printf("\n7-求各叶子节点的哈夫曼编码");

printf("\n8-进行编码译码");

printf("\n请输入你要执行的操作:

\n");

scanf("%d",&c);

switch(c)

{case0:

printf("输入叶子节点个数n:

");

scanf("%d",&n);

m=2\*n-1;

break;

case1:

getcode(ch,w,N);

n=N[0];

m=2\*n-1;

break;

case2:

printf("\n请输入%d个数据的权值:

\n",n);

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

{printf("%d:

",i);

fflush(stdin);//清空输入缓存区

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

}

printf("请输入%d个数据的字符代表:

\n",n);

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

{printf("%d号为:

",i);

fflush(stdin);//清空输入缓存区

scanf("%c",&ch[i]);

}

break;

case3:

printf("请输入要破解的电文二进制编码:

\n");

scanf("%s",code);

break;

case4:

save(n,w,code,ch);

break;

case5:

read(n,w,code,ch);

break;

case6:

createHuffmanTree(&HT,w,n,ch);

printf("\n\*\*\**\*\*\*\*\*\*打印哈夫曼树\*\*\**\*\*\*\*\n");

printf("序号\t字符\t权值\t双亲\t左孩子\t右孩子\n");

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

printf("%d\t%c\t%d\t%d\t%d\t%d\t\n",i,HT[i].c,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);

break;

case7:

creatHuffmanCode(HT,&HC,n);

break;

case8:

Translatecode(HT,&HC,n,code);

break;

default:

break;

}

if((c<0)||(c>8))

break;

}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

运行结果:

首先进行输入节点信息并存储文件的方法构建哈夫曼树

由于太长只截取部分编码。

完整编码为000000001010011111100000000101001111000011110110001111110101111000011001100110110111001111010000110110010011111011110110011111110010000100101110000010111101000110011

保存文件

关闭程序,重新开始,此时选择读取文件方式构建哈夫曼树,文件hafuman.txt中存储着各叶子节点权值,对应字符和待编译的二进制编码,读取文件截图如下,其他操作6.7.8及结果同上。

给出另一种构建哈夫曼树的方法

字母个数为相应字母对应的权值

其他操作同输入节点建树或者读取文件建树相似,在此不再给出。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 自然景观

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1