代码来源于周强老师主讲的,青岛大学,数据结构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) ); } }
本人认为大数左移更容易理解一些
#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); } }