实验4.1 查找第K大的数
实验目的
(1)理解分治算法的求解过程。
(2)通过范例学习分治策略设计技巧,学会分析分治算法的时间复杂度。
(3)掌握用分治算法求解具体问题,了解其面临的瓶颈。
实验任务
(1)设计在未排序的数组中查找第K大的数的高效算法。
(2)用C++语言实现该算法并进行测试。
(3)撰写实验报告,实验报告内容包括实验目的、实验任务、实验环境、实验步骤、实验结果和实验总结等部分。
实验步骤及结果
实验预习
设计在未排序的数组中查找第K大的数的高效算法
在快速排序的过程中,通过判断返回的枢轴的值和第k大数的下标是否相等,如果相等则代表第k大数已固定位置,直接返回,输出部分有序数组中第k大数的下标即可得打第k大的数;如果枢轴大于第k大数的下标则只需向小于枢轴的部分进行递归即可;如果枢轴小于第k大数的下标则只需向大于枢轴的部分进行递归即可。注:返回枢轴的值范围不一定是所有下标,此情况需要在将数组全部排序后才会得到第k大的值。
用C/C++语言实现的源代码
#include <iostream>
using namespace std;
// 输入数的个数
int n = 0;
// 第k大的数
int k;
// 数组
int arr[100];
// 划分函数 返回枢轴
int partition(int L, int R){
int i = L;
int j = R + 1;
// 选择第一个元素为枢轴元素
int pivot = arr[L];
while (true)
{
// 从左至右扫描
while (arr[++i] < pivot && i < R);
while(arr[--j] > pivot);
// 如果相遇则所有元素都处于正确位置 退出循环
if(i >= j) break;
// 交换arr[i] 和 arr[j]
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
// 交换arr[j] 和 枢轴元素
arr[L] = arr[j];
arr[j] = pivot;
// 返回枢轴元素索引j
return j;
}
void quicksort(int L, int R){
if(L < R){
// 返回的枢轴
int p = partition(L, R);
// 如果枢轴等于第k大值的下标
if(p == n-k){
return;
}
// 如果枢轴大于第k大值的下标
if(p > n-k){
quicksort(L, p-1);
}else{// 如果枢轴小于第k大值的下标
quicksort(p+1, R);
}
}
}
int main(void){
// 读取输入
char temp;
int number = 0;
while (temp = getchar())
{
if(temp == ' '){
arr[n] = number;
number = 0;
n++;
}else if(temp == '\n'){
arr[n] = number;
number = 0;
n++;
break;
}else{
number = number * 10 + (temp - '0');
}
}
cin>>k;
// 进行快排选择
quicksort(0, n-1);
// 输出结果
cout<<arr[n-k]<<endl;
system("pause");
return 0;
}
上机实验
上机调试,利用实验教程上的测试用例验证程序是否正确
测试用例1
输入:3 2 1 5 6 4 k=2
输出:5
程序截图:
程序正确
测试用例2
输入:3 2 3 1 2 4 5 5 6 k=4
输出:4
程序截图:
程序正确
设计新的测试用例,对程序进行进一步验证
测试用例
输入:23 2 3 35 30 7 1 34 6 13 15 k=6(中位数)
输出:13
程序截图:
中位数求解正确
实验总结
通过具体实验了解了分治算法的分析求解过程,以及如何设计分治算法解决实际问题。通过此次实验,使我可以正确理解分治算法的特点以及在实际应用中如何正确设计并使用分治算法。