计算机软件技术基础实验报告_2
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机软件基础实验报告
姓名学号
实验目的
1. 掌握C语言程序设计方法, 并学会上机调试。
2. 熟悉Huffman编码源程序,并构造Huffman树。
实验内容
试设计一算法, 从包括n个元素的数组中, 求最大和最小元素, 并使得当n个元素为有序排列时, 元素之间的比较次数仅为n-1次。
在给出的Huffman编码源程序基础上, 要求画出Huffman树, 求出与等长编码相比时的压缩比。
实验要求
1.根据实验内容编写算法, 并用 C 语言进行程序设计。
2.将所编程序在计算机上调试通过,并全面测试.
实验结果
1. 以一个含有8个元素的一维数组{1, 2, 3, 5, 7, 8, 9, 12}为例,设计程序如下:
#include<stdio.h>
int maxArray(int x ,int y);
int minArray(int x ,int y);
int main(void)
{
int i = 0 ;
int array[8]={ 1, 2, 3, 5, 7, 8, 9, 12} ;
printf;
do
{
scanf("%d",&array[i]);
i++;
} while(i < 8);
int maxTemp = array[0];
int minTemp = array[0];
int maxIndex = 0;
int minIndex = 0;
for(i=1;i<8;i++)
{
maxTemp = maxArray(array[i] , maxTemp);
minTemp = minArray(array[i] , minTemp);
}
for(i=0;i<8;i++)
{
if (maxTemp == array[i])
{
maxIndex = i;
}
if (minTemp == array[i])
{
minIndex = i;
}
}
printf;
return 0;
}
运行结果如下:
2.Huffman编码源程序
#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';
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=0;i<n;i++) 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各结点空间for(p=HT+1,i=1;i<=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+1;i<=m;++i) //建哈夫曼树
{Select(HT,i-1,s1,s2);
//从HT[1...i-1]中选择parent为0且weight最小的两个结点, 其序号分别为s1和s2
HT[s1].parent=i; HT[s2].parent=i; //修改s1和s2结点的父指针parent
HT[i].lchild=s1; HT[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=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'; //若是左孩子编为'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=1;i<=n;i++)
{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=1;i<=t;i++)
{if(HT[i].parent==0&&(HT[i].weight<m||HT[i].weight<n)) if(m<n)
{n=HT[i].weight;s2=i;}
else {m=HT[i].weight;s1=i;}
}
if(s1>s2) //s1放较小的序号
{i=s1;s1=s2;s2=i;}
}
运行结果如下:
输入数据后的运行结果:
实验心得
要熟练掌握程序的编写, 如果没有一定的想象能力和大量的上机实践是根本无法完成的。
首先要做的是多看程序, 勤编程序。
完整地编写一个准确、严谨的程序绝非易事。
大量阅读程序有助于我们掌握编程的常用语法和基本要领。
随着阅读量的不断增加, 我们大脑中对于知识的积累越来越丰富, 对于编程的感觉也越来越敏感。
渐渐地, 在基本掌握了编程的方法套路后, 我们大脑中的“数据库”日益壮大, 编写各种类型的程序便会显得得心应手, 也不再像以前那样看到编程就会一头雾水。
当对程序熟练到一定程度后, 我们甚至可以试着去纠正别人程序中的一些不妥之处, 这不仅使得程序更加完善, 更是对自己编程能力的更高一层的肯定。
其次, 上机实践, 也是必不可少的环节。
上机实践的目的是能够更好地检验所编程序的准确性和可行性,还可以帮助我们更加深刻地了解程序的运行过程。
对于一个编写完成的程序, 如果没有上机调试过, 即使程序完全正确, 也未必能够充分理解其功能和目的。
总之, 编程有一定的难度。
但只要勤加训练, 定能熟能生巧。