排序技术综合应用.docx
《排序技术综合应用.docx》由会员分享,可在线阅读,更多相关《排序技术综合应用.docx(17页珍藏版)》请在冰豆网上搜索。
排序技术综合应用
《算法与数据结构》实验报告
(一)实验题目:
排序技术综合应用
1、实验目的:
(1)熟练掌握常用的排序方法,并掌握用高级语言实现排序算法的方法;
(2)深刻理解排序的定义和各种排序方法的特点,并能加以灵活应用;
(3)了解各种方法的排序过程及其依据的原则,并掌握各种排序方法的时间复杂度的分析方法。
2、实验内容:
对希尔排序、快速排序、归并排序任意选择两种排序方法进行比较。
任意选择希尔排序、快速排序、归并排序中两种排序方法,对任意给定一组数据:
单增、单减、乱码等,对它们进行比较分析。
3、实验说明:
希尔排序算法如下:
voidShellSort(intr[],intn)
{
for(d=n/2;d>=1;d=d/2)//以增量为d进行直接插入排序
{
for(i=d+1;i<=n;i++)
{
r[0]=r[i];//暂存被插入记录
for(j=i-d;j>0&&r[0]r[j+d]=r[j];//记录后移d个位置
r[j+d]=r[0];
}
}
}
voidQuickSort(intr[],intfirst,intend)
{
if(firstpivot=Partition(r,first,end);//一次划分
QuickSort(r,first,pivot-1);//递归地对左侧子序列进行快速排序
QuickSort(r,pivot+1,end);//递归地对右侧子序列进行快速排序
}
}
intPartition(intr[],intfirst,intend)
{
i=first;j=end;//初始化
while(i{
while(iif(ir[i]←→r[j];//将较小记录交换到前面
i++;
}
while(iif(ir[j]←→r[i];//将较大记录交换到后面
j--;
}
}
retutni;//i为轴值记录的最终位置
}
快速排序算法如下:
voidQuickSort(intr[],intfirst,intend)
{
if(firstpivot=Partition(r,first,end);//一次划分
QuickSort(r,first,pivot-1);//递归地对左侧子序列进行快速排序
QuickSort(r,pivot+1,end);//递归地对右侧子序列进行快速排序
}
}
intPartition(intr[],intfirst,intend)
{
i=first;j=end;//初始化
while(i{
while(iif(ir[i]←→r[j];//将较小记录交换到前面
i++;
}
while(iif(ir[j]←→r[i];//将较大记录交换到后面
j--;
}
}
retutni;//i为轴值记录的最终位置
}
设计分析:
希尔排序
输入:
数组名称(也就是数组首地址)、数组中元素个数
算法思想简单描述:
在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,并对插入下一个数没有提供任何帮助。
如果比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。
D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。
算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。
当增量减到1时,整个要排序的数被分成一组,排序完成。
下面的函数是一个希尔排序算法的一个实现,初次取序列的一半为增量,以后每次减半,直到增量为1。
希尔排序是不稳定的。
快速排序
输入:
数组名称(也就是数组首地址)、数组中起止元素的下标
算法思想简单描述:
快速排序是对冒泡排序的一种本质改进。
它的基本思想是通过一趟
扫描后,使得排序序列的长度能大幅度地减少。
在冒泡排序中,一次
扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只
减少1。
快速排序通过一趟扫描,就能确保某个数(以它为基准点吧)
的左边各数都比它小,右边各数都比它大。
然后又用同样的方法处理
它左右两边的数,直到基准点的左右只有一个元素为止。
它是由
C.A.R.Hoare于1962年提出的。
显然快速排序可以用递归实现,当然也可以用栈化解递归实现。
下面的函数是用递归实现的,有兴趣的朋友可以改成非递归的。
快速排序是不稳定的。
最理想情况算法时间复杂度O(nlog2n),最坏O(n^2)--[n的平方]
源程序代码:
希尔排序
#include
usingnamespacestd;
#defineMax20
typedefintkeytype;
structretype{
keytypekey;
charch;
};
structsqlist{
retyper[Max+1];
intlen;
};
//初始化数据
voidcreatsqlist(sqlist&L,intn)
{
inti=1;
L.len=0;
if(n>Max||n<0)
exit(0);
cout<<"请输入数据:
"<for(i;i<=n;i++)
{
cout<<"请输入第个"<
cout<<"请输入字符:
"<cin>>L.r[i].ch;
cout<<"输入的数据如下:
"<cin>>L.r[i].key;
L.len++;
}
}
//输出数据
voidoutputsqlist(sqlistL)
{
inti=1;
for(i;i<=L.len;i++)
{
cout<<"数据:
"<
cout<<"字符="<}
}
//希尔排序
voidshellinsert(sqlist&L,intd);//对顺序表L进行一次希尔插入排序
voidshellsort(sqlist&L)
{
intd=L.len/2;
while(d!
=0)
{
shellinsert(L,d);
d=d/2;
}
}
voidshellinsert(sqlist&L,intd)
{
inti=d+1;
for(i;i<=L.len;++i)
{
if(L.r[i].key{
L.r[0]=L.r[i];
//L.r[0].ch=L.r[i].ch;
//L.r[0].key=L.r[i].key;
intj=i-d;
for(j;(j>0)&&(L.r[0].key{
L.r[j+d]=L.r[j];
//L.r[j+d].ch=L.r[j].ch;
//L.r[j+d].key=L.r[j].key;
}
L.r[j+d]=L.r[0];
//L.r[j+d].ch=L.r[0].ch;
//L.r[j+d].key=L.r[0].key;
}
}
}
intpartition(sqlist&L,intlow,inthigh)
{
L.r[0]=L.r[low];//用区间第low个记录作枢轴记录
keytypepivokey=L.r[low].key;//取枢轴记录关键字
while(low{
while((low=pivokey))
--high;//从左向右扫描
L.r[low]=L.r[high];//比枢轴小的记录移到左端
while((low++low;//从右向左扫描
L.r[high]=L.r[low];//比枢轴记录大的移到右端
}
L.r[low]=L.r[0];//枢轴记录到位
returnlow;//返回枢轴位置
}
voidmain()
{
sqlistL;
intn;
cout<<"请输入顺序表的长度(大于0):
"<cin>>n;
creatsqlist(L,n);
cout<<"排序前输出数据:
"<outputsqlist(L);
shellsort(L);
cout<<"排序后输出数据:
"<outputsqlist(L);
}
快速排序
#include
usingnamespacestd;
#defineMax20
typedefintkeytype;
structretype{
keytypekey;
charch;
};
structsqlist{
retyper[Max+1];
intlen;
};
//初始化数据
voidcreatsqlist(sqlist&L,intn)
{
inti=1;
L.len=0;
if(n>Max||n<0)
exit(0);
cout<<"请输入数据:
"<for(i;i<=n;i++)
{
cout<<"请输入第个"<
cout<<"请输入字符:
"<cin>>L.r[i].ch;
cout<<"输入的数据如下:
"<cin>>L.r[i].key;
L.len++;
}
}
//输出数据
voidoutputsqlist(sqlistL)
{
inti=1;
for(i;i<=L.len;i++)
{
cout<<"数据:
"<
cout<<"字符="<}
}
voidqsort(sqlist&L,intlow,inthigh);//顺序表L的子序列L.r[low..high]进行快速排序
intpartition(sqlist&L,intlow,inthigh);//交换顺序表L的子序列L.r[low..high]的记录
voidquiksort(sqlist&L)
{
qsort(L,1,L.len);//排序整个文件记录
}
voidqsort(sqlist&L,intlow,inthigh)
{
if(low{
intpivotpos=partition(L,low,high);//pivotpos曲轴位置
qsort(L,low,pivotpos-1);//对左区间递归排序
qsort(L,pivotpos+1,high);//对右区间递归排序
}
}
intpartition(sqlist&L,intlow,inthigh)
{
L.r[0]=L.r[low];//用区间第low个记录作枢轴记录
keytypepivokey=L.r[low].key;//取枢轴记录关键字
while(low{
while((low=pivokey))
--high;//从左向右扫描
L.r[low]=L.r[high];//比枢轴小的记录移到左端
while((low++low;//从右向左扫描
L.r[high]=L.r[low];//比枢轴记录大的移到右端
}
L.r[low]=L.r[0];//枢轴记录到位
returnlow;//返回枢轴位置
}
voidmain()
{
sqlistL;
intn;
cout<<"请输入顺序表的长度(大于0):
"<cin>>n;
creatsqlist(L,n);
cout<<"排序前输出数据:
"<outputsqlist(L);
cout<<"排序后输出数据:
"<outputsqlist(L);
}
测试用例
希尔排序
快速排序
实验总结
通过这次的实验,我掌握了几种常用的排序方法,并掌握用高级语言实现排序算法的方法;深刻理解排序的定义和各种排序方法的特点,并能加以灵活应用;了解各种方法的排序过程及其依据的原则,并掌握各种排序方法的时间复杂度的分析方法。
通过这次的实验,我认识到仅仅掌握课本上的知识是不够的,在实际操作时,常常遇到一些问题,自己看不懂,更无法解决。
要经过不断的思考,尝试着去更改代码中出现的问题。
虽然开始很困难,但在同学的帮助下,我逐渐的熟悉了许多操作,为后继工作的顺利进行做了准备。
个人的力量是薄弱的,在过程中和同学相互讨论,不断进步。
也许,我们可以说,编一个程仅仅是开始,调试和运行相比之下更难。
实践中收获的远比想象的多。