[二分法]线性时间内在数组中找出第k大的数

#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

 

posted @ 2015-05-23 01:06  chunyi  阅读(755)  评论(0编辑  收藏  举报