数据结构课程设计报告.docx
- 文档编号:29480238
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:40
- 大小:176.46KB
数据结构课程设计报告.docx
《数据结构课程设计报告.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告.docx(40页珍藏版)》请在冰豆网上搜索。
数据结构课程设计报告
《数据结构》课程设计报告
姓名:
潘庆
专业:
计算机科学与技术
班级:
J1401
学号:
4141110020
指导老师:
王新宇
2016年1月15日
目录
一、需求分析2
二、设计说明3
1.算法设计的思想3
2.主要的数据结构设计说明4
3.程序的主要流程图5
4.程序的主要模块6
5.程序的主要函数及其伪代码说明6
三、上机结果及体会13
1.实际完成情况说明13
2.程序运行结果及图示13
3.问题及解决方案16
4.收获及体会16
附录(源程序)17
一、需求分析
1.程序所实现的功能:
七种排序算法的演示:
(1)直接插入排序;
(2)冒泡排序;(3)选择排序;(4)快速排序;(5)归并排序;(6)堆排序;(7)基数排序。
要求:
(1)设计一个人机交互界面;
(2)给出从初始开始时每一趟排序的结果。
2.程序的输入:
用户开始时自行输入排序个数和具体数字(须为整数)
voidinput_int(SqList&L)
{
inti;
printf("请输入排序个数:
");
scanf("%d",&L.length);
printf("请输入%d个整数:
",L.length);
for(i=1;i<=L.length;i++)
scanf("%d",&L.r[i].key);
}
3.程序的输出:
用户选择具体排序方法后,程序将每一趟排序的输出结果一次性输出,最后一趟即为最终排序结果
voidoutput_int(SqListL)
{
inti;
for(i=1;i<=L.length;i++)
printf("%d",L.r[i].key);
}
4.测试数据:
122163082841020618
二、设计说明
1.算法设计的思想
(1).插入排序
基本思路:
向有序表中插入新的元素(或记录),使之仍有序,此时表的长度也相应地发生变化。
排序过程:
整个排序过程为n-1趟插入,即先将序列中第1个记录看成是一个有序子序列,然后从第2个记录开始,逐个进行插入,直至整个序列有序。
(2).冒泡排序
基本思路:
设排序表中有n个数据元素。
首先对排序表中第一,二个数据元素的关键字A[0]和A[1]进行比较。
如果前者大于后者,则进行交换;然后对第二,三个数据做同样的处理;重复此过程直到处理完最后两个相邻的数据元素。
我们称之为一趟冒泡,它将关键字最大的元素移到排序表的最后一个位置,其他数据元素一般也都向排序的最终位置移动。
然后进行第二趟排序,对排序表中前n-1个元素进行与上述同样的操作,其结果使整个排序表中关键字次大的数据元素被移到A[n-2]的位置。
如此最多做n-1趟冒泡就能把所有数据元素排好序。
排序过程:
将第一个记录的关键字与第二个记录的关键字进行比较,若为逆序r[1].key>r[2].key,则交换;然后比较第二个记录与第三个记录;依次类推,直至第n-1个记录和第n个记录比较为止——第一趟冒泡排序,结果关键字最大的记录被安置在最后一个记录上。
对前n-1个记录进行第二趟冒泡排序,结果使关键字次大的记录被安置在第n-1个记录位置。
重复上述过程,直到“在一趟排序过程中没有进行过交换记录的操作”为止。
(3).选择排序
基本思路:
a)开始时设i的初始值为0。
b)如果i c)若A[k]不是这组数据元素中的第一个数据元素(i≠k),则将A[k]与A[i]这两数据元素的位置对调;d)令i=i+1转步骤b)。 排序过程: (1)在n个记录中,通过n-1次关键字比较,找出关键字最小的记录,将它与第一个记录交换 (2)在剩余的n-1个记录,通过n-2次比较,找出关键字最小的记录,将它与第二个记录交换…(i)剩余的n-i+1个记录,通过n-i次比较,找出关键字最小的记录,将它与第i个记录交换…(n-1)在剩余的2个记录中,通过1次比较,找出关键字最小的记录,将它与第n-1个记录交换。 (4).快速排序 基本思想: 通过一趟排序,将待排序记录以某个记录为界分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,分别对这两部分记录按同样方法继续进行排序,以达到整个序列有序。 排序过程: 对L.r[s]、L.r[s+1]、…L.r[t]中记录进行一趟快速排序,附设两个指针i和j,设枢轴记录rp=L.r[s],x=rp.key,初始时令i=s,j=t,首先从j所指位置向前搜索第一个关键字小于x的记录,并和rp交换,再从i所指位置起向后搜索,找到第一个关键字大于x的记录,和rp交换,重复上述两步,直至i==j为止,完成一趟快速排序。 再分别对两个子序列按同样方法进行快速排序,直到每个子序列只含有一个记录为止 (5).归并排序 排序过程: 设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列长度为1。 两两合并,得到ën/2û个长度为2或1的有序子序列。 再两两合并,……如此重复,直至得到一个长度为n的有序序列为止。 (6).堆排序 算法描述: 假设将n个记录构成的记录序列按关键字由小到大排列。 1.建立n个结点的大顶堆,将关键字最大的堆顶记录与记录序列中的第n个记录互换。 2.通过堆结点的筛选与记录互换建立记录有序序列。 (1)对前n-1个记录进行筛选,重新调整为一个大顶堆;将关键字最大的堆顶记录与记录序列中的第n-1个记录互换。 (2)对前n-2个记录进行筛选,重新调整为一个大顶堆;将关键字最大的堆顶记录与记录序列中的第n-2个记录互换。 (7).基数排序 基本思想: 将排序关键字K看作是由多个关键字组成的组合关键字,即K=k1k2…kd。 每个关键字ki表示关键字的一位,其中k1为最高位,kd为最低位,d为关键字的位数。 每个关键字的取值范围为0≤ki≤9,所以每个关键字可取值的数目为10。 通常将关键字取值的数目称为基数,用符号r表示,在这个例子中r=10。 关键字序列(AB,BD,ED),K=k1k2,每个关键字的取值范围为“A~Z”,所以关键字的基数r=26。 2.主要的数据结构设计说明 本程序的主要数据结构为线性顺序表。 结构体: typedefstruct { intkey; int*keys;//关键字项 intbitsum;//关键字位数 }RcdType;//记录类型 typedefstruct { RcdTyper[MAXSIZE+1]; intlength; }SqList;//顺序表 3.程序的主要流程图 4.程序的主要模块 函数的功能为对快速排序、插入排序、选择排序、冒泡排序、堆排序、归并排序、基数排序算法的演示。 主函数: 程序运行时,可使运行者根据提醒输入相关操作,从而进入不同的排序方法或者退出。 快速排序函数: 根据快速排序的算法,最后输出 插入排序函数: 根据插入排序的算法,最后输出 选择排序函数: 根据选择排序的算法,最后输出 冒泡排序函数: 根据冒泡排序的算法,最后输出 堆排序函数: 根据堆排序的算法,最后输出 归并排序函数: 根据归并排序的算法,最后输出 基数排序函数: 根据基数排序的算法,最后输出 5.程序的主要函数及其伪代码说明 插入排序: voidInsertSort(SqListL) { inti,j,h=1; for(i=2;i<=L.length;i++) { if(L.r[i].key { L.r[0]=L.r[i];//设置监视哨 for(j=i-1;L.r[0].key L.r[j+1]=L.r[j];//记录后移(给要插入的元素腾位置) L.r[j+1]=L.r[0];//插入到正确位置(直到插入的元素大于比较的元素时停止循环) } printf("第%d趟: ",h++); //输出本趟排序结果 output_int(L); printf("\n"); } } 冒泡排序: voidBubbleSort(SqListL) {//对顺序表L作起泡排序 inti,j,lastExchangeIndex,h=1; RcdTypew;//记录交换的中间变量 i=L.length;//1.代表记录上界2.记录有无交换 while(i>1)//i>1表明上一趟曾进行过记录的交换 { lastExchangeIndex=1;//最后发生记录交换的下标位置(=1表示从头开始) for(j=1;j { if(L.r[j+1].key { w=L.r[j];L.r[j]=L.r[j+1];L.r[j+1]=w;//互换记录 lastExchangeIndex=j;//把j赋值给最后发生记录交换的下标位置(记录下标位置) }//if }//for i=lastExchangeIndex;//一趟排序中无序序列中最后一个记录的位置=全部元素(while循环条件) printf("第%d趟: ",h++); //输出本趟排序结果 output_int(L); printf("\n"); }//while }//BubbleSort 选择排序: voidSelectSort(SqListL)//选择排序 {//对顺序表L作简单选择排序。 inti,j,k,h=1; RcdTypew;//记录交换的中间变量 for(i=1;i {//选择第i小的记录,并交换到位 j=i;//j为第一个记录从1开始 for(k=i+1;k<=L.length;k++)//要比较的元素就是第一个记录后面的元素,不能超过顺序表的长度 { if(L.r[k].key j=k;//记录最小的那个元素作为要比较的元素,变成j } if(i! =j)//若果第i小的记录不是最小元素j,则需要交换位置 { w=L.r[j]; L.r[j]=L.r[i]; L.r[i]=w; } printf("第%d趟: ",h++); //输出本趟排序结果 output_int(L); printf("\n"); } }//SelectSort 快速排序: intPartition(SqList&L,inti,intj)//快排 { intx;//下表在i与j之间的记录进行一趟快排 L.r[0]=L.r[i];//将枢轴记录暂放在0号单元 x=L.r[i].key;//x为枢轴记录关键字 while(i {while(i if(i while(i if(i } L.r[i]=L.r[0];//将枢轴记录放入合适位置 output_int(L); printf("\n"); returni;//返回枢轴位置 } voidQSort(SqList&L,ints,intt)//整个快速排序的递归算法 { if(s { intpivotloc=Partition(L,s,t);/*将表一分为二*/ QSort(L,s,pivotloc-1);/*对低子表进行递归排序*/ QSort(L,pivotloc+1,t);/*对高子表进行递归排序*/ } } voidQuickSort(SqListL)//对顺序表快速排序(先分割成独立的两部分调用QSort一部分记录的关键字比另一部分关键字大) { QSort(L,1,L.length); } 归并排序: voidMerge(RcdTypeSR[],RcdTypeTR[],inti,intm,intn)//i....mm+1...n {//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]kj intj,k; for(j=m+1,k=i;i<=m&&j<=n;k++) {//将SR中记录由小到大地并入TR if(SR[i].key<=SR[j].key) TR[k]=SR[i++]; else TR[k]=SR[j++]; } while(i<=m) TR[k++]=SR[i++];//将剩余的SR[i..m]复制到TR while(j<=n) TR[k++]=SR[j++];//将剩余的SR[j..n]复制到TR }//Merge voidMSort(RcdTypeSR[],RcdTypeTR1[],ints,intt,SqList&L)//二路归并//对SR[s..t]进行归并排序,排序后的记录存入TR1[s..t]。 {//对SR[s..t]进行归并排序,排序后的记录存入TR1[s..t]。 RcdType*TR2=newRcdType[t-s+1];//开设用于存放归并排序中间结果的辅助空间 if(s==t) TR1[s]=SR[s]; else { intm=(s+t)/2;//将SR[s..t]平分为SR[s..m]和SR[m+1..t] MSort(SR,TR2,s,m,L);//递归地将SR[s..m]归并为有序的TR2[s..m] MSort(SR,TR2,m+1,t,L);//递归地将SR[m+1..t]归并为有序的TR2[m+1..t] Merge(TR2,TR1,s,m,t);//将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] for(inti=s;i<=t;i++) printf("%d",TR1[i]); printf("\n"); }//else }//MSort voidMergeSort(SqListL)//对顺序表进行归并排序 { MSort(L.r,L.r,1,L.length,L); } 堆排序: typedefSqListHeapType;//堆筛选 {//下标从s..m intj; RcdTyperc;//已知H.r[s..m]中记录的关键字除H.r[s].key之外均满足堆的定义,本函数 //依据关键字的大小对H.r[s]进行调整,使H.r[s..m]成为一个大顶堆(对其中 //记录的关键字而言) rc=H.r[s];//暂存根结点的记录 for(j=2*s;j<=m;j*=2) {//沿key较大的孩子结点向下筛选 //j为左孩子,j<=m判断筛选的结点是否为叶子结点 if(j ++j;//(目的: 找左右孩子最大值) //j+1右孩子存在,并且左孩子也存在,并且右孩子大,j为key较大孩子记录的下标 if(rc.key>=H.r[j].key) break;//不需要调整 //双亲的关键字》最大孩子的关键字 H.r[s]=H.r[j]; s=j;//应为不是最终要调的位置,所以只要把大关键字记录往上调,不把结点放在孩子位置上 } H.r[s]=rc;//回移筛选下来的记录 }//HeapAdjust voidHeapSort(HeapTypeH)//堆排序 {//对顺序表H进行堆排序。 从无序序列的第n/2个元素(即此无序序列对应的完全二叉树的最后一个非终端结点)起,至第一个元素止,进行反复筛选 inti,h=1; RcdTypew; for(i=H.length/2;i>0;--i)//把H.r[1..H.length]建成大顶堆,i为无序序列第n/2个元素 HeapAdjust(H,i,H.length); w=H.r[1];H.r[1]=H.r[H.length];H.r[H.length]=w;//交换"堆顶"和"堆底“的记录 output_int(H); printf("\n"); for(i=H.length-1;i>1;--i)//从n/2个元素后前一个 { HeapAdjust(H,1,i);//从根开始调整,将H.r[1..i]重新调整为大顶堆 //从1-i个记录进行堆筛选 w=H.r[1];H.r[1]=H.r[i];H.r[i]=w;//将堆顶记录和当前的"堆底"记录相互交换使已有序的记录堆积到底部 printf("第%d趟: ",h++); output_int(H); printf("\n"); } }//HeapSort 基数排序: //寻找关键字中的最大值 intFindMax(SqList&L) { intmax; max=1; for(inti=2;i<=L.length;i++) if(L.r[i].key>L.r[max].key) max=i; returnL.r[max].key; } //计算最大关键字的位数 intCountBitSum(intmax) { intbitsum=1; while(max/=10) bitsum++; returnbitsum; } //将所有关键字进行截取,转化为多关键字数组 voidConvertKeys(SqList&L,intbitsum) { inti,j; inttmp;//为了防止key除到最后为0 for(i=1;i<=L.length;i++) { L.r[i].keys=newint[bitsum]; for(j=0;j L.r[i].keys[j]=0; j=bitsum; tmp=L.r[i].key; while(tmp) { L.r[i].keys[--j]=tmp%10; tmp/=10; } } } voidRadixPass(RcdTypeA[],RcdTypeB[],intn,inti)//一趟基数排序 { //对数组A中记录关键字的"第i位"计数,并按数组count的值 //将数组A中记录复制到数组B中 intj,k; intcount[100]; for(j=0;j count[j]=0;//计数数组初始化为0 //当j小于关键字基数10 for(k=1;k<=n;++k) count[A[k].keys[i]]++;//对关键字的第i位"计数" for(j=1;j count[j]=count[j-1]+count[j];//累加操作(目的: 为确定数据元素在排序后的位置) for(k=n;k>0;--k)//从右端开始复制记录 { j=A[k].keys[i];//取得关键字 B[count[j]]=A[k]; count[j]--; }//for }//RadixPass voidRadixSort(SqListL,intbitsum)//基数排序 {//对顺序表L进行基数排序 inti,j; RcdType*C=newRcdType[L.length+1];//开设同等大小的辅助空间用于复制数据 i=bitsum-1;//关键字数组keys下标从0开始,从最低位开始排序 while(i>=0) { RadixPass(L.r,C,L.length,i);//对L.r进行一趟基数排序,结果存入C for(j=1;j<=L.length;j++) printf("%d",C[j]); printf("\n"); i--; if(i>=0) { RadixPass(C,L.r,L.length,i);//对C进行一趟基数排序,结果存回L.r output_int(L); printf("\n"); i--; } else { for(j=1;j<=L.length;++j) L.r[j]=C[j];//排序后的结果在C中,复制至L.r中 printf("\n"); } }//while }//RadixSort 三、上机结果及体会 1.实际完成情况说明 此次课程设计基本符合了要求,运行时没有出错,界面友好,条理做到了清晰明了,但仍有很多可以改进的地方,需日后加强。 2.程序运行结果及图示 图一用户输入界面 图二插入排序结果 图三冒泡排序结果 图四快速排序结果 (接上页)图五选择排序结果 图六堆排序结果 图七基数排序结果 (接上页)图八归并排序结果 图九程序退出 3.问题及解决方案 (1)问题: 当进行多次排序后,程序页面杂乱,影响可读性 解决方案: 在主函数case语句中加入system("cls");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)