数据结构课程设计资料讲解.docx

上传人:b****5 文档编号:11796463 上传时间:2023-04-02 格式:DOCX 页数:29 大小:49.33KB
下载 相关 举报
数据结构课程设计资料讲解.docx_第1页
第1页 / 共29页
数据结构课程设计资料讲解.docx_第2页
第2页 / 共29页
数据结构课程设计资料讲解.docx_第3页
第3页 / 共29页
数据结构课程设计资料讲解.docx_第4页
第4页 / 共29页
数据结构课程设计资料讲解.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

数据结构课程设计资料讲解.docx

《数据结构课程设计资料讲解.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计资料讲解.docx(29页珍藏版)》请在冰豆网上搜索。

数据结构课程设计资料讲解.docx

数据结构课程设计资料讲解

 

数据结构课程设计

 

课程设计说明书

 

课程名称:

数据结构和算法

设计题目:

多种排序

院系:

计算机科学与信息工程学院

学生姓名:

学号:

专业班级:

计科嵌入式(12-1)

指导教师:

 

年月日

课程设计任务书

设计题目

表达式计算程序设计

学生姓名

所在院系

计科

专业、年级、班

12计科(嵌入式)

设计要求:

1)采用如下七种方法实现上述问题求解:

插入排序、希尔排序、起泡排序、快速排序、选择排序、堆排序、归并排序。

2)统计每一种排序方法的性能(以上机运行程序所花费的时间为准进行对比),找出其中两种较快的方法。

并将数据序列和不同的查找算法的性能结果记录入txt文件。

学生应完成的工作:

1.利用随机函数产生N个随机整数(10000以上)。

2.对这些数字进行排序。

3.采用插入、希尔、起泡、快速、选择、归并、堆排序方法解决问题。

4.对不同的排序算法进行性能比较并记录。

参考文献阅读:

1.《数据结构(C语言版)》严蔚敏清华大学出版社

2.《C语言程序设计》丁峻岭中国铁道出版社

3.《C程序设计》谭浩强清华大学出版社

工作计划:

任务下达日期:

年月日

任务完成日期:

年月日

指导教师(签名):

学生(签名):

 

多种排序

 

摘要:

排序是算法中最基础的问题之一,经典的排序算法是前人不断总结得到的,基于比较的方法是比较直观的方式,主要存在插入法排序、堆排序、希尔排序、归并排序、快速排序,每一种排序算法都有自己的优缺点,比如插入法排序适用于那些长度短的排序,要是长的话,有些爱莫能助啦,堆排序主要是依据了二叉堆的特性,但是创建堆的过程也是一个复杂的问题,希尔排序的过程是一个不断精确的过程,但是目前也只是一个经验方式。

归并排序是一个递归的问题,采用分治的思想实现,但是这种算法需要额外的存储空间,快速排序虽然是实践中比较常用的算法,但是对于有序的数组采用快速排序就是灾难。

比较型算法的时间复杂度最优也只能到达O(NlogN)。

 

关键词:

归并排序快排排序选择排序冒泡排序

插入排序堆排序希尔排序内部排序

 

1.设计背景

1.1问题描述

利用随机函数产生N个随机整数(10000以上),对这些数进行多种方法进行排序。

包括:

插入排序、希尔排序、起泡排序、快速排序、选择排序、堆排序、归并排序。

1.2问题分析

经典的排序算法是前人不断总结得到的,基于比较的方法是比较直观的方式,主要存在插入法排序、堆排序、希尔排序、归并排序、快速排序,每一种排序算法都有自己的优缺点。

2.设计方案

2.1算法设计

(1)选择排序

在待排序的一组数据元素中,选出最小的一个数据元素与第一个位置的数据元素交换;然后在剩下的数据元素当中再找最小的与第二个位置的数据元素交换,循环到只剩下最后一个数据元素为止。

(2)冒泡排序

相邻的两个元素进行比较,将小的调到前面,大的调到后面。

(3)插入排序

待排序的记录放在数组R[0„n-1]中排序过程中某一时刻,R被划分成两个子区间R[0,i-1](有序和)R[i„n-1](无序)。

直接插入的基本操作是将当前无序区的一个记录R[i]插入到有序区R[0„i-1]中适当的位置

(4)快速排序

在待排序的数组的n个元素中取一个元素(一般取第一个),将其移动到这样的位置:

