插入排序的设计与实现.docx
《插入排序的设计与实现.docx》由会员分享,可在线阅读,更多相关《插入排序的设计与实现.docx(11页珍藏版)》请在冰豆网上搜索。
插入排序的设计与实现
题目:
插入排序的设计与实现
初始条件:
理论:
学习了《数据结构》课程,掌握了基本的数据结构和常用的算法;
实践:
计算机技术系实验室提供计算机及软件开发环境。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
1系统应具备的功能:
(1)从键盘上输入五个学生的考研成绩;
(2)实现直接插入排序、二分插入排序、对各科成绩,以及平均成绩从小到大排序;
(3)比较各种插入排序的优劣。
2数据结构设计;
3主要算法设计;
4编程及上机实现;
5撰写课程设计报告,包括:
(1)设计题目;
(2)摘要和关键字;
(3)正文,包括引言、需求分析、数据结构设计、算法设计、程序实现及测试、结果分析、设计体会等;
(4)结束语;
(5)参考文献。
时间安排:
2007年7月2日-7日(第18周)
7月2日查阅资料
7月3日系统设计,数据结构设计,算法设计
7月4日-5日编程并上机调试
7月6日撰写报告
7月7日验收程序,提交设计报告书。
指导教师签名:
2007年7月2日
系主任(或责任教师)签名:
2007年7月2日
插入排序的设计与实现
摘要:
近几年以来,考研的人数越来越多,有n个人的成绩出来了,想大致了解一下学生的水平,对于出来的成绩进行排序,分别对数学、外语、政治、专业的成绩进行从小到大的排序,以及他们的平均成绩进行排序。
并以五个人为例,用插入排序实现,其中,成绩由外部输入。
关键字:
排序,输入,插入
0.引言
我所写的程序是用的直接插入和折半排序,对所输入的成绩进行排序,共有四门成绩,一共有五个人,然后对平均成绩和各门成绩进行排序,按非递增的顺序输出。
1.需求分析
近几年以来,考研的人数越来越多,有n个人的成绩出来了,想大致了解一下学生的水平,不可能通过人工的去对学生的成绩进行排序。
对于出来的成绩进行排序,分别对数学,外语,政治,专业的成绩进行从小到大的排序,以及他们的平均成绩进行排序。
数据的外部输入,数据的任意性,以及只需大概的了解数据的一些特性。
2.数据结构设计
以下是三个存储结构,各自特点如下:
/*建一个结构体*/
Structstudent
{floatmat;/*存放数学成绩*/
floateng;/*存放英语成绩*/
floatpol;/*存放政治成绩*/
floatpro;/*存放专业成绩*/
};
structStudentstudent[5];/*建立一个结构体类型的数组,用来存放输入的信息*/
纪录类型结构:
typedefstructRecordType
{
intkey;
chardata[];
}RecordType;
#defineMAXSIZEN
顺序表结构:
typedefstructSqList{
RecordTyper[MAXSIZE+1];
intlength;
}SqList;
在设计的过程中,根据插入排序的特点,我认为第一个存储结构的效率更有效,记录类型是一样的,都是用数组存放。
3.算法设计
3.1直接插入排序算法
voidInsert(floatr[],intn)/*建立直接插入排序算法*/
{inti,j;
n=n-1;
for(i=2;i<=n;++i)
if(r[i]{r[0]=r[i];//复制为哨兵
r[i]=r[i-1];
for(j=i-2;r[0]r[j+1]=r[j];//记录后移
r[j+1]=r[0];//插入到正确的位置
}
}
3.2二分查找排序算法
VoidBInsert(Aqlist&L){
//对顺序表L作二分插入排序
For(i=2;i<=L.length;++i){
L.r[0]=L.r[i];//将L.r[n]暂存到L.r[0]
Low=1;high=i-1;
While(low<=high){
//在r[low.high]中折半查找有序插入的位置
m=(low+high)/2;//折半
if(LT(L.r[0].key,L.r[m].key))high=m-1;//插入点在底半区
elselow=m+1;//插入点在高半区
}//while
For(j=i-1;j>=high+1;--j)L.r[j+1]=L.r[j];//记录后移
L.r[high+1]=L.r[0];//插入
}//for}//BInsertSort
折半插入排序所需要附加存储空间和直接插入排序相同,从时间上比较,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变.因此,插入排序的时间复杂度仍为O(n2).
直接插入排序(StraightInsertionSort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的,记录数增1的有序表。
例如,已知待排序的一组记录的初始排列如下所示:
{R(38),R(49),R965},R(97),R(76),R(13),R(27),R(49)…}(10-4)
假设在排序的过程中,前四个记录已按关键字递增的次序重新
排列,构成一个含四个记录的有序序列
{R(38),R(49),R(65),R(97)}(10-5)
现要将式(10-4)中第五个(即关键字为76的)记录插入上述序列以得到一个新的含五个记录的有序序列,则首先要在式(10-5)的序列中进行查找以确定R(76)所应插入的位置,然后进行插入。
假设从R(97)起向左进行顺序查找,由于65〈76〈97,则R(76)应插入在R(65)和R(97)之间,从而得到下列新的有序序列{R(38),R(49),R(65),R(76),R(97)}(10-6)
称从式(10-5)到式(10-6)的过程为一趟直接插入排序。
一般情况下,第i趟直接插入排序的操作为:
在含有i-1个记录的有序子序列r[1..i-1];并且,和顺序查找类似,为了在查找插入位置的过程中避免数组下标出界,在r[0]处设置监视哨。
在自i-1起往前搜索的过程中,可以同时后移记录。
整个排序过程为进行n-1趟插入,即:
先将序列中的第1个记录看成是一个有序的子序列,然后从第2个记录起逐个进行插入,直至整个序列变成按关键字非递减有序序列为止。
从上面的叙述可见,直接插入排序的算法简洁,容易实现,那么它的效率如何呢?
从空间来看,它只需要一个记录的辅助空间,从时间来看,排序的基本操作为:
比较两个关键字的大小和移动记录。
先分析一趟插入排序的情况。
算法中里层的for循环的次数取决于待插记录的关键字与前i-1个记录的关键字之间的关系。
若L.r[i].key则在整个排序过程(进行n-1趟插入排序)中,当待排序序列中记录按关键字非递减有序排列(以下称之为“正序”)时,所需要进行关键字比较的次数达最小值n-1,记录不需移动;反之,当待排序列中记录按关键字非递增有序排列时,总的比较次数达最大植(n+2)(n-1J)/2,记录移动的次数也达最大植(n+4)(n-1)/2.若待排序记录是随机的,即待排序列中的记录可能出现的各种排列的概率相同,则我们可取上述最小值和最大值的平均值,作为直接插入排序的所需进行关键字间的比较次数和移动记录的次数,约为n2/4.由此,直接插入排序的时间复杂度为0(n2).
在下面我所编的程序中,我用的是直接插入排序和二分插入排序
4.程序实现
4.1程序源代码
#include"stdio.h"
#include"string.h"
voidBInsert(floatr[],intn)
{intlow,high;
inti,j,m;
n=n-1;/*对数组作二分插入排序*/
for(i=2;i<=n;++i)
{
r[0]=r[i];/*将r[n]暂存到r[0]*/
low=1;high=i-1;
while(low<=high)
{/*在r[low.high]中折半查找有序插入的位置*/
m=(low+high)/2;/*折半*/
if(r[0]elselow=m+1;/*插入点在高半区*/
}/*endwhile*/
for(j=i-1;j>=high+1;--j)r[j+1]=r[j];/*记录后移*/
r[high+1]=r[0];/*插入*/
}
}
voidInsert(floatr[],intn)/*建立直接插入排序算法*/
{inti,j;
n=n-1;
for(i=2;i<=n;++i)
if(r[i]{r[0]=r[i];
r[i]=r[i-1];
for(j=i-2;r[0]r[j+1]=r[j];
r[j+1]=r[0];
}
}
intmain()/*建立主函数*/
{voidBInsert(floatr[],intn);
voidInsert(floatr[],intn);
structStudent/*建立一个结构体类型*/
{floatmat;
floateng;
floatpol;
floatpro;
};
structStudentstudent[5];
inta1;
inti,t;
floata[6],b[6],c[6],d[6];
floataver[6];
printf("Input五个学生的数学成绩,以逗号隔开,0到100之间:
\n");/*输入五个学生的考研数学成绩*/
scanf("%f,%f,%f,%f,%f",&student[0].mat,&student[1].mat,
&student[2].mat,&student[3].mat,&student[4].mat);
for(a1=1;a1<=5;a1++)
a[a1]=student[a1-1].mat;
for(i=1;i<=5;i++)
if(a[i]<0||a[i]>100)
return0;
printf("Input五个学生的英语成绩:
\n");
scanf("%f,%f,%f,%f,%f",&student[0].eng,&student[1].eng,
&student[2].eng,&student[3].eng,&student[4].eng);
for(a1=1;a1<=5;a1++)
b[a1]=student[a1-1].eng;
for(i=1;i<=5;i++)
if(b[i]<0||b[i]>100)
return0;
printf("Input五个学生的政治成绩:
\n");
scanf("%f,%f,%f,%f,%f",&student[0].pol,&student[1].pol,
&student[2].pol,&student[3].pol,&student[4].pol);
for(a1=1;a1<=5;a1++)
c[a1]=student[a1-1].pol;
for(i=1;i<=5;i++)
if(c[i]<0||c[i]>100)
return0;
printf("Input五个学生的专业成绩:
\n");
scanf("%f,%f,%f,%f,%f",&student[0].pro,&student[1].pro,
&student[2].pro,&student[3].pro,&student[4].pro);
for(a1=1;a1<=5;a1++)
d[a1]=student[a1-1].pro;
for(i=1;i<=5;i++)
if(d[i]<0||d[i]>100)
return0;
for(i=1;i<=5;i++)
aver[i]=(a[i]+b[i]+c[i]+d[i])/4;
Insert(a,6);Insert(b,6);Insert(c,6);/*对各科成绩进行排序*/
BInsert(d,6);Insert(aver,6);
printf("output排序后的数学成绩:
\n");
for(t=5;t>=1;t--)/*逆顺序输出,得到从小到大的顺序*/
printf("%3.2f",a[t]);
printf("\n");
printf("output排序后的英语成绩:
\n");
for(t=5;t>=1;t--)
printf("%3.2f",b[t]);
printf("\n");
printf("output排序后的政治成绩:
\n");
for(t=5;t>=1;t--)
printf("%3.2f",c[t]);
printf("\n");
printf("output排序后的专业成绩:
\n");
for(t=5;t>=1;t--)
printf("%3.2f",d[t]);
printf("\n");
printf("output排序后的平均成绩:
\n");
for(t=5;t>=1;t--)
printf("%3.2f",aver[t]);
}
4.2程序运行主界面
5.设计体会
作为一个计算机专业的学生,编程是我们的基本能力,但是,通过这次的实践,发现自己的编程能力的确是太差劲了,一些语法的错误,犯的很多,对程序的改进和分析的能力也较差,很多错误都是同学帮忙,才被解决了的。
不过,同过这次的设计,了解到,算法在整个程序中的重要性,好的算法,能够节省很多的时间,为计算机节省空间,再次,我通过各种途径,把以前学过的语言,复习了一遍,对它们有了进一步的了解。
通过网上查询,找到了一些很好的程序,发现编的的确是很有水平。
以后可以借鉴,编程不是一朝一夕的事情,需要我们多多的练习。
6.结束语
通过这次的课程设计,对课程上的一些算法有了进一步的了解,由于水平有限,有些要求完成的不是很理想,但是一些算法却是用上去了。
参考文献
[1]严蔚敏,吴伟名.《数据结构》,清华大学出版社,2001年7月
[2]谭浩强.<>,清华大学出版社,2004年6月
[3]谭浩强.<>,清华大学出版社,1999年12月