排序和顺序统计学——中位数和顺序统计学

本文介绍了一种在平均和最坏情况下都能达到线性时间复杂度的选择算法,用于找到未排序数组中的第i小元素。文章详细展示了算法的实现过程,包括如何划分数组、寻找中位数以及递归应用选择算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个由n个元素组成的集合的第i个顺序统计就是该集合的第i小元素。
中位数:在i = (n + 1)/2⌋和(n + 1)/2⌉处。(i = 1, 2, ... , n)
选择问题:
输入:一个含n个(不同的)数的集合A和一个数i,1 i n。
输出:恰大于A中其他i-1个元素的x,(x A)。

一、求最大最小元

/*
 *Copyright(c) 2008 All rights reserved.
 *
 *MaxMin
 *Author:Greentea
 *Date:01.21
 
*/

#include 
<stdio.h>

struct data
{
    
int min, max;
}
;

typedef 
struct data data;

data MaxMin(
int *a, int size)
{
    data temp, l, r;
    
int disize;

    
if(size == 1)
    
{
        temp.min 
= temp.max = a[0];
        
return temp;
    }

    
else if(size == 2)
    
{
        
if(a[0< a[1])
        
{
            temp.min 
= a[0];
            temp.max 
= a[1];
        }

        
else
        
{
            temp.min 
= a[1];
            temp.max 
= a[0];
        }

        
return temp;
    }

    
else
    
{
        disize 
= size / 2;
        l 
= MaxMin(a, disize);
        r 
= MaxMin(a+disize, size-disize);
        
if(l.max > r.max)
            temp.max 
= l.max;
        
else
            temp.max 
= r.max;

        
if(l.min < r.min)
            temp.min 
= l.min;
        
else
            temp.min 
= r.min;

        
return temp;
    }

}


int main(int argc, char **argv)
{   
    
int a[100];
    
int size, i;
    data m;

    i 
= 0;
    scanf(
"%d"&size);
    
while(i < size)
        scanf(
"%d"&a[i++]);
    m 
= MaxMin(a, size);
    printf(
"Min = %d, Max = %d ", m.min, m.max);

    
return 0;
}


二、以线形期望时间做选择

/*
 *Copyright(c) 2008 All rights reserved.
 *
 *Quick Sort
 *Author:Greentea
 *Date:01.21
 
*/

#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<time.h>

int RandomizedPartition(int *a, int p, int r);
int Random(int low, int high);
void Exchange(int *a, int *b);
int Partition(int *a, int p, int r);
int RandomizedSelect(int *a, int p, int r, int i);

/*
 *产生介于low - high之间的随机数包括low和high
 *Return: random_num
 
*/

int Random(int low, int high)
{
    
int random_num;

    srand((unsigned)time(NULL));
    random_num 
= (rand() % (high - low + 1)) + low;

    
return random_num;
}


void Exchange(int *a, int *b)
{
    
int temp;
    temp 
= *a;
    
*= *b;
    
*= temp;
}


int Partition(int *a, int p, int r)
{
    
int i, j, x;

    i 
= p - 1;
    x 
= a[r];
    
for(j = p; j < r; j++)
    
{
        
if(a[j] <= x)
        
{
            i
++;
            Exchange(
&a[i], &a[j]);
        }

    }

    Exchange(
&a[i+1], &a[r]);

    
return i+1;
}


int RandomizedPartition(int *a, int p, int r)
{
    
int i;

    i 
= Random(p, r);
    Exchange(
&a[i], &a[r]);

    
return Partition(a, p, r);
}


int RandomizedSelect(int *a, int p, int r, int i)
{
    
int q, k;

    
if(p == r)
        
return a[p];
    q 
= RandomizedPartition(a, p, r);
    k 
= q - p + 1;
    
if(i == k)
        
return a[q];
    
else if(i < k)
        
return RandomizedSelect(a, p, q-1, i);
    
else
        
return RandomizedSelect(a, q+1, r, i-k);
}


int main(int argc, char **argv)
{
    
int i, temp;
    
int A[10= {549023361210};
    
    scanf(
"%d"&i);
    temp 
= RandomizedSelect(A, 09, i);
    printf(
"第%d小元素是%d ", i, temp);

    
return 0;
}

三、最坏情况线性时间的选择
Select通过执行下列步骤来确定长度为n输入数组中的第i小的元素:
1.将输入数组的n个元素划分成⌊n/5⌋组,每组5个元素,且至多只有一个组包含余下的n mod 5个元素。
2.通过插入排序来找出每组的中位数,并取其中间元素。
3.对第2步中找出的⌈n/5⌉个中位数,递归调用Select以找出其中位数x。
4.用修改的Partition版本,按x来对输入数组进行划分。
5.若i = k,则返回x。否则,若i < k,则在低区递归调用Select以找出第i小的元素;若i > k,则在高区找第(i - k)个最小元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值