#include
#include
#define swap(x, temp, y) (temp = x, x = y, y = temp)
//在[p,r]内找到中值mid_value,并用flag记录下标,使a[flag]与a[r]交换,利用快排思想使中值左边小于它,右边大于等于它,并返回其下标
int partition(int a[], int p, int r, int mid_value)
{
int temp, flag = 0, i = p, z = p - 1;
for(; i <= r; i++)
{
if(a[i] == mid_value)
{
flag = i;
break;
}
}
swap(a[flag], temp, a[r]);
for(i = p; i < r; i++)
{
if(a[r] > a[i])
{
z++;
swap(a[i], temp, a[z]);
}
}
swap(a[z + 1], temp, a[r]);
return z + 1;
}
//利用插值排序找到每组5个数的中值
int find_mid_of_five(int a[], int p, int r)
{
for(int i = p + 1; i <= r; i++)
{
int key = a[i],
index = i - 1;
while(index >= p && a[index] > key)
{
a[index + 1] = a[index];
index--;
}
a[index + 1] = key;
}
return a[(p + r)/2];
}
//递归找到所有数的中值
int find_mid_of_all(int a[], int p, int r)
{
if(p == r)
{
return a[p];
}
int b[23], index = 1;
for(int i = p; i <= r; i += 5)
{
if(i + 4 < r)
{
b[index] = find_mid_of_five(a, i, i + 4);
index++;
}
else
{
b[index] = find_mid_of_five(a, i, r);
}
}
find_mid_of_all(b, 1, index);
}
//找第j小的数
int find_j_min(int a[], int p, int r, int j)
{
if(p == r)
{
return a[p];
}
int mid_value = find_mid_of_all(a, p, r),
mid_index = partition(a, p, r, mid_value),
k = mid_index - p + 1;
if(k == j)
{
return a[mid_index];
}
else if(k > j)
{
return find_j_min(a, p, mid_index - 1, j);
}
else
{
return find_j_min(a, mid_index + 1, r, j - k);
}
}
int main(void)
{
int j, n, a[111], j_min;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
while(scanf("%d", &j), j)
{
j_min = find_j_min(a, 1, n, j);
printf("%d\n\n", j_min);
}
system("pause");
}
找第j小元素(最坏情况为线性时间)
最新推荐文章于 2021-05-26 11:35:17 发布