内部排序算法比较课程设计报告7种基本排序Word格式.docx
- 文档编号:8178919
- 上传时间:2023-05-10
- 格式:DOCX
- 页数:21
- 大小:21.86KB
内部排序算法比较课程设计报告7种基本排序Word格式.docx
《内部排序算法比较课程设计报告7种基本排序Word格式.docx》由会员分享,可在线阅读,更多相关《内部排序算法比较课程设计报告7种基本排序Word格式.docx(21页珍藏版)》请在冰点文库上搜索。
d为0时表不打乱,d越大,打乱程度越高。
RecallList()
恢复最后一次用RandomizeList随机大乱的可排序表。
ListLength()
返回可排序的长度。
ListEmpty()
若可排序表为空表,则返回True,否则返回False。
BubbleSort(&
c,&
s)
进行冒泡排序,返回关键字比较次数c和移动次数s。
InsertSort(&
进行插入排序,返回关键字比较次数c和移动次数s。
SelectSort(&
进行选择排序,返回关键字比较次数c和移动次数s。
QuickSort(&
进行快速排序,返回关键字比较次数c和移动次数s。
ShellSort(&
进行希尔排序,返回关键字比较次数c和移动次数s。
HeapSort(&
进行堆排序,返回关键字比较次数c和移动次数s。
ListTraveres(visit())
依次对L中的每个元素调用函数visit()。
}ADTOrderableList
二.概要设计:
1.冒泡排序:
冒泡排序的基本概念是:
依次比较相邻的两个数,将小数放在前面,大数放在后面。
即在第一趟:
首先比较第1个和第2个数,将小数放前,大数放后。
然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。
至此第一趟结束,将最大的数放到了最后。
在第二趟:
仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。
如此下去,重复以上过程,直至最终完成排序。
2.直接插入排序:
直接插入排序是一种最简单的排序方法,它的基本操作是将一个记录插入到已牌号序的有序表中,从而得到一个新的、记录数增1的有序表。
3.简单选择排序:
在要排序的一组数中,选出最小的一个数与第一个位置的数交换;
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环。
4.希尔排序:
希尔排序又称“缩小增量排序”,它也是一种属插入排序类的方法,但在时间效率上较前述集中排序方法有较大的改进。
它的基本思想是:
先将整个待排序记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
5.堆排序:
由二叉堆的定义可知,堆顶元素(即二叉堆的根节点)一定为堆中的最大值或最小值,因此如果我们输出堆顶元素后,将剩余的元素再调整为二叉堆,继而再次输出堆顶元素,再将剩余的元素调整为二叉堆,反复执行该过程,这样便可输出一个有序序列,这个过程我们就叫做堆排序。
6.归并排序:
归并的含义很明显就是将两个或者两个以上的有序表组合成一个新的有序表。
归并排序中一般所用到的是2-路归并排序,即将含有n个元素的序列看成是n个有序的子序列,每个子序列的长度为1,而后两两合并,得到n/2个长度为2或1的有序子序列,再进行两两合并。
。
直到最后由两个有序的子序列合并成为一个长度为n的有序序列。
2-路归并的核心操作是将一维数组中前后相邻的两个有序序列归并为一个有序序列。
7.快速排序:
快速排序的基本实现思想就是将当前待排序列分成两个部分、一个值。
一个值:
就是选定出一个值作为被比较的元素。
两个部分:
所有比该被选定元素大的部分都去该元素的右边,所有比被选定元素小的部分都去该元素的左边。
这样我们就确定了该元素在这个待排序列中的位置,其实也就是我们已经将这个元素“排好了”。
3、详细设计和编码
voidgensort(intb[],intn)
{
inti,j;
ints=0,t=0;
for(i=0;
i<
n-1;
i++)
for(j=i+1;
j<
n;
j++)
t++;
if(b[i]>
b[j])
inttemp=b[i];
b[i]=b[j];
b[j]=temp;
s+=3;
}}}
cout<
<
"
移动次数="
s<
"
比较次数="
t<
endl;
}
voidinsertsort(sqlistb,intn)
for(i=2;
b[0]=b[i];
s++;
j=i-1;
while(b[0].key<
b[j].key)
b[j+1]=b[j];
j--;
b[j+1]=b[0];
voidgentsort(intb[],intn)
inti,j,k;
k=i;
if(b[k]>
{k=j;
if(k!
=i)
{inttemp=b[k];
b[k]=b[i];
b[i]=temp;
}}
voidshellsort(sqlistb,intn)
inti,j,gap;
recx;
gap=n/2;
while(gap>
0)
for(i=gap+1;
j=i-gap;
while(j>
if(b[j].key>
b[j+gap].key)
x=b[j];
b[j]=b[j+gap];
b[j+gap]=x;
j=j-gap;
elsej=0;
gap=gap/2;
voidsift(sqlistr,ints,intm)
intj;
x=r[s];
for(j=2*s;
=m;
j*=2)
{q++;
if(j<
m&
&
(r[j].key<
r[j+1].key))
++j;
q++;
if(!
(x.key<
r[j].key))break;
r[s]=r[j];
s=j;
p++;
r[s]=x;
voidheapsort(sqlist&
r,intm)
inti;
recw;
for(i=m/2;
i>
0;
--i)
sift(r,i,m);
for(i=m;
1;
w=r[i];
r[i]=r[1];
r[1]=w;
p+=3;
sift(r,1,i-1);
voidsorting(sqlist&
r,intt)
BeforeSort();
heapsort(r,t);
display(p,q);
voidinit(inta[]){//随机生成N个整数并
srand((unsignedint)time(NULL));
N;
a[i]=rand()%99+1;
#include<
stdio.h>
voidcutTwo(intsourceArr[],int*tempArr[],intstart,intend);
voidmerge(intsourceArr[],int*tempArr[],intstart,intmid,intend);
intmain(intargc,char*argv[])
inta[8]={
50,10,20,30,70,40,80,60
};
int*b[8]={
cutTwo(a,b,0,8);
8;
i++){
printf("
%d"
a[i]);
return0;
/*
归并排序算法:
*/
voidmerge(intsourceArr[],int*tempArr[],intstart,intmid,intend){
//当前我们有一个源数组,我们在比较时将这个源数组一分为二进行比较归并排序
因为我们要进行归并排序,所以我们需要两个指针分别指向两个子序列的开始位置,即start指向左边部分的开始位置,
mid+1指向右边部分的开始位置,我们还需要一个k的下标,用于存储我们交换过来的数组到临时数组tempArr[]
inti=start;
//定义一个i下标,用于表示左边部分开始的位置下标
intj=mid+1;
//定义一个j下标,用于表示右边部分开始的位置下标
intk=0;
因为我们在比较时是不断的比较,直到一个子序列到达最后,所以我们应该用while循环来做,结束条件:
无非就是左边序列到头了
或者是右边序列到头了,即:
=mid&
=end只有在这两个条件都成立的条件下说明两个子序列都没有到头
while(i<
=end){//当i=mid+1或者j=end+1时说明子序列中有一个到头了,则跳出循环
if(sourceArr[i]<
=sourceArr[j]){//表示当前i比较小,那么我们就将小的值赋给k
tempArr[k]=sourceArr[i];
k=k+1;
i=i+1;
else{
tempArr[k]=sourceArr[j];
j=j+1;
不能将k,i,j的加1操作放在ifelse判断的外面,因为我们在进行比较的时候,只是将下标所指的数字小的放在左边,将下标所指的数字
大的不动,因为我们小的下标加1后还要和刚才下标所指的数字再次进行比较,如果放在外面,那么我们的比较的对象不对了(
因为的大的数字的下标加1了,前面的一个数字没有进行比较)
当有一个子序列到头以后,我们就要将剩余没到头的子序列的剩余元素放到k的右边,因为剩余的肯定是已经有序的,且肯定比已经
到头的子序列的全部元素都要大的。
while(j<
=end){//i==mid+1&
因为左边序列i跳出循环的条件肯定是当前i=mid+1了,则我们移动右边j的子序列就好了
k++;
j++;
=mid){//&
j==end+1则此时表示当前跳出循环的是j右边的子序列,则我们移动左边的i的子序列
i++;
intm;
for(m=0;
m<
k;
m++){
sourceArr[start+m]=tempArr[m];
上述操作完成仅仅是完成了对一个大的序列中一部分的排列,因为我们的做法是对整个的序列进行二分,二分之后对子序列进行归并排序
voidcutTwo(intsourceArr[],int*tempArr[],intstart,intend){
if(start<
end){
intmid;
//设置一个取中间的变量
mid=(start+end)/2;
cutTwo(sourceArr,tempArr,start,mid);
cutTwo(sourceArr,tempArr,mid+1,end);
merge(sourceArr,tempArr,start,mid,end);
voidoutput(sqlistb,intn)//输出元素值
for(inti=0;
setw(4)<
b[i].key;
voiddisplay(intn,intm)//输出计数
n<
voidBeforeSort()//初始化计数器
p=0;
q=0;
voidquicksort(sqlistr,ints,intt)
inti=s,j=t;
if(s<
t)
r[0]=r[s];
j)
j&
r[j].key>
=r[0].key)
r[i]=r[j];
r[i].key<
r[j]=r[i];
r[i]=r[0];
elsereturn;
quicksort(r,s,j-1);
quicksort(r,j+1,t);
voidsort(sqlistr,ints,intt)
quicksort(r,s,t);
4、上机调试过程
编程过程中出现了各种各样的错误,如输错代码,未定义变量,数组下标越界,产生随机数据的程序不工作等等,导致编译没能通过没有结果.最后和组员讨论,又请教一些同学,终于把所有问题都解决掉,运行出了结果.
5、测试结果及其分析
下图是自动产生的五组随机产生的100个数据的排序结果,由图可知希尔排序、快速排序的关键字移动次数和比较次数都相对较少。
起泡排序、选择排序中关键字比较次数很大,起泡排序、插入排序移动次数很大。
这样方便我们快捷的看出排序优缺点。
图1
图2
图3
图4
图5
6、用户使用说明
内部排序算法比较用户使用说明
本系统采用VisualC++语言编写,运用软件工程的思想,采用面向对象分析、设计的方法学完成。
本程序主要用于人们比较排序算法,从直观感受各种排序的优缺点。
7、参考文献
[1]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:
清华大学出版社,1997.04
[2]严蔚敏,吴伟民.数据结构题集(C语言版)[M].北京:
[3]汪杰等,数据结构经典算法实现与习题解答[M].北京:
人民邮电出版社,2004
[4]陈媛,何波,涂晓红等,算法与数据结构[M].北京:
清华大学出版社,2005
[5]李春葆.数据结构习题与解析(第二版)[M].北京:
清华大学出版社,2004.07
8、附录
iostream.h>
iomanip.h>
stdlib.h>
time.h>
#defineN100
intp,q;
//起泡排序
//插入排序
typedefintKeyType;
structrec
KeyTypekey;
typedefrecsqlist[N];
//希尔排序
//选择排序
//快速排序
//堆排序
voidmain()
inta1[N],i;
inte=N;
sqlista,b,c,d;
intc1[N];
intlow=0,high=10;
init(a1);
c1[i]=a1[i];
a[i].key=a1[i];
b[i].key=a1[i];
c[i].key=a1[i];
d[i].key=a1[i];
排序前数组:
\n"
;
a1[i];
起泡排序运行结果:
gensort(a1,sizeof(a1)/sizeof(int));
插入排序运行结果:
insertsort(a,N);
希尔排序运行结果:
shellsort(b,N);
选择排序运行结果:
gentsort(c1,N);
快速排序运行结果:
sort(c,low,high);
堆排序运行结果:
sorting(d,N);
排序后数组:
cin.get();
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 内部 排序 算法 比较 课程设计 报告 基本