《数据结构》内部排序12种算法上机实验报告word文档良心出品.docx
《《数据结构》内部排序12种算法上机实验报告word文档良心出品.docx》由会员分享,可在线阅读,更多相关《《数据结构》内部排序12种算法上机实验报告word文档良心出品.docx(19页珍藏版)》请在冰豆网上搜索。
![《数据结构》内部排序12种算法上机实验报告word文档良心出品.docx](https://file1.bdocx.com/fileroot1/2023-1/4/5fc90ab9-4fd7-4568-bf6f-4bd52a3657e9/5fc90ab9-4fd7-4568-bf6f-4bd52a3657e91.gif)
《数据结构》内部排序12种算法上机实验报告word文档良心出品
成都信息工程学院计算机系
课
程
实
验
报
告
实验课程:
数据结构
实验项目:
实现算法的全排序
指导教师:
学生姓名:
学生学号:
班级:
计算机工程1班
实验地点:
6305
实验时间:
2012年12月2日—12月19日
实验成绩:
评阅老师:
(说明:
实验报告必须包含下面的每项内容,根据实验情况认真填写,封面必须打印或复印(A4纸),书写上机实验报告内容的纸张也用A4纸,最后从侧面装订)
一【上机实验目的】
目的:
从键盘输入一组数,通过内部排序的12种算法对这组数字进行排序。
熟练掌握刚刚学过的内部排序的算法,并对这12种排序算法的时间复杂度进行比较,根据不同的情况,选择合适的算法
二【实验环境】
PC机每人1台
三【上机实验内容】
实现内部排序的12种排序算法的全排序。
四【上机调试程序流程图】(注:
可打印)
(用传统流程图的形式表示)
五【上机调试中出现的错误信息、错误原因及解决办法】
(记录下你调试程序中出现的错误信息的英文提示,分析出错原因及可能的解决办法)
六【上机调试后的源程序及还存在的问题】(注:
源程序可打印)
(同时记录下你对你编写此程序的其它具体想法,)
主要的程序:
/********************************直接插入排序***************************/
voidInsertSort(SqList&L)
{//直接插入排序
inti,j;
for(i=2;i<=L.length;++i)
{
if(L.r[i].key<=L.r[i-1].key)
{
L.r[0]=L.r[i];
L.r[i]=L.r[i-1];
for(j=i-2;(L.r[0].keyL.r[j+1]=L.r[j];
L.r[j+1]=L.r[0];
}
}
}
/*********************************折半插入排序************************/
voidBinsertSort(SqList&L)
{//折半插入排序
inti,j,low,high,m;
for(i=2;i<=L.length;i++)
{
L.r[0]=L.r[i];
low=1;
high=i-1;
while(low<=high)
{
m=(low+high)/2;
if(L.r[0].keyhigh=m-1;
else
low=m+1;
}
for(j=i-1;j>=high+1;--j)
L.r[j+1]=L.r[j];
L.r[high+1]=L.r[0];
}
}
/**********************************2-路插入排序***********************/
voidP2_InsertSort(SqList&L)
{//2—路插入排序
inti,j,first,final;
RedType*d;
d=(RedType*)malloc(L.length*sizeof(RedType));//生成L.length个记录的临时空间
d[0]=L.r[1];
first=final=0;//first、final分别指示d中排好序的记录的第1个和最后1个记录的位置
for(i=2;i<=L.length;++i)
{//依次将L的第2个~最后1个记录插入d中
if(L.r[i].key{//待插记录小于d中最小值,插到d[first]之前(不需移动d数组的元素)
first=(first-1+L.length)%L.length;//设d为循环向量
d[first]=L.r[i];
}
elseif(L.r[i].key>d[final].key)
{//待插记录大于d中最大值,插到d[final]之后(不需移动d数组的元素)
final=final+1;
d[final]=L.r[i];
}
else
{//待插记录大于d中最小值,小于d中最大值,插到d的中间(需要移动d数组的元素)
j=final++;//移动d的尾部元素以便按序插入记录
while(L.r[i].key{
d[(j+1)%L.length]=d[j];
j=(j-1+L.length)%L.length;
}
d[j+1]=L.r[i];
}
}
for(i=1;i<=L.length;i++)//把d赋给L.r
L.r[i]=d[(i+first-1)%L.length];//线性关系
}
/***************************************希尔排序***************************/
voidShellInsert(SqList&L,intdk)
{
//printf("OK");
inti,j;
for(i=dk+1;i<=L.length;i++)
if(L.r[i].key{
L.r[0]=L.r[i];
for(j=i-dk;j>0&&(L.r[0].keyL.r[j+dk]=L.r[j];
L.r[j+dk]=L.r[0];
}
}
voidShellSort(SqList&L,intdlta[],intt)
{
//printf("OK");
intk;
for(k=0;kShellInsert(L,dlta[k]);
//display(L);
}
/***********************************表插入排序***********************/
voidTableInsert(SLinkListType&SL,RedTypeD[]){
//由数组D建立的n个元素的表插入排序的静态链表SL
inti,p,q;
SL.r[0].rc.key=INT_MAX;//表头结点记录的关键字取得最大整数(非降序表的表尾)
SL.r[0].next=0;//next域为0表示表尾(现为空表,初始化)
for(i=0;iSL.r[i+1].rc=D[i];//将数组D的值赋给静态链表SL
q=0;
p=SL.r[0].next;
while(SL.r[p].rc.key<=SL.r[i+1].rc.key){//静态链表后移
q=p;
p=SL.r[p].next;
}
SL.r[i+1].next=p;
SL.r[q].next=i+1;//将当前记录插入到静态链表
}
SL.length=MAXSIZE;
}
voidArrange(SLinkListType&SL)
{
//根据静态链表SL中各结点的指针值调整记录位置,使得SL中记录按关键字非递减有序排列
inti,p,q;
SLNodet;
p=SL.r[0].next;//p指示第一个记录的当前位置
printf("%d",SL.length);
for(i=1;i{
//SL.r[i...i-1]中记录已按关键字有序排列,第i个记录在SL中的当前记录不应小于i
while(p
p=SL.r[p].next;//找到第i个记录,并用p指示其在SL中当前位置
q=SL.r[p].next;//q指示当前未调整的表尾
if(p!
=i){
t=SL.r[p];//交换记录,使第i个记录到位
SL.r[p]=SL.r[i];
SL.r[i]=t;
SL.r[i].next=p;//指向被移走的记录,使得以后可由while循环找回
}
p=q;//p指示未调整的表尾,为找到第i+1个记录作准备
//print(SL);
//printf("\n");
}
}
/*************************************冒泡排序***********************/
voidbubble_sort(SqList&L)
{//冒泡排序
inti;
intk;
RedTypetem;
for(i=L.length-1,k=1;i>=1&&k;--i)
{
k=0;
for(intj=1;j<=i;++j)
{
if(L.r[j].key>L.r[j+1].key)
{
tem=L.r[j];
L.r[j]=L.r[j+1];
L.r[j+1]=tem;
k=1;
}
}
}
}
/************************************快速排序**************************/
intPartition(SqList&L,intlow,inthigh)
{//快速排序递归函数的实现
intpivotkey;
L.r[0]=L.r[low];
pivotkey=L.r[low].key;
while(low{
while(low=pivotkey)
--high;
L.r[low]=L.r[high];
while(low++low;
L.r[high]=L.r[low];
}
L.r[low]=L.r[0];
returnlow;
}
/********************************简单选择排序***********************/
intSelectMinKey(SqList&L,inti)
{
intj,k=i;
for(j=i+1;j{
if(L.r[k].key>L.r[j].key)
k=j;
}
returnk;
}
voidSelect_Sort(SqList&L)
{
inti,j;
RedTypetem;
for(i=1;i{
j=SelectMinKey(L,i);
if(i!
=j)
{
tem=L.r[i];
L.r[i]=L.r[j];
L.r[j]=tem;
}
}
}
/**************************************堆排序*************************/
voidHeapAdjust(HeadType&L,ints,intm)
{//对生成的堆进行排序,生成大顶堆
RedTyperc;
rc=L.r[s];
intj;
for(j=2*s;j<=m;j*=2)
{
if(jj++;
if(rc.key>=L.r[j].key)
break;
L.r[s]=L.r[j];
s=j;
}
L.r[s]=rc;
}
voidHeadSort(HeadType&L)
{//对一组无序的数字进行排序生成堆
inti;
RedTypetemp;
for(i=L.length/2;i>0;--i)
HeapAdjust(L,i,L.length);
for(i=L.length;i>1;--i)
{
temp=L.r[1];
L.r[1]=L.r[i];
L.r[i]=temp;
HeapAdjust(L,1,i-1);
}
}
/**************************************归并排序***************************/
voidMerge(RedTypeSR[],RedTypeTR[],ints,intm,intt)
{//printf("+_+_+_+_+_+_");
inti,j,k;
//RcdType*tem;
for(j=m+1,k=s,i=s;i<=m&&j<=t;k++)
{
if(SR[i].keyTR[k]=SR[i++];
else
TR[k]=SR[j++];
}
while(i<=m)
{
//for(l=0;lTR[k++]=SR[i++];
}
while(j<=t)
{
//for(l=0;lTR[k++]=SR[j++];
}
}
voidMSort(RedTypeSR[],RedTypeTR1[],ints,intt)
{
intm;
RedTypeTR2[MAXSIZE+1];
if(s==t)
TR1[s]=SR[s];
else
{
m=(s+t)/2;
MSort(SR,TR2,s,m);
MSort(SR,TR2,m+1,t);
Merge(TR2,TR1,s,m,t);
}
}
voidMergeSort(SqList&L)
{
MSort(L.r,L.r,1,L.length);
}
/************************************基数排序*************************/
oidInitList(SLList&L,RedTypeD[],intn)//初始化静态链表L(把数组D中的数据存于L中)
{
charc[MAX_NUM_OF_KEY],c1[MAX_NUM_OF_KEY];
inti,j,max=D[0].key;//max为关键字的最大值
for(i=1;iif(maxmax=D[i].key;
L.keynum=int(ceil(log10(max)));
L.recnum=n;
for(i=1;i<=n;i++)
{
L.r[i].otheritems=D[i-1].otherinfo;
itoa(D[i-1].key,c,10);//将10进制整型转化为字符型,存入c
for(j=strlen(c);j{
strcpy(c1,"0");
strcat(c1,c);
strcpy(c,c1);
}
for(j=0;j}
}
voidDistribute(SLCellr[],inti,ArrTypef,ArrTypee)//算法10.15
{//静态键表L的r域中记录已按(keys[0],…,keys[i-1])有序。
本算法按
//第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的keys[i]相同。
//f[0..RADIX-1]和e[0..RADIX-1]分别指向各子表中第一个和最后一个记录
intj,p;
for(j=0;jfor(p=r[0].next;p;p=r[p].next)
{
j=r[p].keys[i]-'0';//将记录中第i个关键字映射到[0..RADIX-1]
if(!
f[j])
f[j]=p;
else
r[e[j]].next=p;
e[j]=p;//将p所指的结点插入第j个子表中
}
}
voidCollect(SLCellr[],ArrTypef,ArrTypee)//算法10.16
//本算法按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成
//一个链表,e[0..RADIX-1]为各子表的尾指针。
{intj,t;
for(j=0;!
f[j];j=++j);//找第一个非空子表
r[0].next=f[j];
t=e[j];//r[0].next指向第一个非空子表中第一个结点
while(j{for(j=++j;jf[j];j=++j);//找下一个非空子表
if(f[j])//链接两个非空子表
{r[t].next=f[j];
t=e[j];
}
}
r[t].next=0;//t指向最后一个非空子表中的最后一个结点
}
voidprintl(SLListL)//按链表输出静态链表
{inti=L.r[0].next,j;
while(i)
{for(j=L.keynum-1;j>=0;j--)printf("%c",L.r[i].keys[j]);
printf("");
i=L.r[i].next;
}
}
voidRadixSort(SLList&L)//算法10.17
//L是采用静态链表表示的顺序表。
对L作基数排序,使得L成为按关键字
//自小到大的有序静态链表,L.r[0]为头结点。
{inti;
ArrTypef,e;
for(i=0;iL.r[L.recnum].next=0;//将L改造为静态链表
for(i=0;i{Distribute(L.r,i,f,e);//第i趟分配
Collect(L.r,f,e);//第i趟收集
printf("第%d趟收集后:
\n",i+1);
printl(L);
printf("\n");
}
}
voidprint(SLListL)//按数组序号输出静态链表
{inti,j;
printf("keynum=%drecnum=%d\n",L.keynum,L.recnum);
for(i=1;i<=L.recnum;i++)
{printf("keys=");
for(j=L.keynum-1;j>=0;j--)printf("%c",L.r[i].keys[j]);
printf("otheritems=%dnext=%d\n",L.r[i].otheritems,L.r[i].next);
}
}
voidSort(SLListL,intadr[])//改此句(类型)
//求得adr[1..L.length],adr[i]为静态链表L的第i个最小记录的序号
{inti=1,p=L.r[0].next;
while(p)
{adr[i++]=p;
p=L.r[p].next;
}
}
voidRearrange(SLList&L,intadr[])//改此句(类型)
//adr给出静态链表L的有序次序,即L.r[adr[i]]是第i小的记录。
//本算法按adr重排L.r,使其有序。
算法10.18(L的类型有变)
{inti,j,k;
for(i=1;iif(adr[i]!
=i)
{j=i;
L.r[0]=L.r[i];//暂存记录L.r[i]
while(adr[j]!
=i)//调整L.r[adr[j]]的记录到位直到adr[j]=i为止
{k=adr[j];
L.r[j]=L.r[k];
adr[j]=j;
j=k;//记录按序到位
}
L.r[j]=L.r[0];
adr[j]=j;
}
}
运行效果图:
七【上机实验中的其他它问题及心得】
(在上机实验中遇到的你不能解决的其它问题,简单描述一下你此次上机的收获及感想)
心得:
排序时计算机程序设计中的一种重要的操作,因为我们无论做什么样的程序都会涉及到排序算法,在第十章的内部排序算法中,基本上都是一些经典的排序算法,这是我选择这个题目的主要原因,因为通过这个综合设计,我可以了解不同的排序算法,根据不同的情况,选择更好的算法。
在本章中共有12种算法:
插入排序5种,选择排序3种,快速排序2种,归并排序和基数排序。
在没有接触本章之前,我们只是接触了简单的冒泡排序和选择排序,这些只是对数n不是很大的情况,当n值很大时,我们果继续使用这些简单的算法,时间复杂度会很大的。
因此,在本章中介绍的这些算法,适合我们遇到的任何情况,不能够说那种算法是好的,不同的算法都有好坏,我们可以根据不同的情况,从这些算法中选择合适的算法。
每一种排序都有最好的情况和最坏的情况。
1.从平均时间性能而言,快速排序是最好的,因为其所用的时间是最少的。
但是,如果想到最坏的情况,当然就要考虑到堆排序和归并排序。
堆排序对n值较大时是比较有效的,因为堆排序主要的耗时是在建初始堆和调整建新堆时进行的反复的“筛选”。
当n值很大时,归并排序所需时间较堆排序省,但是归并排序所需要的辅助空间较多。
入过在输入一行数字是,这些数字是基本有序的,为了节省时间和空间,可以选择冒泡排序和简单选择排序。
从方法的稳定性来说:
基数排序时稳定的内部排序算法,所有时间复杂度为O(n^2)的简单排序法也是稳定的,但是,快速排序、堆排序和希尔排序等时间较好的排序方法都是不稳定的。
一般来说,排序过程中的“比较“是在“相邻两个关键字”间进行的排序方法是稳定的。
因此,在所有的算法当中,没有哪一种算法是绝对最优的。
有的适用于n较大时,有的