数据排序C程序设计课程设计报告.docx

上传人:b****5 文档编号:8137307 上传时间:2023-01-29 格式:DOCX 页数:29 大小:171.89KB
下载 相关 举报
数据排序C程序设计课程设计报告.docx_第1页
第1页 / 共29页
数据排序C程序设计课程设计报告.docx_第2页
第2页 / 共29页
数据排序C程序设计课程设计报告.docx_第3页
第3页 / 共29页
数据排序C程序设计课程设计报告.docx_第4页
第4页 / 共29页
数据排序C程序设计课程设计报告.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

数据排序C程序设计课程设计报告.docx

《数据排序C程序设计课程设计报告.docx》由会员分享,可在线阅读,更多相关《数据排序C程序设计课程设计报告.docx(29页珍藏版)》请在冰豆网上搜索。

数据排序C程序设计课程设计报告.docx

数据排序C程序设计课程设计报告

淮阴工学院

C++程序设计课程设计报告

选题名称:

数据排序

系(院):

专业:

班级:

姓名:

学号:

指导教师:

学年学期:

2015~2016学年第2学期

2016年6月28日

摘要:

排序是数据处理中经常使用的一种重要运算。

设文件由n个记录{R1,R2,……,Rn}组成,如n个学生记录,每个学生记录包括学号、姓名、班级等。

n个记录对应的关键字集合为{K1,K2,……,Kn},如学生的学号。

所谓排序就是将这n个记录按关键字大小递增或递减重新排列。

当待排序记录的关键字均不相同时,排序结果是惟一的,否则排序结果不唯一。

如果文件中关键字相同的记录经过某种排序方法进行排序之后,仍能保持它们在排序之前的相对次序,则称这种排序方法是稳定的;否则,称这种排序方法是不稳定的。

由于文件大小不同使排序过程中涉及的存储器不同,可将排序分成内部排序和外部排序两类。

整个排序过程都在内存进行的排序,称为内部排序;这里,主要讨论内部排序,外部排序不考虑。

内部排序方法可以分为五类:

插入排序、选择排序、交换排序、归并排序和分配排序。

几乎所有的排序都有两个基本的操作:

(1)关键字大小的比较。

(2)改变记录的位置。

具体处理方式依赖于记录的存储形式,对于顺序型记录,一般移动记录本身,而链式存储的记录则通过改变指向记录的指针实现重定位。

关键词:

插入排序;选择排序;冒泡排序;归并排序;希尔排序;交换排序

1课题需求描述

1.1课题来源

排序是数据处理中经常使用的一种重要运算。

设文件由n个记录{R1,R2,„„,Rn}组成,如n个学生记录,每个学生记录包括学号、姓名、班级等。

n个记录对应的关键字集合为{K1,K2,„„,Kn},如学生的学号。

所谓排序就是将这n个记录按关键字大小递增或递减重新排列。

当待排序记录的关键字均不相同时,排序结果是唯一的,否则排序结果不唯一。

如果文件中关键字相同的记录经过某种排序方法进行排序后,仍能保持它们在排序之前的相对次序,则称这种排序方法是稳定的;否则,这种排序方法是不稳定的。

由于文件大小不同使排序过程中涉及的储存器不同,可将排序分成内部排序和外部排序两类。

整个排序过程都在内存进行的排序,称为内部排序;反之,若排序过程中要进行数据的内、外存交换,则称之为外部排序。

内排序适用于记录个数不是很多的小文件,而外排序则适用于记录个数太多,不能一次性放入内存的大文件。

按策略划分,内部排序方法可以分为五类:

插入排序、选择排序、交换排序、归并排序和分配排序。

几乎所有的排序都有两个基本的操作:

(1)关键字大小的比较。

(2)改变记录的位置。

具体处理方式依赖于记录的存储形式,对于顺序型记录,一般移动记录本身,而链式存储的记录则通过改变指向记录的指针实现重定位。

排序算法很多,不同的算法有不同的优缺点,没有哪种算法在任何情况下都是最好的。

评价一种排序算法好坏的标准主要有两条:

(1)执行时间和所需的辅助空间,即时间复杂度和空间复杂度;

(2)算法本身的复杂程度,比如算法是否易读、是否易于实现。

2总体设计

2.1总体方案

(1)插入排序:

每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的记录集中,使记录依然有序,直到所有待排序记录全部插入完成。

(2)选择排序:

每一趟从待排序的数据中选出最小元素,顺序放在已排好序的数据最后,直到全部数据排序完毕。

