-
(一)问题描述
设计算法实现在一个具有n个互不相同元素的数组A[1……n]中找出所有前k个最小元素的问题,这里k不是常量,即它是输入数据的一部分。要求算法的时间复杂性为O(n)。
-
(二)具体要求
输入的第一行是一个正整数m,表示测试例个数。接下来几行是m个测试例的数据,每个测试例的数据由三行组成,其中,第一行输入一个正整数n,表示元素的个数;第二行输入n个整数,整数之间用一个空格隔开。第三行输入一个正整数k,表示该组测试例中的前k个最小元素(设给出的每个整数序列中的元素是唯一的)。
-
(三)解题思路
- 首先把整个问题进行拆分,分成三个部分:录入数据、对一组数据元素进行升序排序、输出前k个元素->解决问题
- 排序:我使用的是希尔排序(这边复习一下希尔排序):
举例如下一组数据含10个元素,起初是无序的。num=10代表元素个数,gap代表间隔几个数据进行比较。gap越大则大数和小数能更快的到达数据的两端,gap越小则比较并交换后的数据越接近有序(gap=1时,交换后的数据为最终需要的升序序列),一般取总元素个数的一半为初始gap。
【位置发生变换的元素颜色改变】
-
(四)完整代码
#include <stdio.h>
int num[30];
//排序函数:希尔排序
void ShallSort(int m){
for(int j=1;j<=m;j++){
//获取数据元素并录入数组
printf("请输入第%d个测试例的元素个数:",j);
int n;
scanf("%d",&n);
int i;
printf("请输入%d个元素(请用空格隔开):",n);
for(i=0;i<n;i++){
scanf("%d",&num[i]);
}
// 测试元素录入情况
// for(int j=0;j<n;j++){
// printf("%3d",num[j]);
// }
//对数组内元素进行希尔排序
int gap = n;
while (gap > 1) {
gap/=2;
int i;
//开始其中一次排序
for(i=0;i<n-gap;i++){
int end = i;
int tmp = num[end+gap];
while (end>=0) {
if(tmp<num[end]){
num[end+gap] = num[end];
end -= gap;
}
else{
break;
}
}
num[end+gap] = tmp;
}
}
printf("请输入需要前几个元素:");
int k;
scanf("%d",&k);
for(int i=0;i<k;i++){
printf("%3d",num[i]);
}
printf("\n");
}
}
int main(){
int m;
printf("请输入测试例个数:");
scanf("%d",&m);
//获取录入元素并排序
ShallSort(m);
return 0;
}
-
(五)测试及结果
-
(六)总结
本题还是简单的问题,问题变得复杂的时候,分治能发挥的作用真的很大,感觉写代码的时候,尽量让main函数保持精简,别的内容都“外包”给其他的函数,这样代码也更加清晰。在写的时候本来打算把排序和输出分到两个函数里,但是有点转不过弯来,最后还是写在一起了。有大佬可以实现分到两个函数的话,可以给我讲讲吗,感谢感谢。
然后,果然很大一部分思路还是得看前辈大佬的。学习之路漫漫啊……
谨以博客记录我的学习,复盘什么的。(咸鱼瘫)终于搞完了这篇。