题目描述
本题要求实现一个函数,求 N 个集合元素 A[]
的中位数,即序列中第 ⌊(N+1)/2⌋
大的元素。其中集合元素的类型为自定义的 ElementType
。
题目地址 https://pintia.cn/problem-sets/14/problems/743
解题思路
基本思路是排序后输出中间位置的元素(别的思路暂未尝试)。
遇到的问题是, 冒泡排序、C标准库的快排、基于二分查找的插入排序, 都 TLE。
最终选择了希尔排序, 一种改进的插入排序, 在N特别大的情况下,依然可以快速得到结果。
完整代码
// tags: 排序
// https://pintia.cn/problem-sets/14/problems/743
#include <stdio.h>
#define MAXN 10
typedef float ElementType;
ElementType Median( ElementType A[], int N );
int main ()
{
ElementType A[MAXN];
int N, i;
scanf("%d", &N);
for ( i=0; i<N; i++ )
scanf("%f", &A[i]);
printf("%.2f\n", Median(A, N));
return 0;
}
/* 你的代码将被嵌在这里 */
//------------------------------------------------------------
/// solution1: bubble sort
//------------------------------------------------------------
void bubble_sort(ElementType* A, int N)
{
for (int i=0; i<N; i++)
{
for (int j=0; j<N-1-i; j++)
{
if (A[j] > A[j+1]) {
ElementType t = A[j];
A[j] = A[j+1];
A[j+1] = t;
}
}
}
}
//------------------------------------------------------------
/// solution2: naive insertion sort
//------------------------------------------------------------
void insertion_sort_by_linear_search(ElementType* A, int N)
{
for (int i=0; i<N; i++)
{
int j;
ElementType t = A[i];
for (j=i; j>0 && A[j-1]>t; j--)
{
A[j] = A[j-1];
}
A[j] = t;
}
}
//------------------------------------------------------------
/// solution3: insersion sort, optimized with binary search
//------------------------------------------------------------
// https://www.geeksforgeeks.org/implementing-upper_bound-and-lower_bound-in-c/
// 找到第一个大于 val 的元素对应的索引
int upper_bound(ElementType* A, int L, int R, ElementType val)
{
int l = L;
int r = R;
while (l<r)
{
int m = l + (r-l)/2;
if (val <= A[m]) {
r = m;
} else {
l = m+1;
}
}
if (l < R && A[l]<val)
{
l++;
}
return l;
}
void insertion_sort_by_binary_search(ElementType* A, int N)
{
for (int i=0; i<N; i++)
{
ElementType t = A[i];
int j;
int pos = upper_bound(A, 0, i, A[i]);
for (j=i; pos>=0 && j>pos; j--)
{
A[j] = A[j-1];
}
A[j] = t;
}
}
//------------------------------------------------------------
/// solution 4: quick sort, calling C standard library API
//------------------------------------------------------------
#include <stdlib.h> // qsort
/*
void qsort(
void *base, // 数组首地址
size_t number, // 数组元素数量
size_t width, // 数组每个元素宽度
int (__cdecl *compare )(const void *, const void *) // 用来比较大小的函数指针
);
*/
int compare(const void* v1, const void* v2)
{
return (int)(*(float*)v1 - *(float*)v2);
}
//------------------------------------------------------------
// solution5: shell sort, one of the O(n log(n)) adapted insertion sort algorithm
//------------------------------------------------------------
void shell_sort(ElementType A[], int N)
{
for (int gap=N/2; gap>0; gap/=2)
{
for (int i=gap; i<N; i++)
{
ElementType t = A[i];
int j;
for (j=i; j>=gap; j-=gap)
{
if (t<A[j-gap])
{
A[j] = A[j-gap];
}
else
{
break;
}
}
A[j] = t;
}
}
}
ElementType Median( ElementType A[], int N )
{
//bubble_sort(A, N); // TLE
//insertion_sort_by_linear_search(A, N); // TLE
//insertion_sort_by_binary_search(A, N); // TLE
//qsort(A, N, sizeof(A[0]), compare); // TLE
shell_sort(A, N); //ok
return A[N/2];
}