选择问题(选出第i个最小元素)
通过分治法解决的分析(还有其他方法解决选择问题如使用 堆)
1 同快速排序一样,对输入的数组进行递归分解
不同的是:快速排序会递归处理分解的两边,而选择问题只处理需要的一边
2 选择问题的期望时间代价为Θ (n) (平均性能)
3 选择问题一般思路
a. 随机选取一个key
b. 进行区域划分,比key小的在左边,比key大的在右边
c. key的下标与 i (第i个最小元素的下标)比较,分别处理3种情况
相等: 即为需要选择的元素
i<key: 说明第i个最小元素在划分区域的左边,进行递归分解左边的区域
i>key: 说明第i个最小元素在划分区域的右边,进行递归分解右边的区域,[注意需要考虑
此时第i个元素在区域右边为第i-k(key的下标)个最小元素]
1 #include <iostream> 2 using namespace std; 3 4 //交换数据 5 void Swap(int array[], int i, int j) 6 { 7 int temp = array[i]; 8 array[i] = array[j]; 9 array[j] = temp; 10 } 11 12 //选择问题,index 表示选择第i个最小元素 13 int RandomSelect(int array[], int size, int index) 14 { 15 if (size <=1) 16 { 17 return array[size-1]; //只有一个元素时即为需要选择的元素 18 } 19 20 int key = 0; 21 Swap(array, 0, rand()%size); //随机化取样,获得关键值key并与array[0]交换 22 23 //进行区域划分,分别与key比较,小于key的都在左边,大于key的都在右边 24 for (int i=1; i<size; ++i) 25 { 26 if (array[i] < array[0]) 27 { 28 Swap(array, ++key, i); 29 } 30 } 31 Swap(array, 0, key);//关键值key回到正确的位置 32 33 if (key == index-1) //相等,即为需要选择的第i个元素 34 { 35 return array[key]; 36 } 37 else if (index-1 < key) //index小于key,即第i个元素在划分区域的左边 38 { 39 return RandomSelect(array, key, index); 40 } 41 else//index大于key,即第i个元素在划分区域的左边,注意同时更新index-key-1(去除key本身) 42 { 43 return RandomSelect(array+key+1, size-key-1, index-key-1); 44 } 45 } 46 47 void main() 48 { 49 50 int Array[10] = {4, 1, 3, 2, 6, 9, 10, 5, 8, 7}; 51 52 int i = 10; 53 cout << "第" << i <<"个最小元素: " 54 << RandomSelect(Array, 10, i) << endl; 55 56 system("pause"); 57 }
(转载请注明作者和出处^_* Seven++ http://www.cnblogs.com/sevenPP/ )