在快排的基础上进行算法实现,只是每次分区之后只选择第i大的元素所在的区域进行查找。平均算法复杂度为O(n),最差算法复杂度为O(n^2),如同快排一样,出现最差情况的概率极低。
/**
* @brief Exception class which means that i is larger than the number of elements in the array
*/
class OutOfRange
{
public:
OutOfRange(){}
OutOfRange(std::string mes);
OutOfRange(OutOfRange &a);
~OutOfRange(){}
std::string Message() const;
private:
std::string message;
};
OutOfRange::OutOfRange(std::string mes): message(mes)
{
}
OutOfRange::OutOfRange(OutOfRange &a)
{
message = a.Message();
}
std::string OutOfRange::Message() const
{
return message;
}
/**
* @brief Partition the array
*
* @tparam T: template type
* @param array: the array to be partitioned
* @param start: the start position of the array
* @param end: the index of the last element in the array
*
* @return The partition position
*/
template <typename T>
int Partition(T *array, int start, int end)
{
T x = array[end];
int i = start;
int j = end - 1;
//i is to find the element who is larger than array[end]
//j is to find the element who is smaller than array[end]
while (i <= j)
{
if (array[i] <= x)
{
++i;
}
else
{
while (i <= j)
{
if (array[j] > x)
{
--j;
}
else
{
//swap element at i and j
T temp = array[i];
array[i++] = array[j];
array[j--] = temp;
break;
}
}
}
}
//i will be the first element who is larger than array[end] after arrange the array
//if there is no element larger than array[end], i will point to array[end]
T temp = array[i];
array[i] = x;
array[end] = temp;
return i;
}
/**
* @brief Get the i'th element in the array. The badest complexity is O(n^2), the average complexity is O(n).
*
* @tparam V: template type
* @param array: the array to be searched
* @param start: the start position of the array
* @param end: the index of the last element in the array
* @param i: find the i'th element
*
* @return the i'th element
*/
template <typename V>
V RandomSelect(V *array, int start, int end, int i)
{
if (i + start > end + 1)
{
OutOfRange a("ERROE: i is larger than the number of elements in the array!");
throw a;
}
if (start == end)
{
return array[start];
}
int p = Partition(array, start, end);
//k means the order of p in the array
int k = p + 1 - start;
if (i == k)
{
return array[p];
}
if (i < k)
{
return RandomSelect(array, start, p - 1, i);
}
else
{
return RandomSelect(array, p + 1, end, i - k);
}
}
#endif /* end of include guard: RANDOMSELECT_H */