题目:找出一个数组中第m小的值并输出。
代码:
#include <stdio.h>代码的分析:
int findm_min(int a[], int n, int m) //n代表数组长度,m代表找出第m小的数据
{
int left, right, privot, temp;
int i, j;
left = 0;
right = n - 1;
while(left < right)
{
privot = a[m-1];
i = left;
j = right;
do
{
while(privot < a[j]) j--;
while(privot > a[i]) i++;
if(i < j)
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
i ++;
j --;
}
if(i == j && a[i] == privot)
return privot;
}while(i < j);
if(j < m-1)
left = i;
if(i > m-1)
right = j;
}
return a[m-1];
}
int main()
{
int data_set[10] = {125, 25, 32, 5, 6, 89, 124, 77, 98, 23};
printf("The m math number in the data_set is:%d.\n", findm_min(data_set, 10, 5));
return 0;
}
程序的思路,取数组第m个单元也就是a[m-1]作为每一次循环的一个阈值,将大于a[m-1]的全部放在数组的右边,小于a[m-1]的全部放在数组的左边,如果一直这样循环下去,那么最后a[m-1]这个单元中存放的就一定是第m小的数据。至于程序中比较难理解的我觉得是:
if(j < m-1) left = i; //这一句的意思是,程序是想寻找第m小的数据,但是j<m-1,表示现在这个阈值只大于数组中最多(m-2)个数组,那么要查找的第m小的值一定是比当前阈值大的数,然而存放在数组中,比当前阈值大的数的集合中的第一个数的下标正好是i,因为i是从while(privot < a[i]) i++;这个语句中跳出来的,所以这个时候将左查找范围设置为i。if(i > m-1) right = j;跟上面的理解差不多。
注意:其实这两个if判断来修正left和right查找范围的语句完全可以不需要,因为不修改的话每次都是从最左端查找到最右端,结果是一定能够查找出来的,只是效率方面可能就没有加上这两句好了。