(3)交换排序:

两两比较待排序的数据,发现两个数据的次序相反则进行交换,直到没有反序的数据为止。

(4)归并排序:

归并排序是利用“归并”技术来进行排序。

归并是指将若干个已排序的子文件合并成一个有序的文件。

实现方法有两种:

自底向上和自底向下。

自底向上的基本思想是:

第1趟归并排序时,将数列A[1..n]看作是n个长度为1的有序序列,将这些序列两两归并,若n为偶数,则得到[n/2]个长度为2的有序序列;若n为奇数,则最后一个子序列不参和归并。

第2趟归并则是将第一趟归并所得到的有序序列两两归并。

如此反复,直到最后得到一个长度为n的有序文件为止。

自顶向下的基本方法:

分治法。

其三个步骤:

1.分解:

将当前区间一分为二;

2.求解:

递归地对两个子区间进行归并排序;

3.组合:

将已排序的子区间归并为一个有序区间(终结条件:

子区间长度为1)

(5)冒泡

最多进行n-1趟排序,每趟排序时,从底部向上扫描,一旦发现两个相邻的元素不符合规则,则交换。

我们发现,第一趟排序后,最小值在A[1],第二趟排序后,较小值在A[2],第n-1趟排序完成后,所有元素完全按顺序排列。

(6)希尔排序

任取一个小于n的整数S1作为增量,把所有元素分成S1个组。

所有间距为S1的元素放在同一个组中。

第一组:

{A[1],A[S1+1],A[2*S1+1],……}

第二组:

{A[2],A[S1+2],A[2*S1+2],……}

第三组:

{A[3],A[S1+3],A[2*S1+3],……}

……

第s1组:

{A[S1],A[2*S1],A[3*S1],……}

