0
点赞
收藏
分享

微信扫一扫

锦标赛算法_找第一名和第二名

绣文字 2022-03-18 阅读 88
知识图谱
//

满二叉树:
            ( node_sum=2^layor-1 )    ( dad_pos=(x_pos-1)/2 )
0           (1=2^1-1)
1 2         (3=2^2-1)   (1-1)/2=0
3 4 5 6     (7=2^3-1)   (3-1)/2=1 (5-1)/2=2
...
( left_child_pos=2*dad_pos+1 )
( right_child_pos=left_child_pos+1 )

//
#include<bits/stdc++.h>
using namespace std;

const int N=1e5+6;
int a[N];

// a[] 起始数据
// b[] 起始数据对应的下标 -1 表示为空

void f2( int a[],int b[],int b_size,int k,int first )
{
    int k1=2*k+1,k2=k1+1;   // k的 左节点 右节点 
                            // 找到 first 的底层下标时 下一层肯定越界 所以把此时的父亲节点即 first 置为 -1 
    if( k1>=b_size || k2>=b_size ) { b[k]=-1; return ; }

    // 往 first 向下递归 因为其他部分的数据在上一轮已计算出
    if( b[k1]==first )  	f2( a,b,b_size,k1,first );
    else            		f2( a,b,b_size,k2,first );

    if( b[k1]<0 )       // 到达底层时 first_pos 置为 -1, b[k1] && b[k2] != first_pos, 开始向上重新比较  
    {
        if( b[k2]>=0 )  b[k]=b[k2];
        else            b[k]=-1;
        return ;
    }
    if( b[k2]<0 )
    {
        if( b[k1]>=0 )  b[k]=b[k1];
        else            b[k]=-1;
        return ;
    }
    if( a[ b[k1] ] > a[ b[k2] ] )   b[k]=b[k1];
    else                            b[k]=b[k2];
}

void f1( int a[],int a_size )
{
    int n=1;
    while( n<a_size ) n<<=1;

    int b_size=2*n-1;
    int *b=(int*)malloc( sizeof(int*)*b_size );

    int i;              // 底层节点数 == 非底层节点数的总和 +1
    for( i=0;i<n;i++ )  // pos == n-1, cnt == n, first_i == 0 -> pos: n-1~2*n-1-1, cnt_sum == n 
    {
        if( i<a_size )  b[ n-1+i ]=i;
        else            b[ n-1+i ]=-1;
    }
    for( i=b_size-1;i;i-=2 )
    {
        if( b[i]<0 )
        {
            if( b[i-1]>=0 )     b[ (i-1)/2 ]=b[i-1];
            else                b[ (i-1)/2 ]=-1;
        }
        else        // 右节点非 -1 左节点一定非 -1
        {
            if( a[ b[i-1] ]>a[ b[i] ] )     b[ (i-1)/2 ]=b[i-1];
            else                            b[ (i-1)/2 ]=b[i];
        }
    }
    printf("first_pos=%d,value=%d\n",b[0],a[ b[0] ] );
    f2( a,b,b_size,0,b[0] );
    printf("second_pos=%d,value=%d\n",b[0],a[ b[0] ] );
    free(b);
}

int main()
{
    int n,i;
    while( ~scanf("%d",&n) )
    {
        for( i=0;i<n;i++ ) scanf("%d",&a[i]);
        f1( a,n );
    }
    return 0;
}
举报

相关推荐

0 条评论