Создание вектора индексов отсортированного вектора [дубликат]
этот вопрос уже есть ответ здесь:
- C++ сортировка отслеживание индексов 4 ответы
переменная x
- это вектор n
ints, и я хочу отсортировать вектор в порядке возрастания. Однако по причинам, выходящим за рамки этого вопроса, я хочу, чтобы вектор оставался нетронутым. Поэтому, скорее чем собственно сортировка содержимого x
, Я хочу создать еще один вектор n
индексы, где каждый индекс ссылается на соответствующее значение в x
, Если x
должны были быть отсортированы.
например:
std::vector<int> x = {15, 3, 0, 20};
std::vector<int> y;
// Put the sorted indices of x into the vector y
for (int i = 0; i < 4; i++)
{
std::cout << y[i];
}
надо дать выход:
2
1
0
3
соответствует значениям в x:
0
3
15
20
Я могу придумать множество своевременных способов реализации этого, но мне интересно, есть ли у STL что-то встроенное для выполнения это эффективно для меня?
5 ответов
1) создать y
как вектор индекса (целочисленный диапазон)
2) сортировка этого диапазона с помощью компаратора, который возвращает элементы индексов из x
Используя стандартную библиотеку, которая дает:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> x = {15, 3, 0, 20};
std::vector<int> y;
std::vector<int> y(x.size());
std::size_t n(0);
std::generate(std::begin(y), std::end(y), [&]{ return n++; });
std::sort( std::begin(y),
std::end(y),
[&](int i1, int i2) { return x[i1] < x[i2]; } );
for (auto v : y)
std::cout << v << ' ';
return 0;
}
заполнить y
со всеми индексами x
затем использовать std::sort
on y
но обеспечивают компаратор, который сравнивает соответствующие элементы в x
:
std::vector<int> y(x.size());
std::iota(y.begin(), y.end(), 0);
auto comparator = [&x](int a, int b){ return x[a] < x[b]; };
std::sort(y.begin(), y.end(), comparator);
Вы можете предоставить свой собственный компаратор, который проверяет значения целевого вектора при сортировке вектора индексов, а такой:
#include <vector>
#include <iostream>
#include <algorithm>
struct IdxCompare
{
const std::vector<int>& target;
IdxCompare(const std::vector<int>& target): target(target) {}
bool operator()(int a, int b) const { return target[a] < target[b]; }
};
int main()
{
std::vector<int> x = {15, 3, 0, 20};
std::vector<int> y;
// initialize indexes
for(size_t i = 0; i < x.size(); ++i)
y.push_back(i);
std::sort(y.begin(), y.end(), IdxCompare(x));
std::cout << "\nvector x: " << '\n';
for(size_t i = 0; i < x.size(); ++i)
std::cout << x[i] << '\n';
std::cout << "\nvector y: " << '\n';
for(size_t i = 0; i < x.size(); ++i)
std::cout << y[i] << '\n';
std::cout << "\nvector x through y: " << '\n';
for(size_t i = 0; i < x.size(); ++i)
std::cout << x[y[i]] << '\n';
}
выход:
vector x:
15
3
0
20
vector y:
2
1
0
3
vector x through y:
0
3
15
20
мы можем взять подход" ссылается " напрямую и использовать массив указателей на значения в исходном векторе.
#include <iostream>
#include <vector>
#include <algorithm>
int main(int argc, const char * argv[]) {
//a source vector, who's order shouldn't be changed
std::vector<int> values = {15, 4, 20, 25, 0, 19, -5};
//a vector of pointers to the values in the source vector
std::vector<int *> pointersToValues;
pointersToValues.reserve(values.size());
for(auto& value : values){
pointersToValues.push_back(&value);
}
//two comparators in form of lambda functions
auto descendingOrderSorter = [](int * i, int * j){
return *i > *j;
};
auto ascendingOrderSorter = [](int * i, int * j){
return *i < *j;
};
//examples of usage
std::cout<<"Sorting in a descending order"<<std::endl;
std::sort( pointersToValues.begin(), pointersToValues.end(), descendingOrderSorter);
for(int i = 0; i < pointersToValues.size(); ++i) {
std::cout << "index: " << i << ", value: " << *pointersToValues[i] << std::endl;
}
std::cout<<"Sorting in an ascending order"<<std::endl;
std::sort( pointersToValues.begin(), pointersToValues.end(), ascendingOrderSorter);
for(int i = 0; i < pointersToValues.size(); ++i) {
std::cout << "index: " << i << ", value: " << *pointersToValues[i] << std::endl;
}
return 0;
}
pointersToValues[i] даст вам указатель на исходное значение, *pointersToValues[i] даст вам значение.
вы можете сделать сортировку в другой список, затем сравнение с несортированным списком, затем 3-й список, где вы можете хранить индексы i.e nlog(n) + n^2
или просто O(n^2)
Примечание: это псевдо код
vector<int> x = {15, 3, 0, 20};
vector<int> y = sort(x);
vector<in> z;
for(int i = 0; y < y.size(); i++){
for(int j = 0; j < y.size(); j++){
if(y[i] == x[j]){
z.push_back(j);
}
}
}