# 1 STL std::nth_element

http://www.cplusplus.com/reference/algorithm/nth_element/

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main() {
std::vector<int> v{5, 6, 4, 3, 2, 6, 7, 9, 3};
std::nth_element(v.begin(), v.begin() + v.size()/2, v.end());
std::cout << "The median is " << v[v.size()/2] << '\n';
std::nth_element(v.begin(), v.begin()+1, v.end(), std::greater<int>());
std::cout << "The second largest element is " << v[1] << '\n';
}


The median is 5
The second largest element is 7

# 2 BFPRT算法(中位数的中位数算法)

## 2.1 举个例子

int arr[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };


BFPRT算法规定了，将5个元素作为一组（选出中位数）。然后，再选出中位数中的中位数…一直到，最终选出一个数字。

//执行momedians之前
{ 1,2,3,4,5} {6,7,8,9,10} {11,12,13,14,15} {16,17,18 };


//开始momedians
{ 3*,2,1*,4,5};//sort->swap(3,1)
{ 3,8*,1,4,5} {6,7,2*,9,10};//sort->swap(8,2)
{ 3,8,13*,4,5} {6,7,2,9,10} {11,12,1*,14,15};//sort->swap(13,1)
{ 3,8,13,17*,5} {6,7,2,9,10} {11,12,1,14,15} {16,4*,18 };//sort->swap(17,4)


//执行momedians之前
{ 3,8,13,17};


## 2.2 算法实现(c++)

//Median of Medians algorithm
int momedians(int* const low, int* const high) {
if (low >= high - 1) {
return *low;
}
//int grp_length = (int)std::sqrt(high - low);
int grp_length = 5, grp_idx = 0;
for (int* l = low, *r; l < high; l = r+1) {
r = (l + grp_length >= high) ? high : l + grp_length - 1;
std::sort(l, r); //可以使用下文的void isort(int* const low, int* const high)
std::swap(*(low+grp_idx++), *(l + (r - l) / 2));
}
return momedians(low, low + grp_idx);
}


//Insert sort
void insert_sort(int* const low, int* const high) {
for (int* i = low + 1; i <= high; ++i) {
if (*i < *(i-1)) {
int border = *i, *j = i-1;
for ( ; border < *j; --j) {
*(j+1) = *j;
}
*(j+1) = border;
}
}
}


#include <iostream>
#include <algorithm>
using namespace std;

//Median of Medians algorithm
int momedians(int* const low, int* const high) {
if (low >= high - 1) {
return *low;
}
int grp_length = 5, grp_idx = 0;
for (int* l = low, *r; l < high; l = r+1) {
r = (l + grp_length >= high) ? high : l + grp_length - 1;
std::sort(l, r);
std::swap(*(low+grp_idx++), *(l + (r - l) / 2));
}
return momedians(low, low + grp_idx);
}

//Quick sort
int qsort(int* const low, int* const high, int* const ptrk) {
int* l = low, *r = high;
if (l < r) {
int pivot = momedians(l, r);
while (l < r) {
while (l < r && *r >= pivot) {
--r;
}
*l = *r;
while (l < r && *l <= pivot) {
++l;
}
*r = *l;
}
*r = pivot;
}
//per qsort end, check left == right == ptrk?
return r == ptrk ? *ptrk :
(r > ptrk ?
qsort(low, r - 1, ptrk) :
qsort(r + 1, high, ptrk));
}

//Blum、Floyd、Pratt、Rivest、Tarjan
int bfprt(int* const low, int* const high, const int k = 1) {
if (low >= high || k < 1 || k > high - low) {
throw std::invalid_argument("low > high || k < 1");
}
return qsort(low, high-1, low + k -1);//[low, high)
}

int main() {
int arr[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };
//cout << bfprt(&arr[0], &arr[0]+1, 1) << endl;
cout << bfprt(&arr[0], &arr[0] + 18, 18) << endl;

return 0;
}


//Blum、Floyd、Pratt、Rivest、Tarjan
template<typename T>
T bfprt(T* const low, T* const high, const int k = 1) {
if (low >= high || k < 1 || k > high - low) {
throw std::invalid_argument("low > high || k < 1");
}
return qsort(low, high-1, low + k -1);//[low, high)
}


main函数中对intcharstring类型进行了测试。完整代码如下…

#include <iostream>
#include <algorithm>
using namespace std;

//Median of Medians algorithm
template<typename T>
T momedians(T* const low, T* const high) {
if (low >= high - 1) {
return *low;
}
int grp_length = 5, grp_idx = 0;
for (T* l = low, *r; l < high; l = r+1) {
r = (l + grp_length >= high) ? high : l + grp_length - 1;
std::sort(l, r);
std::swap(*(low+grp_idx++), *(l + (r - l) / 2));
}
return momedians(low, low + grp_idx);
}

//Quick sort
template<typename T>
T qsort(T* const low, T* const high, T* const ptrk) {
T* l = low, *r = high;
if (l < r) {
T pivot = momedians(l, r);
while (l < r) {
while (l < r && *r >= pivot) {
--r;
}
*l = *r;
while (l < r && *l <= pivot) {
++l;
}
*r = *l;
}
*r = pivot;
}
//per qsort end, check left == right == ptrk?
return r == ptrk ? *ptrk :
(r > ptrk ?
qsort(low, r - 1, ptrk) :
qsort(r + 1, high, ptrk));
}

//Blum、Floyd、Pratt、Rivest、Tarjan
template<typename T>
T bfprt(T* const low, T* const high, const int k = 1) {
if (low >= high || k < 1 || k > high - low) {
throw std::invalid_argument("low > high || k < 1");
}
return qsort(low, high-1, low + k -1);//[low, high)
}

int main() {
int arr[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };
cout << bfprt(&arr[0], &arr[0] + 18, 18) << endl;

char str[7] = {'a','b','c','d','e','f','g'};
cout << bfprt(&str[0], &str[0] + 7, 4) << endl;

string s = "abcdefghijklmnopqrstuvwxyz";
cout << bfprt(&s[0], &s[0] + 26, 10) << endl;

return 0;
}