分治算法

  代码来源于周强老师主讲的,青岛大学,数据结构mooc

  分治法,是把原问题分解成规模较小的问题;从小问题的解,构建出原问题的解使用分治法的前提是,把规模为N的问题划分成两个规模为二分之N的问题,然后把小规模问题再合并起来花的时间是线性时间,T(N) = 2T(N/2) + O(N) --> T(N) = O(N logN)

  在一个数组中查找第K个大的数,使用分治算法

#include <iostream>
using namespace std;
#define maxsize 100

/* 
8
8 3 4 1 9 7 10 6 
3
*/

void swap( int &a, int &b);
void findKmax(int *a, int left, int right, int k);

int main()
{
    int a[maxsize];
    int n;
    int k;
    int i;
    
    cout << "input the length of arr:";
    cin >> n;
    
    for(i=0; i<n; ++i)
        cin >> a[i];
    
    cout << "input K:" << endl;
    cin >> k;
    
    findKmax(a, 0, n-1, k );
    
    for(i=0; i<n; ++i)  //调用函数后数组的变化
        cout << a[i] << " ";
    
    cout << "K-th max number is " << a[n-k] << endl;
    
    return 0;
}

void swap( int &a, int &b){
    int t = a;
    a = b;
    b = t;
}

void findKmax( int *a, int left, int right, int k ){
    int i=left, j=right, partition = a[i];
    while(i!=j){
        while(i<j && a[j]>partition) j--;
        swap( a[i], a[j] );
        while(i<j && a[i]<partition) i++;
        swap( a[i], a[j] );
        if( right-i+1 == k )  // right-i+1
            return;
        else if( right-i+1 > k )
            findKmax( a, i+1, right, k );
        else if( right-i+1 < k )
            findKmax( a, left, i-1, k-(right-i+1) );
    }
}
View Code

  本人认为大数左移更容易理解一些

#include <iostream> 
using namespace std;
#define maxsize 100

int partition(int *l,int low,int high);
void findk(int k,int *l,int low,int high);
 
int main() 
{
    int a[maxsize];
    int m, k;
        
    cin >> m >> k;
    
    for (int i = 0; i < m;i++) {
        cin >> a[i];
    }
    
    findk(k,a,0,m-1);
    
    cout << endl;
    
    for (int i = 0; i < m;i++) {
        cout << a[i] << " ";
    }
    
    return 0;
} 
 
int partition(int *l,int low,int high) //大数左移,小数右移
{ 
    int p = l[low];
    while (low != high) {
        while (low < high && l[high] <= p) {
            high--;
        }
        l[low] = l[high];  //大数替换
        while (low < high && l[low] >= p) {
            low++;
        }
        l[high] = l[low]; //小数替换    
    }
    l[low] = p; //p的位置

    return low;  // 分界p的下标
}

void findk(int k,int *l,int low,int high) {

    int temp = partition(l,low,high);

    if (temp == k - 1) {
        cout << l[temp];
    }
    else if (temp < k-1) { //小于k的位置, 向右边找
        findk(k, l, temp + 1, high);
    }
    else {        //大于k的位置, 向左边找
        findk(k, l, low, temp - 1);        
    }
} 
View Code
原文地址:https://www.cnblogs.com/GoldenEllipsis/p/14068960.html