北航计算机软件技术基础实验报告1线性表的插入与删除资料.docx
《北航计算机软件技术基础实验报告1线性表的插入与删除资料.docx》由会员分享,可在线阅读,更多相关《北航计算机软件技术基础实验报告1线性表的插入与删除资料.docx(18页珍藏版)》请在冰豆网上搜索。
北航计算机软件技术基础实验报告1线性表的插入与删除资料
实验报告
实验名称线性表的插入与删除
班级
学号
姓名
成绩
实验概述:
【实验目的及要求】
1.实验目的
掌握线性表在顺序分配下的插入与删除运算;掌握线性表的链式存储结构;掌握插入排序的方法;并掌握一种产生随机数的方法。
2.实验内容
产生1000个0至999间的随机整数,并以产生的次序存入一个数据文件中。
编制一个程序,依次实现以下功能:
定义一个有序(非递减)线性表,其最大容量为1000,初始时为空。
从由1产生的数据文件中依次取前N个随机整数,陆续插入到此线性表中,并要求在每次插入后保持线性表的有序性。
最后将此有序线性表打印输出。
在由
(2)产生的线性表中,依在1中产生的次序逐个将元素删除,直至表空为止。
以N=100及N=400分别运行2的程序,并比较它们的运行时间。
编写一个程序,用插入排序依次将1中产生的1000个随机整数链接成有序链表(不改变原随机数在存储空间中的顺序)。
3.实验步骤和要求
事先编制好实验内容中1、2、4的程序(可参考本实验中的方法说明),并调试通过。
运行1的程序,生成1000个0至999之间的随机整数的数据文件,并打印输出此数据文件。
以N=100运行2的程序,并记下运行时间。
以N=400运行2的程序,并记下运行时间。
运行4的程序。
整理程序清单和运行结果,写出实验报告。
【实验原理】
1.随机整数的产生
产生随机整数的方法有很多,下面只介绍一种方法:
设m=216,初值y0=0,则递推公式yi=mod(2053yi-1+13849,m)产生0至65535之间的随机整数。
如要产生0至999之间的随机整数,只需做运算xi=INT(1000yi/m)。
其中mod(*)是模运算,INT(*)是取整函数。
2.线性表的插入与删除
在本实验中线性表是动态增长的。
插入一个新元素后,为了使线性表仍保持有序,必须要找到新元素应插入的位置。
实际上这是一个插入排序的问题。
为了要将新元素插入到一个有序的线性表中,可以从原有序表的最后一个元素开始,往前逐个与新元素比较,并将大于新元素的所有元素都往后移动一个位置,直到找到新元素应插入的位置为止。
显然,插入一个新元素后,表的长度也增加了1。
现假设用一个数组L(1:
m)来存储线性表,其中m为最大容量(在本实验中为m=1000);用一个变量n表示线性表的长度(在本实验中,其初值为n=0)。
则可以得到将新元素插入到有序线性表的算法如下。
输入:
数组L(1:
m),有序线性表L(1:
n),需插入的新元素b。
其中n输出:
插入b后的有序线性表L(1:
n)。
要在原线性表中删除一个元素b(在本实验中,保证b在线性表中),且仍保持线性表的顺序存储结构,可以从线性表的第一个元素开始,往后逐个与新元素相比较,直到发现一个元素与新元素相等。
然后从当前位置的下一个元素开始,将后面所有元素都往前移动一个位置,直到线性表的最后一个位置为止。
显然,删除一个元素之后,线性表的长度减小了1。
其算法如下。
输入:
线性表L(1:
n),n为线性表的长度,删除的元素b(一定在线性表中)。
输出:
删除b后的线性表L(1:
n)。
在上述算法中,从线性表的第一个元素开始寻找要删除的元素b,实际上我们还可以从线性表的最后一个元素开始寻找b,其算法留给读者自行考虑。
3.线性链表的插入排序
定义一个二列数组A(1:
1000,1:
2),其中,A(i,1)(i=1,2,…,1000)依随机数产生的顺序存放1000个数据,A(i,2)(i=1,2,…,1000)为链接指针,将1000个随机数链接成有序链表。
其插入排序的方法如下。
依次从数据文件中读入一个数据,将它按行顺序存放到数组A的第一列中,然后通过相应行的第二列将它链接到已经有序的链表中。
其过程为:
将读入的数据依次与链表中各元素进行比较,找到其应该插入的位置后,适当改变链指针,将其插入。
其算法如下:
输入:
1000个随机整数。
输出:
头指针为H的有序链表。
【实验环境】(使用的软硬件)
处理器英特尔Corei5-4200M@2.50GHz双核
内存4GB(记忆科技DDR3L1600MHz)
操作系统Windows10专业版64位(DirectX12)
编译环境Dev-C++5.6.1
编译语言C
实验内容:
【实验方案设计】
1.利用递推公式yi=mod(2053yi-1+13849,m)产生0至65535之间的随机整数。
如要产生0至999之间的随机整数,只需做运算xi=INT(1000yi/m)。
将数据写入D:
\\data.txt中
2.从1中产生的文件中依次读出数据,以数组形式创建一个空白线性表,以插入排序算法依次将数据茶如有序线性表中,最后打印输出。
再从文件中依次读取数据,与线性表中元素对比,删除该元素。
删除方法为:
将线性表后一个元素的值赋给当前元素。
最终达到清空线性表的目的。
3.以N=100和N=400分别运行2中的程序,比较运行时间。
4.以二维数组的形式创建一个静态链表,第一维存放从文件中读取的数据,第二维存放指向下一个元素位置的指向记号,链表开始的标志是指向记号指向最小元素,链表结束的标志是指向记号置-1。
用插入排序的方法将数据存入数组中并形成链表结构。
5.整理实验结果,写出实验报告
【实验过程】(实验步骤、记录、数据、分析)
实验一:
源代码:
/*
实验1:
产生1000个0至999间的随机整数,并以产生的次序存入一个数据文件中。
*/
#include
#include
#include
intmain()
{
longm=65536,y=0;
intx,i;
//定义一个文件类型的指针
FILE*fp;
//用fopen函数新建一个文件,失败则返回0
if((fp=fopen("D:
\\data.txt","w"))==NULL)
{
fprintf(stderr,"Erroropeningfile.");
exit(0);
}
printf("ThedatahasbeenoutputtoD:
\\data.txt!
\n");
printf("Alldataisasfollows!
\n\n");
//递归创造1000个0~999之间的随机数
for(i=0;i<1000;i++)
{
y=(2053*y+13849)%m;
x=(int)(1000*y/m);
fprintf(fp,"%d\n",x);
printf("%d:
%d\t",i+1,x);
}
//关闭文件
fclose(fp);
exit
(1);
}
运行结果:
实验二、实验三:
源代码:
/*
实验2:
编制一个程序,依次实现以下功能:
1.定义一个有序非递减线性表,其最大容量为1000,初始时为空。
2.从由1产生的数据文件中依次取前N个随机整数陆续插入到此线性表中,
并要求在每次插入后保持线性表的有序性。
最后将此有序线性表打印输出。
3.在由2产生的线性表中,依在1中产生的次序逐个将元素删除直至
表空为止。
实验3:
以N=100及N=400分别运行2的程序,并比较它们的运行时间。
*/
#include
#include
#include
#defineN1000
voidmain()
{
//新建时钟变量,得到程序从开始运行到某时刻经过的时钟周期数
clock_tstart,finish;
FILE*fp;
inta[1000];
inti,j,n,temp;
doubleduration;
//Part1:
创建一个有序线性表
start=clock();
if((fp=fopen("D:
\\data.txt","r"))==NULL)
{
fprintf(stderr,"Erroropeningfile.");
exit(0);
}
//判断插入顺序是否合理
elseif(n=N>1000)
{
printf("Dataoverflow!
Pleasetryagain!
");
exit(0);
}
//比较插入元素与有序表中元素位置并插入
elsefor(n=0;n{
fscanf(fp,"%d",&temp);
if(n==0)
a[0]=temp;
//将比a[i]大的数向后移动一格,将a[i]放入线性表
else
{
for(i=n;(i>0)&&(a[i-1]>temp);i--)
a[i]=a[i-1];
a[i]=temp;
}
}
for(i=0;iprintf("%d\t",a[i]);
fclose(fp);
finish=clock();
//计算程序运行时间
duration=(double)(finish-start)/CLOCKS_PER_SEC;
printf("\n\n");
printf("Asortedlinearlisthasbeencreated!
\n");
printf("Thelengthofitis%d.\n",n);
printf("Timetaken:
%fs\n\n",duration);
//Part2:
按创建顺序删除线性表
start=clock();
if((fp=fopen("D:
\\data.txt","r"))==NULL)
{
fprintf(stderr,"Erroropeningfile.");
exit(0);
}
//判断删除位置是否合理
if(n==0)
{
printf("Dataunderflow!
Pleasetryagain!
");
exit(0);
}
//在线性表中利用顺序查找法找到元素位置
elsefor(;n>0;n--)
{
fscanf(fp,"%d",&temp);
for(i=0;i=temp;i++);
if(i>=n)
printf("ThiselementCANNOTbefound!
");
//若要删除元素不是位于顺序表最后一位,则将后面的元素前移一位;若位于最后一位,直接令n--即可,不必再移动
elseif(ifor(j=i;ja[j]=a[j+1];
else;
}
//打印清空后的顺序表
for(i=0;iprintf("%d\t",a[i]);
finish=clock();
duration=(double)(finish-start)/CLOCKS_PER_SEC;
printf("\nThesortedlinearlisthasbeencleared!
\n");
printf("Thelengthofitis%d.\n",n);
printf("Timetaken:
%fs\n",duration);
fclose(fp);
exit
(1);
}
运行结果:
实验二:
(此图将原程序中for(;n>0;n--)改成了for(;n>20;n--),即删除至剩20个数据的线性表,目的为验证删除一些元素后线性表仍保持有序)
实验三:
1.N=100
t1=0.005000st2=0.001000s
2.N=400
t1=0.049000st2=0.001000s
实验四:
源代码:
/*
实验4:
编写一个程序,用插入排序依次将1中产生的1000个随机整数链接成有序链表
不改变原随机数在存储空间中的顺序。
*/
#include
#include
#defineN1000
intmain()
{
FILE*fp;
inta[N][2];
intH,i,k,x;
if((fp=fopen("D:
\\data.txt","r"))==NULL)
{
fprintf(stderr,"Erroropeningfile.");
exit(0);
}
//定义头节点位置
H=0;
fscanf(fp,"%d",&x);
a[0][0]=x;
//定义链表结束标志
a[0][1]=-1;
//逐一插入元素并与原链表内元素比较以确定位置
for(k=1;k{
fscanf(fp,"%d",&x);
a[k][0]=x;
//在链表头结点插入元素
if(a[k][0]{
a[k][1]=H;
H=k;
}
//在链表某一位置插入一个元素
else
{
i=H;
while((a[i][1]!
=-1)&&(a[a[i][1]][0]i=a[i][1];
a[k][1]=a[i][1];
a[i][1]=k;
}
}
printf("Alinkedlistcontaining%dnumbershasbeencreated!
\n",N);
printf("Itsheadpointeris%d,itsvalueis%d.\n",H,a[H][0]);
printf("Thedataisasfollows.\n\n");
i=H;
//按大小顺序打印链表
do
{
printf("%d\t",a[i][0]);
i=a[i][1];
}while(a[i][1]!
=-1);
exit
(1);
}
运行结果:
【结论】(结果)
1.实验1中利用函数递归的方法得到随机数的方法是可行的,要得到(0,a)之间的随机数只需加xi=INT(a*yi/m)语句即可。
2.实验2中利用插入排序法可以成功将一组无序数据按从小到大顺序排好并放入线性表中,利用顺序查找法可以成功找到、删除任意元素。
第四个结果图说明删除一些元素后线性表顺序保持不变
3.实验3中N=100时插入时间t1=0.005000s,清空时间t2=0.001000s;N=400时插入时间t1=0.049000s,清空时间t2=0.001000s。
当表中已经有n个数时,再插入一个数时,若比较i次,则需要移动i次(1<=i<=n)。
假设他们的概率相等,则平均需要比较(n+1)/2次,移动(n+1)/2次。
即顺序表中已经有n个数的时候,再进行插入排序运算的算法复杂度为O(n)。
那么假设题目要求一共读取N个数,则程序平均要执行(N+1)*N/2,即算法的时间复杂度为O(n^2)。
同理,删除这N个数的算法的时间复杂度也为O(n^2)。
在此程序中N=400时插入时间约为N=100时的10倍,基本符合,误差是由于运行时电脑环境及计时误差引起的
4.实验4中用二维数组模拟静态链表成功实现了数据的插入及排序功能
【小结】
在完成这份实验报告后,感慨良多。
在实验四中,要求是用二维数组模拟静态链表,数组第一维用来存放数据,第二维用来存放指向下一个数据的记号,在本实验中是下一个数据的位置。
而参考报告中则是创建了一个struct类型的动态链表,与实验要求有所出入。
因此我认真分析题目给出的示例算法,一步步思考判断条件与循环等问题,遇到想不明白的条件时就画一个二维数组并将具体数据放入再进行分析或上网查找相关内容。
最终,亲自完成四个实验的代码编写、调试及注释说明后,我掌握了很多知识点。
实验1有文件的创建、数据写入、随机数创建;实验2有数据读取、插入排序、顺序查找、有序表删除;实验3有程序运行时间的获得方法,数据量对运行时间的影响;实验4有用二维数组模拟静态链表、链表的插入排序。
如果只是参考了别人的实验报告而不加以思考分析,这些知识点绝对不可能熟练掌握,实验课也就失去了存在的意义。
在今后的实验课中,我一定会认真对待每一个实验,看懂实验说明和参考算法,在此基础上亲自编写程序并调试直到成功运行,课后认真完成实验报告的撰写。
也只有这样才能学到知识,掌握编程思想,才能有所收获。
纸上得来终觉浅,绝知此事要躬行!
指导教师评语及成绩:
成绩:
指导教师签名:
批阅日期: