排序技术综合应用Word文档格式.docx
《排序技术综合应用Word文档格式.docx》由会员分享,可在线阅读,更多相关《排序技术综合应用Word文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
r[0]=r[i];
//暂存被插入记录
for(j=i-d;
j>
0&
&
r[0]<
r[j];
j=j-d)
r[j+d]=r[j];
//记录后移d个位置
r[j+d]=r[0];
}
}
voidQuickSort(intr[],intfirst,intend)
if(first<
end){//递归结束
pivot=Partition(r,first,end);
//一次划分
QuickSort(r,first,pivot-1);
//递归地对左侧子序列进行快速排序
QuickSort(r,pivot+1,end);
//递归地对右侧子序列进行快速排序
intPartition(intr[],intfirst,intend)
i=first;
j=end;
//初始化
while(i<
j)
while(i<
j&
r[i]<
=r[j])j--;
//右侧扫描
if(i<
j){
r[i]←→r[j];
//将较小记录交换到前面
i++;
=r[j])i++;
//左侧扫描
if(i<
j){
r[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<
iostream>
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<
<
"
请输入数据:
endl;
for(i;
i++)
{
cout<
请输入第个"
i<
个整数"
请输入字符:
cin>
>
L.r[i].ch;
输入的数据如下:
L.r[i].key;
L.len++;
//输出数据
voidoutputsqlist(sqlistL)
=L.len;
i++)
数据:
字符="
L.r[i].ch<
#"
数="
L.r[i].key<
//希尔排序
voidshellinsert(sqlist&
L,intd);
//对顺序表L进行一次希尔插入排序
voidshellsort(sqlist&
L)
intd=L.len/2;
while(d!
=0)
shellinsert(L,d);
d=d/2;
L,intd)
inti=d+1;
++i)
if(L.r[i].key<
L.r[i-d].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].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<
high)//从区间两端交替地向中间扫描
while((low<
high)&
(L.r[high].key>
=pivokey))
--high;
//从左向右扫描
L.r[low]=L.r[high];
//比枢轴小的记录移到左端
(L.r[low].key<
=pivokey))
++low;
//从右向左扫描
L.r[high]=L.r[low];
//比枢轴记录大的移到右端
L.r[low]=L.r[0];
//枢轴记录到位
returnlow;
//返回枢轴位置
voidmain()
sqlistL;
intn;
请输入顺序表的长度(大于0):
cin>
n;
creatsqlist(L,n);
排序前输出数据:
outputsqlist(L);
shellsort(L);
排序后输出数据:
voidqsort(sqlist&
L,intlow,inthigh);
//顺序表L的子序列L.r[low..high]进行快速排序
//交换顺序表L的子序列L.r[low..high]的记录
voidquiksort(sqlist&
qsort(L,1,L.len);
//排序整个文件记录
if(low<
high)
intpivotpos=partition(L,low,high);
//pivotpos曲轴位置
qsort(L,low,pivotpos-1);
//对左区间递归排序
qsort(L,pivotpos+1,high);
//对右区间递归排序
测试用例
实验总结
通过这次的实验,我掌握了几种常用的排序方法,并掌握用高级语言实现排序算法的方法;
深刻理解排序的定义和各种排序方法的特点,并能加以灵活应用;
了解各种方法的排序过程及其依据的原则,并掌握各种排序方法的时间复杂度的分析方法。
通过这次的实验,我认识到仅仅掌握课本上的知识是不够的,在实际操作时,常常遇到一些问题,自己看不懂,更无法解决。
要经过不断的思考,尝试着去更改代码中出现的问题。
虽然开始很困难,但在同学的帮助下,我逐渐的熟悉了许多操作,为后继工作的顺利进行做了准备。
个人的力量是薄弱的,在过程中和同学相互讨论,不断进步。
也许,我们可以说,编一个程仅仅是开始,调试和运行相比之下更难。
实践中收获的远比想象的多。