2016-05-03 82 views
6

使用另一這意味着,當我在非遞增順序排序的V2,V1的應該是這樣的一個載體:排序在非增順序

載體看起來如下。

v1 = {0, 5, 5, 2, 10}; 
v2 = {0 ,2, 6, 20, 5}; 

輸出:

v1 = {2, 5, 10, 5, 0}; 
v2 = {20, 6, 5, 2, 0}; 

我試圖解決這個問題混合std::sort和lambda表達式。 這就是爲什麼我讀了幾個關於std::sort的問題,沒有解決類似於我的問題的答案,所以這就是我問的原因。

我對包含C++ 11和C++ 14的用法或其他特性的答案特別感興趣。

它不是這樣的問題:

「我完全不知道該怎麼辦。」

我知道如何使用C++ 98來實現輸出,但我想知道是否有更高效更漂亮的方法來實現它。

非常感謝您的幫助:)

+5

你的C++ 98代碼是什麼樣的? –

+1

您的輸出v2有一個較少的元素 –

+0

那麼我說我知道如何在C++ 98中實現它我沒有說我得到了代碼。這個想法是存儲索引,這些索引被移動到v2排序並使用這些索引來排序v1。 – FieryCod

回答

9

你可以zipsortunzip

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

//converts two vectors into vector of pairs 
template <typename T, typename U> 
auto zip(T t, U u) { 
    std::vector<std::pair<typename T::value_type,typename U::value_type>> pairs; 
    for (size_t i = 0; i < t.size(); ++i){ 
    pairs.emplace_back(u[i],t[i]); 
    } 
    return pairs; 
} 

//converts a vector of pairs, back into two two vectors 
template <typename T, typename U, typename V> 
void unzip(V pairs, T & t, U & u) { 
    for (auto const& it: pairs){ 
    u.emplace_back(it.first); 
    t.emplace_back(it.second); 
    } 
} 


int main(){ 

    //vectors 
    std::vector<int> v1 = {0, 5, 5, 2, 10}; 
    std::vector<int> v2 = {0 ,2, 6, 20, 5}; 

    //zip vectors 
    auto pairs = zip(v1,v2); 

    //sort them 
    std::sort(pairs.begin(),pairs.end(),std::greater<>()); 

    //unzip them 
    v1.clear(); 
    v2.clear(); 
    unzip(pairs,v1,v2); 

    //print 
    std::cout << '\n'; 
    for (auto i: v1) std::cout << i << ' '; 
    std::cout << '\n'; 
    for (auto i: v2) std::cout << i << ' '; 
    std::cout << '\n'; 

} 
+0

非常感謝您的回答,它是一個純金。 – FieryCod

+0

如果沒有顯式的模板參數,'std :: greater <>()'是如何工作的? 「較大」模板是否有一個默認參數,允許它更通用? –

+0

@AaronMcDaid來自C++ 14的void specialization。默認類型是void,並且推導參數和返回類型。 –

3

好吧,我不,如果這將是有效的,或沒有,但這個說明了如何使用std::generatestd::sortstd::transform做到這一點,與可變lambda表達式和迭代器一些額外的調味料。

#include <algorithm> 
#include <iostream> 

int main() 
{ 
    std::vector<int> v1={0, 5, 5, 2, 10}, 
     v2 = {0, 2, 6, 20, 5}; 

    std::vector<int> index; 

    index.resize(5); 

    std::generate(index.begin(), index.end(), 
       [n=0] 
      () 
       mutable 
       { 
        return n++; 
       }); 

    std::sort(index.begin(), index.end(), 
      [&] 
      (auto &a, auto &b) 
      { 
       return v2[b] < v2[a]; 
      }); 

    std::vector<int> v1_out, v2_out; 

    std::transform(index.begin(), index.end(), 
       std::back_insert_iterator<std::vector<int>>(v1_out), 
       [&] 
       (auto a) 
       { 
        return v1[a]; 
       }); 

    std::transform(index.begin(), index.end(), 
       std::back_insert_iterator<std::vector<int>>(v2_out), 
       [&] 
       (auto a) 
       { 
        return v2[a]; 
       }); 

    for (auto n: v1_out) 
     std::cout << n << ' '; 
    std::cout << std::endl; 

    for (auto n: v2_out) 
     std::cout << n << ' '; 

    std::cout << std::endl; 
} 
+5

而不是生成+可變lambda,std :: iota從 galop1n

+0

感謝您的負擔;) – FieryCod

+0

有趣的設計,儘管我發現'std :: back_inserter'比原始'std :: back_insert_iterator '更具可讀性。 – Hiura

1

非常感謝您的答案。我找到了一個簡單的方法來達到同樣的效果,並且這個想法來自this answer

1. 首先我用從答案我鏈接的所有代碼,所以它是:

template <typename T> 
vector<size_t> sort_indexes(const vector<T> &v) 
{ 

    // initialize original index locations 
    vector<size_t> idx(v.size()); 
    for (size_t i = 0; i != idx.size(); ++i) idx[i] = i; 

    // sort indexes based on comparing values in v 
    sort(idx.begin(), idx.end(), 
     [&v](size_t i1, size_t i2) 
     { 
     return v[i1] >= v[i2]; 
     }); 

    return idx; 
} 

2.然後我確實將排序的第一和第二向量使用第三one.To的函數實現它我不得不爲第一個向量創建一個臨時向量,爲第二個向量創建臨時向量,並且爲最後一個創建臨時向量兩個

爲什麼兩個 因爲我必須記住第三個向量的排序索引,我需要一個臨時的,我將按照排序後的索引來推送原始第三個向量的元素。

void SortByIndexes(vector<int>& Pi,vector<int> &Wi,vector<int>& PidivWi) 
    { 

     vector<int> Pitemp, Witemp, PidivWitemp,SortedIndexes; 

     for (auto i : sort_indexes(PidivWi)) 
     { 

     SortedIndexes.push_back(i); 

     } 

    for (auto i : SortedIndexes) 
     { 
     Pitemp.push_back(Pi[i]); 
     Witemp.push_back(Wi[i]); 
     PidivWitemp.push_back(PidivWi[i]); 
     } 

     swap(Pi, Pitemp); 
     swap(Wi, Witemp); 
     swap(PidivWi,PidivWitemp); 

    } 

3.排序後只是交換排序的向量與原來的。 完成。

謝謝大家。

+0

是的,這正是要走的路(如果它缺乏的話,本來應該是我的答案)。 – davidhigh