特定分治策略

在一个数组S中查找第k小的元素并输出。
把n 分为五个一组,取每组中位数并排序,按照mm对数组进行划分,比mm小,比mm大,和mm相同的,第k小元素在哪块区域,对该区域再次递归调用本算法
在这里插入图片描述

typedef pair<int, int> pairs;
/*
 * 选择第k小元素
 */ 
int Select(vector<int> a, int k)//需要保证k的范围合理
{   
    int temp1 = a.size();
    vector<int>::iterator iter = a.begin();
    
    if(temp1 < 5){
        sort(iter, iter + temp1);
        return *(iter + k - 1);
    }
    
    int temp2, temp3, i, m, n, last, sdn, sxn/*大于或小于m的个数*/;
    vector<pairs> b;
    vector<pairs>::iterator iter1;
    vector<int> c, sd, sx;
    
    n = temp1 / 5;
    last = temp1 % 5;//不是5的倍数
    
    for(i = 0; i < n; ++i){
        temp2 = i * 5;
        sort(iter + temp2, iter + temp2 + 5);
        b.push_back(make_pair(*(iter + temp2 + 2), i + 1));
    }
    
    /*
    for_each(a.begin(), a.end(), Show);
    cout<<endl;
    for(vector<pairs>::iterator m = b.begin(); m != b.end(); ++m){
        cout<<"("<<m -> first<<","<<m -> second<<")";
    }
    cout<<endl;
    */
    
    for(iter1 = b.begin();iter1 != b.end(); ++iter1)
        c.push_back(iter1 -> first);
    m = Select(c, b.size() / 2 + 1);
    
    //cout<<m<<endl;
    
    (n % 2) ? (sdn = sxn = (n / 2 + 1) * 3 - 1) : (sxn = (n / 2 + 1) * 3 - 1, sdn = n / 2 * 3 - 1);

    //处理不能整除5而剩余的元素
    for(i = 0, iter = a.end() - 1; i < last; ++i){
        if(*(iter - i) >= m){
            ++sdn;
            sd.push_back(*(iter - i));
        }
        else{
            ++sxn;
            sx.push_back(*(iter - i));
        }
    }
    
    
    for(iter1 = b.begin(); iter1 != b.end(); ++iter1){
        temp3 = ((iter1 -> second) - 1) * 5 + 2;
        iter = a.begin() + temp3;
        if(iter1 -> first < m){
            sx.push_back(*iter);sx.push_back(*(iter - 1));sx.push_back(*(iter - 2));
            for(i = 1; i <= 2; ++i){
                if(*(iter + i) >= m){
                    ++sdn;
                    sd.push_back(*(iter + i));
                }
                else{
                    ++sxn;
                    sx.push_back(*(iter + i));
                }
            }
        }
        else if(iter1 -> first == m){
            sx.push_back(*(iter - 1));sx.push_back(*(iter - 2));
            sd.push_back(*(iter + 1));sd.push_back(*(iter + 2));
        }
        else{
            sd.push_back(*iter);sd.push_back(*(iter + 1));sd.push_back(*(iter + 2));
            for(i = -2; i <= -1; ++i){
                if(*(iter + i) >= m){
                    ++sdn;
                    sd.push_back(*(iter + i));
                }
                else{
                    ++sxn;
                    sx.push_back(*(iter + i));
                }
            }
        }
    }
    
    /*
    cout<<sdn<<endl;
    for_each(sd.begin(), sd.end(), Show);
    cout<<endl;
    cout<<sxn<<endl;
    for_each(sx.begin(), sx.end(), Show);
    cout<<endl;
    */
    if(k <= sxn)
        return Select(sx, k);
    else if(k == sxn + 1)
        return m;
    else
        return Select(sd, k - sxn - 1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值