Emi*_*mir 8 c++ sorting vector quantile nth-element
我编写了一个程序,用户可以在向量中输入任意数量的值,它应该返回四分位数,但我不断得到"向量下标超出范围"错误:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <ios>
#include <vector>
int main () {
using namespace std;
cout << "Enter a list of numbers: ";
vector<double> quantile;
double x;
//invariant: homework contains all the homework grades so far
while (cin >> x)
quantile.push_back(x);
//check that the student entered some homework grades
//typedef vector<double>::size_type vec_sz;
int size = quantile.size();
if (size == 0) {
cout << endl << "You must enter your numbers . "
"Please try again." << endl;
return 1;
}
sort(quantile.begin(), quantile.end());
int mid = size/2;
double median;
median = size % 2 == 0 ? (quantile[mid] + quantile[mid-1])/2 : quantile[mid];
vector<double> first;
vector<double> third;
for (int i = 0; i!=mid; ++i)
{
first[i] = quantile[i];
}
for (int i = mid; i!= size; ++i)
{
third[i] = quantile[i];
}
double fst;
double trd;
int side_length = 0;
if (size % 2 == 0)
{
side_length = size/2;
}
else {
side_length = (size-1)/2;
}
fst = (size/2) % 2 == 0 ? (first[side_length/2]/2 + first[(side_length-1)/2])/2 : first[side_length/2];
trd = (size/2) % 2 == 0 ? (third[side_length/2]/2 + third[(side_length-1)/2])/2 : third[side_length/2];
streamsize prec = cout.precision();
cout << "The quartiles are" << setprecision(3) << "1st"
<< fst << "2nd" << median << "3rd" << trd << setprecision(prec) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Tem*_*Rex 21
而不是做std::sort(quantile.begin(), quantile.end())一些有点便宜的方式
auto const Q1 = quantile.size() / 4;
auto const Q2 = quantile.size() / 2;
auto const Q3 = Q1 + Q2;
std::nth_element(quantile.begin(), quantile.begin() + Q1, quantile.end());
std::nth_element(quantile.begin() + Q1 + 1, quantile.begin() + Q2, quantile.end());
std::nth_element(quantile.begin() + Q2 + 1, quantile.begin() + Q3, quantile.end());
Run Code Online (Sandbox Code Playgroud)
这不会对整个数组进行排序,而只会对4个四分位数进行"组间"排序.这节省了完整的"组内"排序std::sort.
如果您的quantile阵列不大,那么这是一个小优化.但标度行为std::nth_element是O(N)不过的,而不是O(N log N)的std::sort.
这是量子函数,它是MATLAB与线性插值的等效函数:
#include <algorithm>
#include <cmath>
#include <vector>
template<typename T>
static inline double Lerp(T v0, T v1, T t)
{
return (1 - t)*v0 + t*v1;
}
template<typename T>
static inline std::vector<T> Quantile(const std::vector<T>& inData, const std::vector<T>& probs)
{
if (inData.empty())
{
return std::vector<T>();
}
if (1 == inData.size())
{
return std::vector<T>(1, inData[0]);
}
std::vector<T> data = inData;
std::sort(data.begin(), data.end());
std::vector<T> quantiles;
for (size_t i = 0; i < probs.size(); ++i)
{
T poi = Lerp<T>(-0.5, data.size() - 0.5, probs[i]);
size_t left = std::max(int64_t(std::floor(poi)), int64_t(0));
size_t right = std::min(int64_t(std::ceil(poi)), int64_t(data.size() - 1));
T datLeft = data.at(left);
T datRight = data.at(right);
T quantile = Lerp<T>(datLeft, datRight, poi - left);
quantiles.push_back(quantile);
}
return quantiles;
}
Run Code Online (Sandbox Code Playgroud)
查找四分位数:
std::vector<double> in = { 1,2,3,4,5,6,7,8,9,10,11 };
auto quartiles = Quantile<double>(in, { 0.25, 0.5, 0.75 });
Run Code Online (Sandbox Code Playgroud)