算法設計與分析——求無序序列中第k小的數(類快排思想)

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <stack>
#include <set>
#define IOS ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int maxn=1000;
//二分法在無序序列中找到第k小的數
int find_k(int l,int r,int a[],int k){
    if(l==r)return a[l];
    int mid=a[l];//將訪問區間的第一個作爲分界標準值
    int pre=l,rear=r+1;
    //將所有小於mid的放到mid左邊,大於mid的放到mid右邊,兩遍都有可能存在等於mid的
    while(pre<rear){
        while(pre<r&&a[++pre]<mid);//從左邊開始找不小於mid的數
        while(a[--rear]>mid);//從右邊找不大於mid的數
        if(pre<rear)//如果沒有到達分界處就交換
            swap(a[pre],a[rear]);
    }
    a[l]=a[rear];
    a[rear]=mid;//將標準值放到分解處(a[rear]保證了小於mid所以可以交換)
    if(k==rear)return a[rear];//如果rear的值正好是k,根據搜索的原理,第k小的數肯定等於a[rear];
    //根據k所在區間搜索左或右兩個區間
    if(k<rear){
        return find_k(l,rear-1,a,k);
    }
    else{
        return find_k(rear+1,r,a,k);
    }
}
int main()
{
    IOS;
    int n,k;
    int a[maxn];
    cout<<"序列元素的個數:";
    cin>>n;
    cout<<"第k小數:k=";
    while(cin>>k){
        if(k<1||k>n){
            cout<<"輸入的k應該在區間[1:n]範圍,請重新輸入"<<endl;
            cout<<"k=";
        }
        else break;
    }
    cout<<"輸入"<<n<<"個元素值(空格間隔):";
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int ans=find_k(1,n,a,k);//求a[1:n]內第k小的數
    cout<<"ans="<<ans<<endl;
    getchar();
    getchar();
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章