求自定类型元素序列的中位数 PAT

PAT基础编程题目集中的求自定类型元素序列的中位数,通过率很低,只有6%,题目很简单,原题如下所述:

本题要求实现一个函数,求N个集合元素A[]的中位数,即序列中第\lceil N/2 \rceilN/2大的元素。其中集合元素的类型为自定义的ElementType

函数接口定义:

ElementType Median( ElementType A[], int N );

其中给定集合元素存放在数组A[]中,正整数N是数组元素个数。该函数须返回NA[]元素的中位数,其值也必须是ElementType类型。

裁判测试程序样例:

#include 

#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

输入样例:

3
12.3 34 -5

输出样例:

12.30

        通过读题可知,该题主要考察的就是排序问题了,于是本人很自信地用了选择排序法,结果可想而知,对于某个测试用例,显示运行超时;于是寻找效率高的排序算法,第一个想到的就是快速排序,但是依旧运行超时,平时总是听人说快速排序比大部分排序算法都要快,通常情况下选择快速排序算法,很显然,对于这道题来说,快速排序算法也是叫天不应了,可以想到的是,也许测试用例中有很多相同的元素,导致快速排序算法退化到了冒泡排序了,时间复杂度也从O(nlogn)退化到了O(n^2)了。因此需要寻找一种算法,这个算法在最优和最坏的情况下时间复杂度都是O(nlogn),归并排序和堆排序都可以,本文应用的是堆排序算法。具体代码如下所示:

void HeapAdjust(ElementType array[], int i, int nlength)
{
int nChild;
ElementType nTemp;
for (; 2 * i + 1 < nlength; i = nChild)
{
nChild = 2 * i + 1;
//得到子节点中较大的节点
if (nChild < nlength - 1 && array[nChild + 1] > array[nChild])
nChild++;
//如果较大的子节点大于父节点那么把较大的子节点往上移动,替换它的父节点
if (array[i] < array[nChild])
{
nTemp = array[i];
array[i] = array[nChild];
array[nChild] = nTemp;
}
else
break;
}
}
void Heapsort(ElementType array[], int length)
{
int i;//调整序列的前半部分元素,调整完之后第一个元素是序列的最大元素
ElementType temp;
for (i = length / 2 - 1; i >= 0; i--)
HeapAdjust(array, i, length);
//从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
for (i = length - 1; i >= 0; i--)
{
//把第一个元素和当前的最后一个元素交换
//保证当前的最后一个位置的元素都是现在这个序列中最大的
temp = array[0];
array[0] = array[i];
array[i] = temp;
//不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
HeapAdjust(array, 0, i);
}
}
ElementType Median(ElementType A[], int N)
{
Heapsort(A, N);
return A[N / 2];
}

提交代码后运行结果:

求自定类型元素序列的中位数 PAT_第1张图片

问题解决!该题还有需要注意的地方,那就是当N为偶数时,其中位数不再是中间两个数的平均值了,而是第N/2 + 1个数(从小到大排序),也就是元素下标为N/2的A的值,也即A[N/2]。







你可能感兴趣的:(求自定类型元素序列的中位数 PAT)