数据结构课程设计报告各种排序实现及对比.docx

上传人:b****5 文档编号:8208416 上传时间:2023-01-29 格式:DOCX 页数:25 大小:74.87KB
下载 相关 举报
数据结构课程设计报告各种排序实现及对比.docx_第1页
第1页 / 共25页
数据结构课程设计报告各种排序实现及对比.docx_第2页
第2页 / 共25页
数据结构课程设计报告各种排序实现及对比.docx_第3页
第3页 / 共25页
数据结构课程设计报告各种排序实现及对比.docx_第4页
第4页 / 共25页
数据结构课程设计报告各种排序实现及对比.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

数据结构课程设计报告各种排序实现及对比.docx

《数据结构课程设计报告各种排序实现及对比.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告各种排序实现及对比.docx(25页珍藏版)》请在冰豆网上搜索。

数据结构课程设计报告各种排序实现及对比.docx

数据结构课程设计报告各种排序实现及对比

数据结构课程设计报告

 

设计题目:

学生姓名:

系别:

专业:

班级:

学号:

指导教师:

2010年版

 

目录

一、设计题目……………………………………………………4

二、运行环境(软、硬件环境)………………………………4

三、算法设计的思想……………………………………………4

3.1简单选择排序………………………………………………4

3.2直接插入排序……………………………………………….4

3.3希尔排序……………………………………………………4

3.4冒泡排序……………………………………………………4

3.5快速排序……………………………………………………4

四、算法的流程图……………………………………………….5

4.1主函数的算法流程图………………………………………...5.

4.2简单选择排序的算法流程图………………………………….6

4.3直接插入排序的算法流程图………………………………….7

4.4希尔排序的算法流程图………………………………………8

4.5冒泡排序的算法流程图………………………………………9

4.6快速排序的算法流程图

(1)………………………………..10

4.7快速排序的算法流程图

(2)………………………………..11

五、算法设计分析………………………………………………11

5.1简单选择排序………………………………………………11

5.2直接插入排序……………………………………………….12

5.3希尔排序……………………………………………………12

5.4冒泡排序……………………………………………………13

5.5快速排序……………………………………………………13

六、源代码………………………………………………………14

七、运行结果分析………………………………………………23

八、收获及体会…………………………………………………26

一、

设计题目

各种排序

二、运行环境(软、硬件环境)

软件环境:

操作系统的名称windows、版本号XP;

程序开发的环境:

MicrosoftVisualC++6.0

硬件环境:

内存:

512M,硬盘:

80G

三、算法设计的思想

3.1简单选择排序

     <1> 基本思想