在其之前的元素的值都小于它,在其之后的元素都大于它,这样是一趟快速排序;然后对数组的两个部分进行同样的操作,直到每部分只有一个记录为止;总之,每趟使表的第一个元素放在适当位置,将表两分,再对两子表进行同样的递归划分,直至划分的子表长度为1。

(5)堆排序

堆排序中heap算法的时间复杂度与堆所对应的完全二叉树的树高度log2n相关。

而heapsort中对heap的调用数量级为n,所以堆排序的整个时间复杂度为O(nlog2n)。

并且堆排序是不稳定的。

堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

(6)归并排序

将两个或两个以上的有序表组成一个新的有序表。

(7)希尔排序

将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,对各个子序列进行插入排序;然后再选择一个更小的增量,再将数组分割为多个子序列进行排序......最后选择增量为1,即使用直接插入排序,使最终数组成为有序。

增量的选择:

在每趟的排序过程都有一个增量,至少满足一个规则增量关系d[1]>d[2]>d[3]>..>d[t]=1(t趟排序);根据增量序列的选取其时间复杂度也会有变化,这个不少论文进行了研究,在此处就不再深究;本文采用首选增量为n/2,以此递推,每次增量为原先的1/2,直到增量为1。

2.2功能模块分析

1.数据输入:

采取随机函数实现输入数据表。

intinput_num()

