算法:平衡树求第k大数 Sm 前段时间刚学会了用快速排序来求一个列中的第 k大数,可是她觉得每次 序列被改变

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:平衡树求第k大数 Sm 前段时间刚学会了用快速排序来求一个列中的第 k大数,可是她觉得每次 序列被改变相关的知识,希望对你有一定的参考价值。

Sm 前段时间刚学会了用快速排序来求一个列中的第 k大数,可是她觉得每次 序列被改变的时候就得重新算一遍!刚好今天教了平衡树,她决定要用来求第 k大数! 初始时给定一个大小为 N的序列,每次有两种操作:
a. 在序列中插入一个数。
b. 询问序列中第 k大数。
注意:所谓的第 k大数是指将序列排后的第 k个数。 序列中是可以出现重复元素的。
★数据输入 数据输入 数据输入
输入第一行有个整数 N
第二行有 N个整数表示初始的序列
第三行有一个数 M表示操作数
接下来 的 M行有两个数( a, b )
当 a=1 时,表示往序列中插入一个数 b
当 a=0 时,表示询问序列中第 b大数
★数据输出 数据输出 数据输出
对每次询问输出第 k大数。

算法描述

设第k个数为标准比a[k-1]大的数放到其左边,比他小的,放到其右边,其中保持a[k-1]是前k个数中最大的值

#include<iostream>
#include<string>
using namespace std;
int a[10000];
//寻找前k个数中的最大值
int found(int k)
int i;
int max=a[0],flag=0;
for(i=0;i<k;i++)
if(max<a[i])
max=a[i];
flag=i;

return flag;

void change(int &a,int &b)
if(a==b)
return;
int t;
t=a;
a=b;
b=t;

int main()

int n,k,i,flag;
while(cin>>n>>k)
memset(a,0,sizeof(a));
if(k>n)
continue;
for(i=0;i<n;i++)
cin>>a[i];
flag=found(k);
change(a[flag],a[k-1]);
for(i=k;i<n;i++)
if(a[i]<a[k-1])
change(a[i],a[k-1]);
flag=found(k);
change(a[flag],a[k-1]);


cout<<a[k-1]<<endl;

return 0;
参考技术A 用C++得MAP 参考技术B erw

快排划分思想的应用-求第k大数或者第k小的数(求前k大数或者前k小的数)

//第k大数,第k小的数--前k大数,k小的数-----------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
//每次选择第一个元素作为划分点,比它小放左边,比它大放右边
int partitionV2(int *a,int low,int high)

    int key=a[low];
    int i=low,j=high;
    while(i<j)
    
        while(i<j&&a[j]>=key)j--;
        a[i]=a[j];
        while(i<j&&a[i]<=key)i++;
        a[j]=a[i];
    
    a[i]=key;
    return i;

//寻找第k大数
int find_K_max(int *a,int n,int k)

/*
8 3
1 5 3 4 2 6 8 7
11 6
78934 234 65 32 543 354 567 3412 3 547 423
11 5
11 6 78934 234 65 32 543 354 567 3412 3
*/
    int low=0,high=n-1;
    while(low<=high)
    
        int index=partitionV2(a,low,high);
        if(index==n-k)
        
            return a[index];
        
        else if(index<n-k)
        
            low=index+1;
        
        else
        
            high=index-1;
        
    

//寻找第k小数
int find_K_min(int *a,int n,int k)

/*
8 3
1 5 3 4 2 6 8 7
11 6
78934 234 65 32 543 354 567 3412 3 547 423
11 5
11 6 78934 234 65 32 543 354 567 3412 3
*/
    int low=0,high=n-1;
    while(low<=high)
    
        int index=partitionV2(a,low,high);
        if(index==k-1)
        
            return a[index];
        
        else if(index<k-1)
        
            low=index+1;
        
        else
        
            high=index-1;
        
    

int main()

    int n,k;
    int a[100];
    while(cin>>n>>k)
    

        vector<int> mv(n);
        for(int i=0;i<n;++i)
        
            cin>>a[i];
            mv[i]=a[i];
        
        cout<<find_K_min(a,n,k)<<endl;
        sort(mv.begin(),mv.end());
        cout<<mv[k-1]<<endl;
    
    return 0;


以上是关于算法:平衡树求第k大数 Sm 前段时间刚学会了用快速排序来求一个列中的第 k大数,可是她觉得每次 序列被改变的主要内容,如果未能解决你的问题,请参考以下文章

平衡树之Splay

快排划分思想的应用-求第k大数或者第k小的数(求前k大数或者前k小的数)

快排划分思想的应用-求第k大数或者第k小的数(求前k大数或者前k小的数)

求第k大数

【python滴滴出行】整数无序数组求第K大数?

非递归的o(n)的求n个数里面第k大数的算法