每一趟在n-i+1(i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列的第i个关键字。

3.2插入排序

    <1> 基本思想

插入排序的思想就是读一个,排一个,将第1个数放入数组的第1个元素中,以后读入的数与已存入数组的数进行比较,确定它在从大到小的排列中应处的位置.将该位置以及以后的元素向后推移一个位置,将读入的新数填入空出的位置中.

3.3希尔排序

  <1> 基本思想

      希尔排序法是1959年由D.L.Shell提出来的,又称减少增量的排序。

下表是以八个元素排序示范的例子.在该例中,开始时相隔4个成分,分别按组进行排序,这时每组2个成分,共4组; 然后相隔2个成分,在按组排序......最后,对所有相邻成分进行排序.

3.4冒泡排序

   <1> 基本思想

      依次比较相邻的两个数,把大的放前面,小的放后面.即首先比较第1个数和第2个数,大数放前,小数放后.然后比较第2个数和第3个数......直到比较最后两个数.第一趟结束,最小的一定沉到最后.重复上过程,仍从第1个数开始,到最后第2个数.然后......  由于在排序过程中总是大数往前,小数往后,相当气泡上升,所以叫冒泡排序.

3.5快速排序

  <1> 基本思想

      快速排序的基本思想是基于分治策略的。

对于输入的子序列L[p..r],如果规模足够小则直接进行排序,否则分三步处理:

     分解(Divide):

将输入的序列L[p..r]划分成两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。

     递归求解(Conquer):

通过递归调用快速排序算法分别对L[p..q]和L[q+1..r]进行排序。

  合并(Merge):

由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序。

   

四、算法的流程图

4.1主函数的算法流程图

开始

 

输入数据个数length

 

create(),

visit()

 

输入select

7

select

6

5

4

3

2

1

0

select_sort(L);Zhijie(L);ShellSort(L,dlta,4);Maopao(L);QuickSort(L);print(num);

select_sort(L);

QuickSort(L);

Maopao(L);

ShellSort()

Zhijie(L)

Exit(0)

 

输入y/n

n

y

结束

4.2简单选择排序的算法流程图

开始

inti=1;

i

intj=i;

k=i+1

k

L.r[j].key

j=k;

k++

i!

=j

L.r[i]L.r[j]

i++

结束

4.3直接插入排序的算法流程图

开始

i=2

i<=L.length

L.r[i].key

L.r[0]=L.r[i];

L.r[i]=L.r[i-1];

j=i-2;

L.r[0].key

L.r[j+1]=L.r[j];

--j;

L.r[j+1]=L.r[0]

++i

结束

4.4希尔排序的算法流程图

开始

k=0

k

ShellInsert(&L,dlta[k],&r);

i=dk+1;

i<=L.length

L.r[i].key

L.r[0]=L.r[i];

j=i-dk;

j>0&&L.r[0].key

L.r[j+dk]=L.r[j];

j-=dk;

L.r[j+dk]=L.r[0]

++i

++k

结束

4.5冒泡排序的算法流程图

开始

inti=1;

i

intj=1;

j

L.r[j].key

L.r[j]

L.r[j+1]

j++

结束

i++

4.6快速排序的算法流程图

(1)

开始

Low

--high

++low

Low

&&L.r[high].key<=pivotkey

77

L.r[low]=L.r[high]

Low

&&L.r[high].key>=pivotkey

77

L.r[0]=L.r[low]

Pivotkey=L.r[low].key

L.r[high]=L.r[low]

结束

L,low,high

 

4.7快速排序的算法流程图

(2)

开始

Low

L,low=pivotloc+1,high=high

Pivotloc=partioion(L,low,high),low=low,

high=pivotloc-1;

Low

L,low,high

Pivotloc=partioion(L,low,high),low=low,

high=pivotloc-1;

QSort(L,low,pivotloc-1)

结束

五、算法设计分析

5.1简单选择排序

操作方法:

第一趟,从n个记录中找出关键码最小的记录与第一个记录交换;第二趟,从第二个记录开始的n-1个记录中再选出关键码最小的记录与第二个记录交换;如此,第i趟,则从第i个记录开始的n-i+1个记录中选出关键码最小的记录与第i个记录交换,直到整个序列按关键码有序。

【效率分析】

空间效率:

仅用了一个辅助单元。

时间效率:

简单选择排序中,所需进行记录移动的操作次数较小,其最小值为0,最大值为3(n-1)。

然而,无论记录的初始排列如何,所需进行的关键字之间的比较次数相同,均为n(n-1)/2。

因此,总的时间复杂度也是O(n2)。

5.2直接插入排序

设有n个记录,存放在数组r中,重新安排记录在数组中的存放顺序,使得按关键码有序。

即r[1].key≤r[2].key≤……≤r[n].key

先来看看向有序表中插入一个记录的方法:

设1<j≤n,r[1].key≤r[2].key≤……≤r[j-1].key,将r[j]插入,重新安排存放顺序,使得r[1].key≤r[2].key≤……≤r[j].key,得到新的有序表,记录数增1。

【效率分析】

空间效率:

仅用了一个辅助单元。

时间效率:

向有序表中逐个插入记录的操作,进行了n-1趟,每趟操作分为比较关键码和移动记录,而比较的次数和移动记录的次数取决于待排序列按关键码的初始排列。

最好情况下:

即待排序列已按关键码有序,每趟操作只需1次比较2次移动。

总比较次数=n-1次

总移动次数=2(n-1)次

最坏情况下:

即第j趟操作,插入记录需要同前面的j个记录进行j次关键码比较,移动记录的次数为j+2次。

平均情况下:

即第j趟操作,插入记录大约同前面的j/2个记录进行关键码比较,移动记录的次数为j/2+2次。

由此,直接插入排序的时间复杂度为O(n2)。

是一个稳定的排序方法

5.3希尔排序(Shell’sSort)

直接插入排序算法简单,在n值较小时,效率比较高,在n值很大时,若序列按关键码基本有序,效率依然较高,其时间效率可提高到O(n)。

希尔排序即是从这两点出发,给出插入排序的改进方法。

希尔排序方法:

1.选择一个步长序列t1,t2,…,tk,其中ti>tj,tk=1;

2.按步长序列个数k,对序列进行k趟排序;

3.每趟排序,根据对应的步长ti,将待排序列分割成若干长度为m的子序列,分别对各子表进行直接插入排序。

仅步长因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。

希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于步长因子序列的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。

目前还没有人给出选取最好的步长因子序列的方法。

步长因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:

步长因子中除1外没有公因子,且最后一个步长因子必须为1。

希尔排序方法是一个不稳定的排序方法。

5.4冒泡排序

冒泡排序方法:

对n个记录的表,第一趟冒泡得到一个关键码最大的记录r[n],第二趟冒泡对n-1个记录的表,再得到一个关键码最大的记录r[n-1],如此重复,直到n个记录按关键码有序的表。

【效率分析】

空间效率:

仅用了一个辅助单元。

时间效率:

总共要进行n-1趟冒泡,对j个记录的表进行一趟冒泡需要j-1次关键码比较。

移动次数:

最好情况下:

待排序列已有序,不需移动。

5.5快速排序

快速排序是通过比较关键码、交换记录,以某个记录为界(该记录称为支点),将待排序列分成两部分。

其中,一部分所有记录的关键码大于等于支点记录的关键码,另一部分所有记录的关键码小于支点记录的关键码。

我们将待排序列按关键码以支点记录分成两部分的过程,称为一次划分。

对各部分不断划分,直到整个序列按关键码有序。

【效率分析】

空间效率:

快速排序是递归的,每层递归调用时的指针和参数均要用栈来存放,递归调用层次数与上述二叉树的深度一致。

因而,存储开销在理想情况下为O(log2n),即树的高度;在最坏情况下,即二叉树是一个单链,为O(n)。

时间效率:

在n个记录的待排序列中,一次划分需要约n次关键码比较,时效为O(n),若设T(n)为对n个记录的待排序列进行快速排序所需时间。

理想情况下:

每次划分,正好将分成两个等长的子序列,则

T(n)≤cn+2T(n/2)c是一个常数

≤cn+2(cn/2+2T(n/4))=2cn+4T(n/4)

≤2cn+4(cn/4+T(n/8))=3cn+8T(n/8)

······

≤cnlog2n+nT

(1)=O(nlog2n)

最坏情况下:

即每次划分,只得到一个子序列,时效为O(n2)。

快速排序是通常被认为在同数量级(O(nlog2n))的排序方法中平均性能最好的。

但若初始序列按关键码有序或基本有序时,快排序反而蜕化为冒泡排序。

为改进之,通常以“三者取中法”来选取支点记录,即将排序区间的两个端点与中点三个记录关键码居中的调整为支点记录。

快速排序是一个不稳定的排序方法。

排序方法

最好时间

平均时间

最坏时间

稳定性

插入排序

直接插入排序

O(n)

O(n2)

O(n2)

稳定

希尔排序

O(n1.5)

不稳定

交换排序

冒泡排序

O(n)

O(n2)

O(n2)

稳定

快速排序

O(nlogn)

O(nlogn)

O(n2)

不稳定

选择排序

直接选择排序

O(n2)

O(n2)

O(n2)

不稳定

内部排序各种算法的性能比较(表)

六、源代码

#include"stdlib.h"

#include"stdio.h"

#include"time.h"

#defineMAXSIZE200

typedefintKeyType;

typedefstruct//定义存储记录关键字及其他信息的结构体

{KeyTypekey;

charother;

}RedType;

typedefstruct//定义存储所有记录的结构体

{RedTyper[MAXSIZE+1];

intlength;

}SqList;

typedefstruct{

intmove;/*记录数据移动次数*/

intcomp;/*记录数据比较次数*/

}Recode;

intdlta[5]={31,15,7,3,1};//初始化希尔排序的增量序列

intnum[10]={0};//记录每个排序方法的移动次数和比较次数

intflag=0;//标记变量

//利用产生的随即数模拟用户输入的数据

voidcreate(SqList*L,intlength)

{inti;

srand(time(0));

L->length=length;

for(i=1;i<=L->length;i++)

{

L->r[i].key=rand()%1000;

L->r[i].other=rand()%26+65;

}

}

/*输出元素*/

voidvisit(SqListL)

{inti;

printf("\n");

for(i=1;i<=L.length;i++)

printf("%4d%2c",L.r[i].key,L.r[i].other);

printf("\n");

}

/*简单选择排序*/

voidselect_sort(SqListL)

{Recoder;

p=0;

r.move=0;

inti,j,k;

RedTypet;

for(i=1;i

{j=i;

for(k=i+1;k<=L.length;k++)

{p++;

if(L.r[j].key>L.r[k].key)

{

j=k;

}

}

if(i!

=j)

{

t=L.r[j];

L.r[j]=L.r[i];

L.r[i]=t;

r.move=r.move+3;

}

}

if(!

flag)

{printf("本次随机数据排序的移动次数为:

");

printf("%d\n",r.move);

printf("本次随机数据排序的比较次数为:

");

printf("%d\n",p);

printf("简单选择排序后的结果:

");

visit(L);

}

else{num[0]=r.move;num[1]=p;}

}

//直接插入排序

voidZhijie(SqListL)

{Recoder;

p=0;

r.move=0;

intj;

for(inti=2;i<=L.length;++i)

{p++;

if(L.r[i].key

{

L.r[0]=L.r[i];//复制为哨兵

L.r[i]=L.r[i-1];

r.move=r.move+2;

for(j=i-2;L.r[0].key

{

L.r[j+1]=L.r[j];//记录后移

r.move++;

p++;

}

L.r[j+1]=L.r[0];//插入到正确位置

r.move++;

}

}

if(!

flag)

{

printf("本次随机数据排序的移动次数为:

");

printf("%d\n",r.move);

printf("本次随机数据排序的比较次数为:

");

printf("%d\n",p);

printf("直接插入排序后的结果:

");

visit(L);

}

else{num[2]=r.move;num[3]=p;}

}

//希尔排序

voidShellInsert(SqList*L,intdk,Recode*r)

{inti,j;

for(i=dk+1;i<=L->length;++i)

{r->comp++;

if(L->r[i].keyr[i-1].key)

{L->r[0]=L->r[i];//暂存

r->move++;

for(j=i-dk;j>0&&(L->r[0].keyr[j].key);j-=dk)

{L->r[j+dk]=L->r[j];//记录后移

r->move++;

r->comp++;

}

L->r[j+dk]=L->r[0];//插入到正确位置

r->move++;

}

}

}

voidShellSort(SqListL,intdlta[],intt)

{//按增量序列dlta[0..t-1]对顺序表L作希尔排序。

Recoder;

p=0;

r.move=0;

intk;

for(k=0;k

ShellInsert(&L,dlta[k],&r);//一趟增量为dlta[k]的插入排序

if(!

flag)

{printf("本次随机数据排序的移动次数为:

");

printf("%d\n",r.move);

printf("本次随机数据排序的比较次数为:

");

printf("%d\n",p);

printf("希尔排序后的结果:

");

visit(L);

}

else{num[4]=r.move;num[5]=p;}

}

//冒泡排序法

voidMaopao(SqListL)

{Recoder;

p=0;

r.move=0;

inti,j;

RedTypet;

for(i=1;i

for(j=1;j<=L.length-i;j++)

{p++;

if(L.r[j].key>L.r[j+1].key)

{r.move=r.move+3;

t=L.r[j];

L.r[j]=L.r[j+1];

L.r[j+1]=t;

}

}

if(!

flag)

{

printf("本次随机数据排序的移动次数为:

");

printf("%d\n",r.move);

printf("本次随机数据排序的比较次数为:

");

printf("%d\n",p);

printf("冒泡排序后的结果:

");

visit(L);

}

else{num[6]=r.move;num[7]=p;}

}

//快速排序法

intPartition(SqList*L,intlow,inthigh,Recode*r)

{

intpivotkey;

L->r[0]=L->r[low];//用子表的第一个记录作枢轴记录

pivotkey=L->r[low].key;//枢轴记录关键字

r->move=r->move+2;

while(low

{

while(lowr[high].key>=pivotkey){--high;r->comp++;}

L->r[low]=L->r[high];//将比枢轴记录小的记录移到低端

while(lowr[low].key<=pivotkey){++low;r->comp++;}

L->r[high]=L->r[low];//将比枢轴记录大的记录移到高端

r->move=r->move+2;

}

L->r[low]=L->r[0];//枢轴记录到位

r->move++;

returnlow;//返回枢轴位置

}

voidQSort(SqList*L,intlow,inthigh,Recode*r)

{intpivotloc;

if(low

{pivotloc=Partition(L,low,high,r);//将L->r[low..high]一分为二

QSort(L,low,pivotloc-1,r);/对低子表递归排序,pivotloc是枢轴位置

QSort(L,pivotloc+1,high,r);//对高子表递归排序

}

}

voidQuickSort(SqListL)

{Recoder;

p=0;

r.move=0;

QSort(&L,1,L.length,&r);

if(!

flag)

{printf("本次随机数据排序的移动次数为:

");

printf("%d\n",r.move);

printf("本次

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1