#include "stdafx.h" #include "iostream" using namespace std;
//参数为 数组指针,开始下标, 结束下标, 第K大数(k从0开始)
int rand_par(int array[], int start, int end, int th){ if( start < 0 || end < 0 || th < 0 || end < start ){ return -1; } int left = start; int right = end; int key = array[right]; while( left < right ){ while( left < right && array[left] <= key){ //找到左边第一个大于key的下标 left++; } array[right] = array[left]; while( left < right && array[right] >= key ){ //找到左边第一个小于key的下标 right--; } array[left] = array[right]; //让他们交换 } array[left] = key; //如果碰对了结果就返回,否则通过二分法,继续递归 if( left == th ){ return array[left]; }else if( left > th ){ return rand_par( array, start, left - 1 , th ); }else{ return rand_par( array, left + 1, end , th ); } return 0; } int _tmain( void ) { int array[] = {432,13,61,6,425,132,422,4213,521}; //测试数据,参数为数组 开始下标, 结束下标, 第K大数(k从0开始) int r1 = rand_par(array,0, 8, 0); int r2 = rand_par(array,0, 8, 1); int r3 = rand_par(array,0, 8, 8); int r4 = rand_par(array,0, 8, 5); cout<<r1<<endl; cout<<r2<<endl; cout<<r3<<endl; cout<<r4<<endl; return 0; }
算法导论里基础内容,算法基本上和快速排序没什么区别。今天学习不太认真,所以只能拿这个凑博文了。
我想在
int array[] = {432,13,61,6,425,132,422,4213,521};
找到第K大的数。比如K=6.
这里运用到了二分法的思想。每次计算都把范围减少一半。
数组开始下标为 start = 0
结束下标为 end = 8
1. 取数组最后一项array[end]当作重要线索key,这key有特殊用途。
432, 12, 61, 6, 425, 132, 422, 4213, 521
下标 0 1 2 3 4 5 6 7 8
2. 通过排序,让所有大于key的移动到key的右边,小于key的移动到key的左边。key的下标因此会发生改动(不再是最后一项了,假设变成了m)。我们可以知道数组第m大的项是key
排序后成了这样 432, 12, 61, 6, 425, 132, 422, 521, 4213
下标 0 1 2 3 4 5 6 7 8 看图可知 m == 7 , array[m] == 521
3.我们算出了第7大数...但并没有算出第K大数
很明显, m> k
这时候将数组分为两段: 432, 12, 61, 6, 425, 132, 422 和 521, 4213。
所求的第6大的数一定在前面这个数组里。因为左边的数都比521小。右边的数都会比521大。
---------------------------------------------------------------------------
start = 0
end = 6
将这个数组进行排序: 432, 12, 61, 6, 425, 132, 422
下标 0 1 2 3 4 5 6
排序后的结果是 12, 61, 6, 132, 422,432,425
下标 0 1 2 3 4 5 6
得到了数组中第4大的元素是422。依然不是我们想得到的答案。
这时又可以把数组分为两部分。 12, 61, 6, 132, 422 和 432,425
m < k,所以答案肯定在右边的数组找。
-------------------------------------------------------------------------------------
就这样一直计算下去,一定能碰到我们所求的第K大数。偷懒了, 最后答案是425