{

printf("您要给多少个数排序?

\n\t\t");

scanf("%d",&data_num);

srand(NULL);

printf("随机产生%d个数:

\n\t\t",data_num);

for(inti=1;i<=data_num;i++)

{

data_array[i]=rand()%10000000;

printf("%d\n",data_array[i]);

old[i]=data_array[i];

printf("\n\t\t");

}

}

2.数据输出:

for循环输出即可。

intoutnew0()

{

printf("排序后的结果为:

");

for(inti=data_num;i>=1;i--)

printf("%d%s",data_array[i],i!

=1?

"":

"\n");

}

其中增加了输出空格与换行区别。

 

3.主界面实现:

printf("DATE:

Maytwenty2014\n");

printf("AllCopyrightReserved@2014-2015WangGuangchun\n");

printf("ADDRESS:

604AYIT\r\n\n\n");

printf("———————————————————\n");

printf("——————各种排序比较—————————\n");

printf("默认从大到小输出,可以选择9进行切换\n");

printf("———————————————————\n");

printf("**\n");

printf("***\n");

printf("**\n");

printf("*520*\n");

printf("*欢迎*\n");

printf("*使用*\n");

printf("**\n");

printf("*\n");

printf("欢迎再次使用!

!

!

\n\r\n");

printf("*******************************************\n");

printf("**.............**\n");

printf("**......**\n");

printf("**..........**\n");

printf("**......**\n");

printf("**................**\n");

printf("*******************************************\n");

 

4.人机交互界面:

printf("\n———————————————————\n");

printf("——————请输入指令————————\n");

printf("————********************—————\n");

printf("————$1.快速排序$—————\n");

printf("————$2.归并排序$—————\n");

printf("————$3.堆排序$—————\n");

printf("————$4.希尔排序$—————\n");

printf("————$5.插入排序$—————\n");

printf("————$6.选择排序$—————\n");

printf("————$7.冒泡排序$—————\n");

printf("————$8.重新随机输入$—————\n");

printf("————$9.选择排序方式$—————\n");

printf("————********************—————\n");

printf("—————0.退出——————\n");

printf("———————————————————\n");

printf("请选择:

\n");

 

printf("——————请输入指令————————\n");

printf("————********************—————\n");

printf("————$1.从小到大$—————\n");

printf("————$0.从大到小$—————\n");

printf("————********************—————\n");

printf("—————87.退出——————\n");

printf("———————————————————\n");

printf("请选择:

\n");

 

5.排序方法的实现:

(1)选择排序

voidchose_sort(inta[],intn)

{

intmin,temp;

for(inti=0;i

{

min=i;

for(intj=i;j

if(a[min]>a[j])

min=j;

temp=a[min];

a[min]=a[i];

a[i]=temp;

}

}

(2)希尔排序

voidShellInsert(int*a,intd,intn)

{

for(inti=d;i

{

intj=i-d;

inttemp=a[i];//记录要插入的数据

while(j>=0&&a[j]>temp)//从后向前,找到比其小的数的位置

{

a[j+d]=a[j];//向后挪动

j-=d;

}

if(j!

=i-d)//存在比其小的数

a[j+d]=temp;

}

}

voidShellSort(int*a,intn)

{

intd=n/2;//初始增量设为数组长度的一半

while(d>=1)

{

ShellInsert(a,d,n);

d=d/2;//每次增量变为上次的二分之一

}

}

(3)归并排序:

void__merge(inta[],intfirst,intmid,intlast,inttemp[])

{

inti=first,j=mid+1,m=mid,n=last,k=0;

while(i<=m&&j<=n)

{

if(a[i]<=a[j])

temp[k++]=a[i++];

else

temp[k++]=a[j++];

}

while(i<=m)

temp[k++]=a[i++];

while(j<=n)

temp[k++]=a[j++];

for(i=0;i

a[first+i]=temp[i];

}

voidMergeSort(inta[],intfirst,intlast,inttemp[])

{

if(first

{

intmid=(first+last)/2;

MergeSort(a,first,mid,temp);

MergeSort(a,mid+1,last,temp);

__merge(a,first,mid,last,temp);

}

}

boolMergeSort(inta[],intn)

{

int*p=newint[n];

if(p==NULL)

returnfalse;

else

{

MergeSort(a,0,n-1,p);

delete[]p;

returntrue;

}

}

(4)堆排序:

voidHeapAdjust(int*a,inti,intsize)//调整堆

{

intlchild=2*i;//i的左孩子节点序号

intrchild=2*i+1;//i的右孩子节点序号

intmax=i;//临时变量

if(i<=size/2)//如果i是叶节点就不用进行调整

{

if(lchild<=size&&a[lchild]>a[max])

max=lchild;

if(rchild<=size&&a[rchild]>a[max])

max=rchild;

if(max!

=i)

{

swap(a[i],a[max]);

HeapAdjust(a,max,size);//避免调整之后以max为父节点的子树不是堆

}

}

}

voidBuildHeap(int*a,intsize)//建立堆

{

inti;

for(i=size/2;i>=1;i--)//非叶节点最大序号值为size/2

HeapAdjust(a,i,size);

}

voidHeapSort(int*a,intsize)//堆排序

{

intj=1;

BuildHeap(a,size);

for(inti=size;i>=1;i--)

{

swap(a[1],a[i]);//交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面

//BuildHeap(a,i-1);//将余下元素重新建立为大顶堆

HeapAdjust(a,1,i-1);//重新调整堆顶节点成为大顶堆

}

}

(5)冒泡排序:

voidmaopao()

{

inttemp;

for(inti=1;i<=data_num;i++)

for(intj=i+1;j<=data_num;j++)

if(data_array[i]>data_array[j])

{

temp=data_array[i];

data_array[i]=data_array[j];

data_array[j]=temp;

}

}

(6)插入排序:

voidcharu()

{

inti,j;

inttemp;

printf("插入排序:

\n");

for(i=1;i<=data_num;i++)

{

inttemp=data_array[i];

for(j=i;j>0&&temp

{

data_array[j]=data_array[j-1];

}

data_array[j]=temp;

}

if(!

t)

outnew0();

else

outnew1();

}

(7)快速排序:

voidkuaisu1()//快速排序1

{

printf("快速排序:

\n");

sort(data_array+1,data_array+data_num+1);

if(!

t)

outnew0();

else

outnew1();

}

 

主程序

产生1组随机数

将随机数保存在数组中

选择排序

快速排序

归并排序

插入排序

冒泡排序

堆排序

希尔排序

选择排序方式

输出无序数组排序后的结果

选择操作方式

3.主要算法流程图

 

4.结果与结论

4.1正确结果

1.主界面人机交互

 

 

2.输入界面

3.选择排序方式

4.输出结果

 

5.退出界面

4.2错误信息

5.算法复杂度以及稳定性分析

下图反映了不同算法排序的时间复杂度的级别及其空间复杂度和稳定性。

算法名称

平均时间

辅助空间

稳定性

冒泡排序

O(n2)

O

(1)

选择排序

O(n2)

O

(1)

插入排序

O(n2)

O

(1)

归并排序

O(nlog2n)

O(n)

快速排序

O(nlog2n)

O(n)

堆排序

O(nlog2n)

O

(1)

希尔排序

\

O

(1)

下图表明了各种算法在不同数据规模下,完成排序所消耗的时间(毫秒为单位),从表中可以显然看出O(n2)的排序算法比O(nlog2n)的算法时间多出几百上千倍,而且随着数据数据规模增大时间比也会随着增大;因为排序的数据采用随机数,顺序将被打乱,快速排序算法优于其他排序算法。

算法名称

1万

2万

3万

4万

5万

6万

7万

8万

9万

10万

冒泡排序

1442

5497

12206

21861

34017

49148

67394

88880

111939

139071

选择排序

199

816

1790

3254

5062

7166

9645

12636

16102

19643

插入排序

178

717

1628

2882

4458

6446

8822

11649

14547

17914

归并排序

3

6

9

12

15

18

22

26

28

33

快速排序

2

5

8

11

14

18

21

25

29

32

堆排序

3

7

12

16

19

23

26

30

34

37

希尔排序

3

8

11

15

24

24

29

35

40

41

6.收获与致谢

通过这次课程设计作业我着实感受了一次编程的乐趣,从中学到了不少知识,虽然都说“程序=数据结构+算法”,但我们在学习运用数据结构编程之前,并没能深刻体会到这一点,直到这次课设实践。

我们感受最深的一点是:

以前用C编程,只是注重如何编写函数能够完成所需要的功能,似乎没有明确的战术,只是凭单纯的意识和简单的语句来堆砌出一段程序。

但现在编程感觉完全不同了。

在编写一个程序之前,自己能够综合考虑各种因素,首先选取自己需要的数据结构,然后选定一种或几种存储结构来具体的决定后面的函数的主要风格。

最后在编写每一个函数之前,可以仔细斟酌比对,挑选出最适合当前状况的算法。

这样,即使在完整的还没有写出来之前,自己心中已经有了明确的原图了。

这样无形中就提高了自己编写的程序的质量。

我们还体会到深刻理解数据结构的重要性。

只有真正理解定义数据类型的好处,才能用好这样一种数据结构。

了解典型数据结构的性质是非常有用的,它往往是编写程序的关键。

这次实验中我们也出现过一些错误。

但我们经过反复调试后,发现并做了修改,从而完成了此次课程设计。

在这次的数据结构课程设计中,我此次的题目是各种排序,排序实际上是编程设计中应用比较广泛的知识,通过本次设计,我对一些基本的内部排序有了很好的理解和掌握,并且通过此次课程设计中的程序运行结果很好的理解了排序各种算法的稳定性和时间复杂度,既巩固了课堂上学到的排序理论,又为自己的编程增强了实践。

总之,在这次的数据结构课程设计中,收获还是蛮多的。

也让自己对数据结构这门课程有了更好的认识,相信在越来越多的尝试之后,自己会不断进步不断提高的。

 

7.参考文献

1.《数据结构(C语言版)》严蔚敏清华大学出版社

2.《C语言程序设计》丁峻岭中国铁道出版社

3.《C程序设计》谭浩强清华大学出版社

 

8.附件

程序源代码:

 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

usingnamespacestd;

constintN=1000010;

intdata_num,data_array[N],data_arrayy[N];

intold[N],a[N],t;

//数据输入

intinput_num()

{

printf("您要给多少个数排序?

\n\t\t");

scanf("%d",&data_num);

srand(NULL);

printf("随机产生%d个数:

\n\t\t",data_num);

for(inti=1;i<=data_num;i++)

{

data_array[i]=rand()%10000000;

printf("%d\n",data_array[i]);

old[i]=data_array[i];

printf("\n\t\t");

}

}//排序后数据输出从大到小data_num1

intoutnew0()

{

printf("排序后的结果为:

");

for(inti=data_num;i>=1;i--)

printf("%d%s",data_array[i],i!

=1?

"":

"\n");

}//排序后逆序数据输出从小到大1data_num

intoutnew1()

{

printf("排序后的结果为:

");

for(inti=1;i<=data_num;i++)

printf("%d%s",data_array[i],i!

=data_num?

"":

"\n");

}

//排序后数据输出从大到小data_num-10

intoutnew2()

{

printf("排序后的结果为:

");

for(inti=data_num-1;i>=0;i--)

printf("%d%s",data_arrayy[i],i!

=0?

"":

"\n");

}//排序后逆序数据输出

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

当前位置:首页 > 表格模板 > 合同协议

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

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