找出数组中第i小元素
期望时间复杂度:Θ(n)
最坏情况的时间复杂度Θ(n^2)
int randomized_select(int *array,int start,int end,int index){
if(start == end)
return array[start];
int middle = randomized_partition(array,start,end);
int position = middle - start + 1;
if(index == position)
return array[middle];
else if(index < position)
return randomized_select(array,start,middle-1,index);
else
return randomized_select(array,middle + 1,end,index - position);
}
快速排序的随机划分函数:randomized_partition
>>链接地址
本版本为错误版本,中间的中位数求中位数排序用了插入排序,用插入算法,在最坏的情况下,时间复杂度Ω(n^2)
int select(int *array,int start,int end,int index)
{
//if(start == end) return array[start];
const int constant_num = 5;
int remainder = (end - start + 1) % constant_num;
int zero = remainder == 0 ? 0 : 1;
int num = (end - start + 1) / constant_num + zero;
int *median = new int[num];
if(remainder)
{
insertion_sort(array,start + (num - 1 ) * constant_num,start + (num - 1 ) * constant_num + remainder-1);
median[num-1] = array[start + (num - 1 ) * constant_num + (remainder - 1)/2];
}
for (int i = 0; i < num - zero; ++i) {
insertion_sort(array,start + i * constant_num,start + (i+1) * constant_num - 1);
median[i] = array[start + i * constant_num + constant_num / 2];
}
insertion_sort(median,0,num-1);
int key = median[(num-1) / 2];
delete[] median;
//划分
int middle = partition(array,start,end,key);
//递归求解
int position = middle - start + 1;
if(index == position)
{
return array[middle];
}
else if(index < position)
{
return select(array,start,middle-1,index);
}
else
{
return select(array,middle + 1,end,index - position);
}
}
下面是最坏情况的(当n>70时)时间复杂度Θ(n)
以下是正确版本
int select(int *array,int start,int end,int index)
{
if(start == end) return array[start];
const int constant_num = 5;
int remainder = (end - start + 1) % constant_num;
int zero = remainder == 0 ? 0 : 1;
int num = (end - start + 1) / constant_num + zero;
int *median = new int[num];
if(remainder)
{
insertion_sort(array,start + (num - 1 ) * constant_num,start + (num - 1 ) * constant_num + remainder-1);
median[num-1] = array[start + (num - 1 ) * constant_num + (remainder-1)/2];
}
for (int i = 0; i < num - zero; ++i) {
insertion_sort(array,start + i * constant_num,start + (i+1) * constant_num - 1);
median[i] = array[start + i * constant_num + constant_num / 2];
}
int key = select(median,0,num-1,num/2 + (num % 2 == 0 ? 0 : 1));
delete[] median;
//划分
int middle = partition(array,start,end,key);
//递归求解
int position = middle - start + 1;
if(index == position)
{
return array[middle];
}
else if(index < position)
{
return select(array,start,middle-1,index);
}
else
{
return select(array,middle + 1,end,index - position);
}
}
辅助函数partition
int partition(int *array,int start,int end,int key)
{
for (int i = start; i < end + 1; ++i) {
if(array[i] == key)
{
int temp = array[i];
array[i] = array[end];
array[end] = temp;
break;
}
}
int middle = start - 1;
for (int i = start; i < end; ++i) {
if(array[i] <= key)
{
middle++;
int temp = array[i];
array[i] = array[middle];
array[middle] = temp;
}
}
array[end] = array[middle+1];
array[middle+1] = key;
return middle + 1;
}