北邮数据结构实验四题目1文档格式.docx
- 文档编号:21628923
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:14
- 大小:137.96KB
北邮数据结构实验四题目1文档格式.docx
《北邮数据结构实验四题目1文档格式.docx》由会员分享,可在线阅读,更多相关《北邮数据结构实验四题目1文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
存储结构:
顺序存储结构
示意图如下:
2.2关键算法分析
核心算法思想:
1.利用教材讲述的基本算法思想,实现七种排序算法,统计其运行相关数据。
2.将数组名当做地址传入函数,实现快速调用和统计。
使得程序代码可读性增、结构更加优化。
关键算法思想描述和实现:
关键算法1:
实现七种算法的基本排序功能。
1、插入排序:
依次将待排序的序列中的每一个记录插入到先前排序好的序列中,直到全部记录排序完毕。
2、希尔排序:
先将整个序列分割成若干个子列,分别在各个子列中运用直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序。
3、冒泡排序:
两两比较相邻记录的关键码,如果反序则交换,直到没有反序记录为止。
4、快速排序:
首先选择一个基准,将记录分割为两部分,左支小于或等于基准,右支则大于基准,然后对两部分重复上述过程,直至整个序列排序完成。
5、选择排序:
从待排序的记录序列中选择关键码最小(或最大)的记录并将它与序列中的第一个记录交换位置;
然后从不包括第一个位置上的记录序列中选择关键码最小(或最大)的记录并将它与序列中的第二个记录交换位置;
如此重复,直到序列中只剩下一个记录为止。
6、堆排序:
通过建立大根堆或者小根堆,取出根节点,反复调整堆使之保持大根堆或者小根堆,直至最后序列有序。
7、归并排序:
将若干个有序序列两两归并,直至所有待排序的记录都在一个有序序列为止。
C++实现:
voidInsert(intr[],intn)//直接插入排序,升序
{
intcompare=0,move=0;
定义比较和移动的系数并初始化为零,以下相同不再叙述
for(inti=2;
i<
n;
i++)将数组中的数一个一个放入序列
{
if(r[i]<
r[i-1])第一个位置当做哨兵,从第二个开始,若后面的数不比前面的数大则将哨兵入列,较小的数作为新哨兵
{
r[0]=r[i];
intj;
for(j=i-1;
r[0]<
r[j];
j--)若后面的数比哨兵大,则直接放进数列
{
r[j+1]=r[j];
move++;
每进行一次上移动从操作则移动加1
}
r[j+1]=r[0];
}
compare++;
每判断一次比较加1
}
cout<
<
"
比较次数:
"
compare<
移动次数:
move<
endl;
}
voidShellInsert(intr[],intn)//希尔排序
for(intd=n/2;
d>
=1;
d=d/2)主要思想每次循环跨越的步子折半
for(inti=d+1;
i++)依次比较每一个下标等差增长的数列
if(r[i]<
r[i-d])判断,小的值放前面
r[0]=r[i];
intj;
for(j=i-d;
j>
0&
&
j=j-d)比较没一个数列内的元素
r[j+d]=r[j];
r[j+d]=r[0];
compare++;
voidBubbleSort(intr[],intn)//改进后的冒泡排序
intpos=n;
while(pos!
=0)判断循环的结束条件,下面会有介绍
intbound=pos;
pos=0;
令pos初始化为0,之后如果没有进入循环修改其值则跳出while循环
for(inti=1;
bound-1;
i++)bound为每次循环需要进行的次数,因为排好序的元素不需要再进行比较
if(r[i]>
r[i+1])大数后置
r[i]=r[i+1];
r[i+1]=r[0];
pos=i+1;
intPartion(intr[],intfirst,intend,inta,intb)//一次快排
inti=first;
头
intj=end;
尾
intpivot=r[i];
哨兵
while(i<
j)头在尾之前,即尚未遍历数组
while((i<
j)&
(r[j]>
=pivot))右侧扫瞄,大于哨兵的不动
j--;
a++;
r[i]=r[j];
小小于哨兵的进入哨兵
b++;
(r[i]<
=pivot))进行左侧扫描,小于哨兵的写入数组
i++;
a++;
r[j]=r[i];
否则,进入哨兵
r[i]=pivot;
哨兵入列
returni;
voidQsort(intr[],inti,intj)//运用递归实现多次快排
{
if(i<
j)
intpivotloc=Partion(r,i,j,a,b);
依次分割排序区间
Qsort(r,i,pivotloc-1);
Qsort(r,pivotloc+1,j);
voidSelectSort(intr[],intn)//简单选择排序
for(inti=1;
i++)目前比较开始的元素
intmin=i;
为了判断目前的元素是否为最小
for(intj=i+1;
j<
j++)那当前元素和之后的元素比较
if(r[j]<
r[min])找出最小当前最小的元素并贴上标记
min=j;
if(min!
=i)如果标记被改变,就交换标记改变前后位置的元素,否则标记的元素即为最小不用改变
r[i]=r[min];
r[min]=r[0];
move++;
voidSift(intr[],intk,intm)//小根堆的筛选
inti=k,j=2*i;
while(j<
=m)循环结束的条件,最后的子节点大于总结点
if(j<
m&
r[j]>
r[j+1])比较左右孩子的大小,并将j指向较小的孩子
j++;
if(r[i]<
r[j])父节点比最大的子节点小则该堆建成,跳出循环
break;
else否则把父节点往下筛
r[0]=r[j];
r[j]=r[i];
r[i]=r[0];
i=j;
j=2*i;
voidHeapSort(intr[],intn)//小根堆排序
for(inti=n/2;
i>
i--)从最后一个有字节点的节点开始建小根堆
Sift(r,i,n);
i++)依次取出每一个小跟对的根节点,再重新筛,形成有序数列
r[0]=r[n-i+1];
r[n-i+1]=r[1];
r[1]=r[0];
Sift(r,1,n-i);
voidMerge(intr[],intr1[],ints,intm,intt,int*c,int*d)r为要排序的数组,r1为缓冲数组,s为第一个序列开始的位置,m为第一个序列的结束的位置,t为第二个序列的结束位置,c为比较次数的指针,d为移动次数的指针
inti=s;
定义两个要归并的序列的起始位置
intj=m+1;
intk=s;
=m&
=t)循环条件,两个序列都不空
r[j])将小数写进缓冲数组,小数对应的序列比较值后一一位
r1[k++]=r[i++];
(*d)++;
else
r1[k++]=r[j++];
(*c)++;
=m)当一个序列穷尽时,将另一个序列抄进缓冲数组
while(i<
=m)
if(j<
=t)
while(j<
voidMergePass(intr[],intr1[],intn,inth,int*c,int*d)将一个数组一次拆分成长度不同的小数组再两两归并
inti=1;
=n-2*h+1)h为本次小序列的长度,当能拆成两个等长的序列时,拆出该序列进行归并
Merge(r,r1,i,i+h-1,i+2*h-1,c,d);
i+=2*h;
每次归并完,序列长度增加一倍,再次归并
n-h+1)当只能拆出一个单位长度的序列和一个残缺序列时,只将第二个序列归并到最大长度n
Merge(r,r1,i,i+h-1,n,c,d);
Else只能拆出一个残序列时,只把该序列抄进缓冲数组即可
for(;
=n;
i++)
r1[i]=r[i];
voidMergeSort(intr[],intr1[],intn)
inth=1;
起始拆分的序列长度定义为一,即每个数都需要进行比较
while(h<
n)依次展长序列长度进行归并
MergePass(r,r1,n,h,&
compare,&
move);
h=2*h;
i++)将缓冲数组里的有序数写进原数组
r[i]=r1[i];
关键算法2:
获取当前系统时间,精确到微秒,分别在代码运行前后调用记录前后时间,再相减即可得到代码运行时间。
此处调用函数QueryPerformanceCounter()用于得到高精度计时器的值。
时间复杂度与空间复杂度:
理论分析可以得出各种排序算法的时间复杂度和空间复杂度,如下表所示:
排序方法
平均情况
最好情况
最坏情况
辅助空间
直接插入排序
O(n2)
O(n)
O
(1)
希尔排序
O(nlog2n)~O(n2)
O(n1.3)
起泡排序
O(n)
快速排序
O(nlog2n)
O(log2n)~O(n)
简单选择排序
堆排序
O(nlog2n)
归并排序
3.程序运行结果
程序运行框图:
实际测试和分析:
实际运行结果如下:
作如下分析:
1、多次运行之后统计,从乱序的时间消耗来看,基本符合理论分析。
。
2、由于加入了统计次数的代码,势必增加时间开销,这样统计出来的时间将有一定的误差。
假若比较次数和移动次数相差较多,则将产生较大的实验误差。
4.总结
通过本次试验我基本掌握了各种排序方法的基本算法和思想,通过编程增加了我的实际操作能力,在编程过程中也遇到过一些问题,比如消耗时间的测量,起初我的想法是用clock函数,但是后来发现其精度太低,经过查资料后才确定采用QueryPerformanceCounter()来得到高精度的计时器。
另外本程序也有一定的缺陷,比如采用了内置数组不具有实际作用,下一步的改进将是输入的数组,另外,采用了固定数组导致经过一次排序后其余的排序数组不再移动,为了能更好的突出各种排序方法的性能优劣,下一步应采用系统随机生成的随机数组。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 题目