算法第二章上机实验报告
1. 实践题目名称: 找第k小的数
2. 问题描述:输入一组数组,和k,求该数组中第k小的数并输出
3. 算法描述:主要由三个函数:
I.Swap函数(利用中间变量t对调数组中的两个元素)
II.Part函数(用数组中的某个数将数组分为两半,并返回该数字在排好序后在数组中的下标j)
{
int x=a[left];
int i=left,j=right+1;
while(true){
while(a[++i]<x&&i<right);
while(a[--j]>x);
if(i>=j) break;
Swap(a,i,j);
}
a[left]=a[j];
a[j]=x;
return j;
}
III.find函数(判断Part函数返回的下标j+1是否与k相等,如果j+1大于k,则用find函数查询j左边的数组,否则查询j右边的数组)
{
int j=Part(a,left,right);
if(j+1==k)
cout<<a[j]<<endl;
else if(j>k-1) find(a,left,j-1,k);
else find(a,j+1,right,k);}
IV.再用main函数输入数组,调用find函数
4. 算法时间及空间复杂度分析(要有分析过程)
时间复杂度:由于将序列第一个元素作为mid来分开序列,具有一定的随机性。所以我们只能考虑极限情况,最坏情况时,即每次选的都是最大值或者最小值,则需要进行k次循环,T = O(n^2)。
空间复杂度:利用递归,T=O(log n)
5. 心得体会(对本次实践收获及疑惑进行总结)
学会了快速排序的算法,懂得问题的转化与缩略;如果没有学到快速排序,我想到的解题方法可能就是全部排好序后再找出对应的值,这章学习不仅仅是掌握了快排算法,更是给我在思考问题方面有很大启发。在进行解题时,发现只有一半题目通过,反复检查与思考,才发现find的左右范围应该为(0~n-1),而不是(0~n),细节还是没有注意到,发现时恍然大悟。
1. 实践题目名称: 找第k小的数
2. 问题描述:输入一组数组,和k,求该数组中第k小的数并输出
3. 算法描述:主要由三个函数:
I.Swap函数(利用中间变量t对调数组中的两个元素)
II.Part函数(用数组中的某个数将数组分为两半,并返回该数字在排好序后在数组中的下标j)
{
int x=a[left];
int i=left,j=right+1;
while(true){
while(a[++i]<x&&i<right);
while(a[--j]>x);
if(i>=j) break;
Swap(a,i,j);
}
a[left]=a[j];
a[j]=x;
return j;
}
III.find函数(判断Part函数返回的下标j+1是否与k相等,如果j+1大于k,则用find函数查询j左边的数组,否则查询j右边的数组)
{
int j=Part(a,left,right);
if(j+1==k)
cout<<a[j]<<endl;
else if(j>k-1) find(a,left,j-1,k);
else find(a,j+1,right,k);}
IV.再用main函数输入数组,调用find函数
4. 算法时间及空间复杂度分析(要有分析过程)
时间复杂度:由于将序列第一个元素作为mid来分开序列,具有一定的随机性。所以我们只能考虑极限情况,最坏情况时,即每次选的都是最大值或者最小值,则需要进行k次循环,T = O(n^2)。
空间复杂度:利用递归,T=O(log n)
5. 心得体会(对本次实践收获及疑惑进行总结)
学会了快速排序的算法,懂得问题的转化与缩略;如果没有学到快速排序,我想到的解题方法可能就是全部排好序后再找出对应的值,这章学习不仅仅是掌握了快排算法,更是给我在思考问题方面有很大启发。在进行解题时,发现只有一半题目通过,反复检查与思考,才发现find的左右范围应该为(0~n-1),而不是(0~n),细节还是没有注意到,发现时恍然大悟。