2011-07-28 33 views
5

我想使用另一個向量v2對向量v1進行排序。而這段代碼運行使用函數對象的向量上的C++排序

terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Abort trap

:我不能換我的頭周圍此錯誤

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

class Comp 
{ 
    public: 
     Comp(vector<double>& inVec): _V(inVec) {} 
     bool operator()(int i, int j) {return (_V.at(i)<_V.at(j));} 
    private: 
     vector<double> _V; 
}; 

int main(int argc, char** argv) 
{ 
    double x1[] = {90.0, 100.0, 80.0}; 
    double x2[] = {9.0, 3.0, 1.0}; 
    vector<double> v1(x1,x1+3); 
    vector<double> v2(x2,x2+3); 

    sort(v1.begin(), v1.end(), Comp(v2)); // sort v1 according to v2 

    for(unsigned int i=0; i<v1.size(); i++) 
    { 
     cout << v1.at(i) << " " << v2.at(i) << endl; 
    } 

    return 0; 
} 

v1v2大小相同的。爲什麼out_of_range錯誤?

在此先感謝任何指針。

+2

您的'Comp'類應該保存對矢量的引用,而不是將其複製。 – Tim

回答

9

我相信,你的問題是在這條線:

bool operator()(int i, int j) {return (_V.at(i)<_V.at(j));} 

的問題是,當std::sort算法採用的是定製的回調,它通過存儲在vector在特定的位置,而不是實際值指數vector內的那些位置。其結果是,當你調用

sort(v1.begin(), v1.end(), Comp(v2)); // sort v1 according to v2 

你寫將會得到作爲參數傳遞存儲在v1矢量值,然後會在那些位置到v2矢量嘗試索引Comp比較。由於v1中的值大於v2的大小,因此調用_V.at(i)將導致引發out_of_range異常。

如果您想對兩個範圍相互進行排序,您需要採用不同的方法。我不知道這樣做的直接方式,但如果我想到一個,我會告訴你。

6

v1的尺寸只是3,但是您使用v2的每個值作爲v1的索引。而作爲v2有一個值9這比v1尺寸更大,這是什麼讓這裏std::out_of_range錯誤:

bool operator()(int i, int j) {return (_V.at(i)<_V.at(j));} 

std::vector::at函數給出std::out_of_range例外,傳遞給它的指數作爲參數比規模更大的矢量。也就是說,該指數必須小於vector::size()

4

就像在其他答案中說的那樣,問題是排序算法會傳遞實際值來比較而不是索引。

這裏是你如何解決這個問題:

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

using namespace std; 

typedef pair<double, double> Zipped; // Represent an element of two lists 
            // "zipped" together 

// Compare the second values of two pairs 
bool compareSeconds (Zipped i, Zipped j) 
{ 
    return i.second < j.second; 
} 

int main (int argc, char **argv) 
{ 
    double x1[] = { 90, 100, 80 }; 
    double x2[] = { 9, 3, 1 }; 

    vector<double> v1(x1, x1 + 3); 
    vector<double> v2(x2, x2 + 3); 

    vector<Zipped> zipped(v1.size()); // This will be the zipped form of v1 
             // and v2 

    for (int i = 0; i < zipped.size(); ++i) 
    { 
     zipped[i] = Zipped(v1[i], v2[i]); 
    } 

    sort(zipped.begin(), zipped.end(), &compareSeconds); 

    for (int i = 0; i < zipped.size(); ++i) 
    { 
     cout << zipped[i].first << " " << zipped[i].second << endl; 
    } 

    for (int i = 0; i < v1.size(); ++i) 
    { 
     v1[i] = zipped[i].first; 
    } 

    // At this point, v1 is sorted according to v2 

    return 0; 
} 
4

好了,現在你可能知道的事實,即ijvector,而不是持有指數實際值。有一個很好的理由:排序是關於值而不是索引。請注意,您正在將迭代器傳遞給sort方法,因此它無法爲您提取索引。當然,你可以得到相對於第一個迭代器的索引,但是沒有理由這樣做。

但是,讓我們瘋狂一段時間吧,想象一下你會在比較器中獲得索引而不是數值。假設你的代碼,你想要做什麼,讓我們想想以下情形:

v1 = {20,10}; v2 = {2,1}

我暗暗想,你希望下面的輸出:

v1 = {10, 20}

吧?現在想象一下,我是一個排序函數你打電話,我做以下步驟:

  • v2[0] < v2[1]是假的,所以swap(&v1[0], &v1[1])

它的排序,是不是?別急,我是一個瘋狂的排序功能,所以我想確保它的排序,所以我做到以下幾點:

  • v2[0] < v2[1]是假的,swap(&v1[0], &v1[1])

並再次:

  • v2[0] < v2[1]是假的,swap(&v1[0], &v1[1])

一而再,再,再一次......

你能看到一個問題嗎?排序功能有一些要求,並確保你打破基本。

我懷疑你需要完全不同的容器(也許std::mapvec1鍵和值從vec2),或者至少像vector< pair<double, double> >,讓您輕鬆排序第一或第二值。如果不是,請考慮創建vector,其值爲[0, v2.size()),使用比較器對值進行排序(值等於索引,因此將會正常),然後從v1中打印正確的值。此代碼正常工作:

vector<size_t> indices; 
for(size_t i =0; i < v1.size(); ++i) 
{ 
    indices.push_back(i); 
} 

// yes, it works using your original comparator 
sort(indices.begin(), indices.end(), Comp(v2)); 

for(size_t i =0; i < indices.size(); ++i) 
{ 
    cout << v1.at(indices[i]) << " " << v2.at(indices[i]) << endl; 
} 
+0

+1給出真正的原因,而不是僅僅說'std :: sort'使用值而不是索引。 – leftaroundabout