先在各组内进行直接插人排序;然后,取第二个增量S2(

3详细设计和实现

3.1插入排序

假设待排序数据存放在数组A[1..n]中,则A[1]可看作是一个有序序列,让i从2开始,依次将A[i]插入到有序序列A[1..i-1]中,A[n]插入完毕则整个过程结束,A[1..n]成为有序序列。

排序过程示例(用【】表示有序序列)

待排序数据:

【25】548542119727315(n=10)

i=2:

【2554】8542119727315

i=3:

【82554】542119727315

i=4:

【8255454】2119727315

i=5:

【821255454】19727315

i=6:

【1821255454】9727315

i=7:

【182125545497】27315

i=8:

【1282125545497】7315

i=9:

【128212554547397】15

i=10:

【12815212554547397】排序结束

程序编写:

intcharu(intb[],intc)//将第一个看作有序数列,后面的数插入

{

system("cls");

inti,x,j;

cout<<"初始值:

";

print1(b,c);

for(i=1;i

{

x=b[i];

j=i-1;

while(x=0)

{

b[j+1]=b[j];

j--;

}

b[j+1]=x;

}

cout<<"排序后:

";

print1(b,c);

return1;

}

3.2选择排序

选择排序的基本思想是:

每一趟从待排序的数据中选出最小元素,顺序放在已排好序的数据最后,直到全部数据排序完毕。

过程模拟

待排序数据

92

28

62

84

62

16

56

87

33

66

第一趟排序

16

28

62

84

62

92

56

87

33

66

第二趟排序

16

28

62

84

62

92

56

87

33

66

第三趟排序

16

28

33

84

62

92

56

87

62

66

第四趟排序

16

28

33

56

62

92

84

87

62

66

第五趟排序

16

28

33

56

62

92

84

87

62

66

第六趟排序

16

28

33

56

62

62

84

87

92

66

第七趟排序

16

28

33

56

62

62

66

87

92

84

第八趟排序

16

28

33

56

62

62

66

84

92

87

第九趟排序

16

28

33

56

62

62

66

84

87

92

程序编写

intxuanze(intb[],intc)

{

system("cls");

inti,j,t,p;

cout<<"初始值:

";

print1(b,c);

for(i=0;i<=c-2;i++)

{

p=i;

for(j=i+1;j<=c-1;j++)

if(b[p]>b[j])

p=j;

if(p!

=i)

{

t=b[p];

b[p]=b[i];

b[i]=t;

}

}

cout<<"排序后:

";

print1(b,c);

return1;

}

3.3交换排序

交换排序的基本思想是:

两两比较待排序的数据,发现两个数据的次序相反则进行交换,直到没有反序的数据为止。

排序思想

在A[1..n]中任取一个数据元素作为比较的“基准”(不妨记为X),将数据区划分为左右两个部分:

A[1..i-1]和A[i+1..n],且A[1..i-1]≤X≤A[i+1..n](1≤i≤n),当A[1..i-1]和A[i+1..n]非空时,分别对它们进行上述的划分过程,直至所有数据元素均已排序为止。

排序过程示例

待排序数据:

6767145229990548771

X=67ij

扫描jij

交换5467145229990678771

扫描iij

交换5467145229967908771

j=i,结束ij

第一趟排序后:

54671452299[67]908771

第二趟排序后:

9291452[54]67[67]7187[90]

第三趟排序后:

[9]291452[54676771]87[90]

第四趟排序后:

[9]14[29]52[546767718790]

第五趟排序后:

[9142952546767718790]

程序编写

voidswap(int*a,int*b)

{

inttemp=*a;

*a=*b;

*b=temp;

}

intpartition(inta[],intlow,inthigh)

{

intprivotKey=a[low];//基准元素

while(low

while(low=privotKey)

--high;//从high所指位置向前搜索,至多到low+1位置。

将比基准元素小的交换到低端

swap(&a[low],&a[high]);

while(low

++low;

swap(&a[low],&a[high]);

}

returnlow;

}

 

voidqsort_improve(intr[],intlow,inthigh,intk)

{

if(high-low>k)//长度大于k时递归,k为指定的数

{

intpivot=partition(r,low,high);//调用的Partition算法保持不变

qsort_improve(r,low,pivot-1,k);

qsort_improve(r,pivot+1,high,k);

}

}

voidkuaisupaixu(intr[],intn,intk)

{

system("cls");

cout<<"初始值:

";

print1(r,n+1);

qsort_improve(r,0,n,k);//先调用改进算法Qsort使之基本有序

for(inti=1;i<=n;i++)//再用插入排序对基本有序序列排序

{

inttmp=r[i];

intj=i-1;

while(tmp

{

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

j=j-1;

}

r[j+1]=tmp;

}

cout<<"排序后:

";

print1(r,n+1);

}

3.4冒泡排序

排序思想

最多进行n-1趟排序,每趟排序时,从底部向上扫描,一旦发现两个相邻的元素不符合规则,则交换。

我们发现,第一趟排序后,最小值在A[1],第二趟排序后,较小值在A[2],第n-1趟排序完成后,所有元素完全按顺序排列。

排序示例

待排序数据:

5333195336382201939

第一趟排序:

3533319531963822039

第二趟排序:

3195333195320638239

第三趟排序:

3191953332053396382

第四趟排序:

3191920533339536382

第五趟排序:

没有反序数据,排序结束

程序编写

intmaopao(intb[],intc)

{

system("cls");

cout<<"初始值:

";

print1(b,c);

inti,j,t;

for(i=0;i

{

for(j=c-2;j>=i;j--)

{

if(b[j+1]

{

t=b[j+1];

b[j+1]=b[j];

b[j]=t;

}

}

}

cout<<"排序后:

";

print1(b,c);

return1;

}

3.5希尔排序

基本思想

任取一个小于n的整数S1作为增量,把所有元素分成S1个组。

所有间距为S1的元素放在同一个组中。

第一组:

{A[1],A[S1+1],A[2*S1+1],……}

第二组:

{A[2],A[S1+2],A[2*S1+2],……}

第三组:

{A[3],A[S1+3],A[2*S1+3],……}

……

第s1组:

{A[S1],A[2*S1],A[3*S1],……}

先在各组内进行直接插人排序;然后,取第二个增量S2(

排序示例

序号

1

2

3

4

5

6

7

8

9

10

原始数据

12

89

57

32

96

37

54

5

79

57

S1=5

组别

排序结果

12

54

5

32

57

37

89

57

79

96

S2=3

组别

排序结果

12

54

5

32

57

37

89

57

79

96

S3=2

组别

排序结果

5

32

12

37

57

54

79

57

89

96

S4=1

组别

排序结果

5

12

32

37

54

57

57

79

89

96

编写程序

voidxiercharpaixu(inta[],intn,intdk)

{

for(inti=dk;i

{

if(a[i]

{//若第i个元素大于i-1元素,直接插入。

小于的话,移动有序表后插入

intj=i-dk;

intx=a[i];//复制为哨兵,即存储待排序元素

a[i]=a[i-dk];//首先后移一个元素

while(x

{//查找在有序表的插入位置

a[j+dk]=a[j];

j-=dk;//元素后移

}

a[j+dk]=x;//插入到正确位置

}

}

}

voidxierpaixu(inta[],intn)

{

system("cls");

cout<<"初始值:

";

print1(a,n);

intdk=n/2;

while(dk>=1)

{

xiercharpaixu(a,n,dk);

dk=dk/2;

}

cout<<"排序后:

";

print1(a,n);

}

3.6归并排序

归并排序有两种实现方法:

自底向上和自顶向下。

自底向上的方法

自底向上的基本思想是:

第1趟归并排序时,将数列A[1..n]看作是n个长度为1的有序序列,将这些序列两两归并,若n为偶数,则得到[n/2]个长度为2的有序序列;若n为奇数,则最后一个子序列不参和归并。

第2趟归并则是将第1趟归并所得到的有序序列两两归并。

如此反复,直到最后得到一个长度为n的有序文件为止。

上述的每次归并操作,均是将两个有序序列合并成一个有序序列,故称其为“二路归并排序”。

类似地有k(k>2)路归并排序。

自顶向下的方法

采用分治法进行自顶向下的算法设计,形式更为简洁。

分治法的三个步骤:

设归并排序的当前区间是A[l..h],分治法的三个步骤是:

●分解:

将当前区间一分为二,即求分裂点m=(l+h)/2

●求解:

递归地对两个子区间A[l..m]和A[m+1..h]进行归并排序;

●组合:

将已排序的两个子区间A[l..m]和A[m+1..h]归并为一个有序的区间A[l..h]。

●递归的终结条件:

子区间长度为1(一个数据组成的区间必然有序)。

voidmerge1(int*a,intleft,intmid,intright)

{

int*t=newint[right-left+1];

intm=left,n=mid+1,k=0;

while((m<=mid)&&(n<=right))

{

if(a[m]

t[k++]=a[m++];

else

t[k++]=a[n++];

}

while(m<=mid)

t[k++]=a[m++];

while(n<=right)

t[k++]=a[n++];

for(m=0,k=left;k<=right;)

a[k++]=t[m++];

}

voidsort(int*a,intleft,intright)

{

if(left

{

intm=(left+right)/2;

sort(a,left,m);

sort(a,m+1,right);

merge1(a,left,m,right);

}

}

intguibin(intr[],intc)

{

system("cls");

cout<<"初始值:

";

print1(r,c);

//数组r1[]的大小一定要不小于r[]

sort(r,0,c-1);

cout<<"排序后:

";

print1(r,c);

return1;

}

4调试和测试

4.1程序模块图

Intmain

主函数完成输出的主界面以及输入数据的方式

Print1()

完成输出菜单的功能

intcharu

完成插入排序的功能

Intxuanze

完成选择排序的功能

Intmaopao

完成冒泡排序的功能

voidmerge1voidsortintguibin

三个程序共同完成归并排序

voidxiercharpaixuvoidxierpaixu

两个程序共同完成希尔排序

voidxuanzepaixu

完成二元排序

voidswapintpartitionvoidqsort_improvevoidkuaisupaixu

四个程序完成交换排序

4.2程序代码

#include

#include

#include

#include

#defineN10000

voidprint1(intb[],intc)

{

for(inti=0;i

cout<

cout<

}

//插入排序

intcharu(intb[],intc)//将第一个看作有序数列,后面的数插入

{

system("cls");

inti,x,j;

cout<<"初始值:

";

print1(b,c);

for(i=1;i

{

x=b[i];

j=i-1;

while(x=0)

{

b[j+1]=b[j];

j--;

}

b[j+1]=x;

}

cout<<"排序后:

";

print1(b,c);

return1;

}

//选择排序

intxuanze(intb[],intc)

{

system("cls");

inti,j,t,p;

cout<<"初始值:

";

print1(b,c);

for(i=0;i<=c-2;i++)

{

p=i;

for(j=i+1;j<=c-1;j++)

if(b[p]>b[j])

p=j;

if(p!

=i)

{

t=b[p];

b[p]=b[i];

b[i]=t;

}

}

cout<<"排序后:

";

print1(b,c);

return1;

}

//冒泡

intmaopao(intb[],intc)

{

system("cls");

cout<<"初始值:

";

print1(b,c);

inti,j,t;

for(i=0;i

{

for(j=c-2;j>=i;j--)

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

当前位置:首页 > 工作范文 > 行政公文

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

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