【算法导论】线性时间选择---从数组中选择第i小的数
问题:从数组中选择第i小的数,并且要求问题的时间复杂度为O(n)。
代码用到了随机化的快速排序中的分组方法。
其基本原理为:用快速排序的分组方法,随机的选择一个数组元素,使其大于左边的元素,小于右边的元素。然后,看这个元素的下表与要求元素中第i小的值是否相等,如果小于i则表示要查找的元素在当前分组元素的右边,如果大于i表示在左边。这样递归进行,可以达到很高的运行效率。
c++实现的代码如下:
#include <iostream> #include <ctime>#include <set> #include <string> void swap(int * a,int * b); int partition(int * array_list,int left,int right); void Print(); int random_partition(int * array_list,int left,int right); const int size = 8; int random_slelect(int * array_list,int left,int right,int index);int * array_list; int main() { array_list = new int [sizeof(int)*size]; srand((unsigned)time(NULL));for(int i=0;i<size;i++) {/*随机的填充数组元素*/ int ran_num=rand()%( size*10); array_list[i] = ran_num; } Print(); std::cout<<random_slelect(array_list,0,size-1,1);getchar();return 0; } /*从数组中,选择第i小的数*/int random_slelect(int * array_list,int left,int right,int index){int val = 0;if(left == right){val = array_list[left];return val;}int q = random_partition(array_list,left,right);int k = q - left + 1;if(index == k){return array_list[q];}else if( index < k){random_slelect(array_list,left,q-1,index);}else{random_slelect(array_list,q+1,right,index - k);}}/*随机化的快速排序分组方法,对于输入的元素加入随机化的成分,使之获得较好的平均性能*/ int random_partition(int * array_list,int left,int right) { srand(left); int ran_num=( rand())% right; if((ran_num < left )) {/*防止出现因为取模后随机数为0的情况*/ ran_num = left; } /*如果,不交换排序区间内的数据,则成为普通的快速排序*/ swap(&array_list[right],&array_list[ran_num]); return partition(array_list,left,right); } int partition(int * array_list,int left,int right) { int index = left; int pivot = array_list[right]; for(int i= left ; i< right; i++) { if(array_list[i] < pivot) { swap(&array_list[index],&array_list[i]); index ++; } } swap(&array_list[right],&array_list[index]); //Print(); return index; } void swap(int * a,int * b) { int tmp = *a; *a = *b; *b = tmp; } void Print() { for(int i=0;i< size;i++) { std::cout<<array_list[i]<<"\t"; } std::cout<<std::endl; }