Reputation: 1148
I have a string of words, and they are ranked by relevance. Relevance is a float stored in a separate vector, but I have it that the positions of the two vectors correlate with each other.
float floatTemp1, floatTemp2;
string stringTemp1, stringTemp2;
for(int m=0; m<PlayList.size()-1; m++){
for(int i=0; i<PlayList.size(); i++){
if(storedRelevance[i+1]>storedRelevance[i]){
floatTemp1 = storedRelevance[i];
floatTemp2 = storedRelevance[i+1];
storedRelevance[i]= floatTemp2;
storedRelevance[i+1] = floatTemp1;
stringTemp1 = relevantPlays[i];
stringTemp2 = relevantPlays[i+2];
relevantPlays[i]= stringTemp2;
relevantPlays[i+1]= stringTemp1;
}
}
}
So basically, if the relevance of the vector in position [1] is greater than the relevance of [0], it'll swap the positions of the elements in both the relevance and string vectors. I get a segmentation fault every time I run it.
Upvotes: 1
Views: 214
Reputation: 24269
There are several problems of various levels with your approach.
problem #1, i+1 could exceed PlayList.size().
for ( ... i < storedRelevance.size() ... )
if(storedRelevance[i+1]>storedRelevance[i]){
I think you have the conditions of your m and i loops the wrong way around.
problem #2, you copy both values from one place and then copy them back elsewhere, when you only need to "park" one of them:
floatTemp1 = storedRelevance[i];
floatTemp2 = storedRelevance[i+1];
storedRelevance[i]= floatTemp2;
storedRelevance[i+1] = floatTemp1;
better as
floatTemp = storedRelevance[i];
storedRelevance[i] = storedRelevance[i+1];
storedRelevance[i+1] = floatTemp;
or better still
std::swap(storedRelevance[i], storedRelevance[i+1]);
but again, i+1 could exceed PlayList.size() with your current implementatino.
BIG problem:
stringTemp1 = relevantPlays[i];
stringTemp2 = relevantPlays[i+2];
That +2 seems like ... the wrong string and is definitely going to exceed the array size.
relevantPlays[i]= stringTemp2;
relevantPlays[i+1]= stringTemp1;
I also don't understand the purpose of the outer, "m", loop, other than to make sure that the sort always costs O(N^2) complexity?
If you are simply doing this as an exercise to understand how to implement a sort, you may want to look at one of these alternate approaches:
Method 1: Use a struct/class to give the values locality (this is C++)
struct PlayListSearchResult {
int m_relevance;
const string& m_word; // a reference, so a short lifetime for these objects.
PlayListSearchResult(int relevance_, const std::string& word_)
: m_relevance(relevance_)
, m_word(word_)
{}
};
typedef std::vector<PlayListSearchResult> PlayListSearchResults;
// the sort:
// given PlayListSearchResults results or &results:
const numResults = results.size();
bool needsRedo;
do {
needsRedo = false;
for (size_t i = 0; i < numResults - 1; ++i) {
if (!(results[i + 1].m_relevance < results[i].m_relevance))
continue;
std::swap(results[i], results[i + 1]);
needsRedo = true;
}
} while (needsRedo);
Method 2: Create an array of indexes:
std::vector<size_t> indexes;
for (size_t i = 0; i < results.size(); ++i) {
indexes.push_back(i);
}
// do the sort, but instead of swapping relevance/word, just swap the index.
But otherwise, just look into std::sort or std::map
Upvotes: 0
Reputation: 1028
Your [i+1] and [i+2] index sometime calling somewhere out of your vector storage.
That's why you have segmentation fault.
A better why of doing this is using a struct to encapsulate your data
Struct Play {
float score;
string name;
}
And in your vector, just calling
std::sort(Playlist.begin(), Playlist.end());
std::sort is included in < algorithm>
Upvotes: 1
Reputation: 264739
You could keep the original arrays in their same order but have an indirection that is sorted.
std::vector<int> sorted(PlayList.size());
for(int loop=0;loop < sorted.size();++loop) { sorted[loop] = loop;}
std::sort(sorted.begin(), sorted.end(),
[](int lhs, int rhs){return storedRelevance[lhs]<storedRelevance[rhs]});
// Now you can access your playlist in order via the sorted vector.
// First Item
std::cout << relevantPlays[sorted[0]] << " " << storedRelevance[sorted[0]] << "\n";
Upvotes: 1
Reputation: 7249
use std::map<float, std::string>
because the data is sorted as elements are added.
std::map<float, std::string> relevance_mapping;
std::vector<std::string> words;
std::vector<float> relevance;
//...
for(std::size_t i = 0; i < words.size(); i++) {
relevance_mapping[relevance[i]] = words[i];
}
You can now iterate over relevance_mapping
and you'll get a the data sorted by relevance.
Upvotes: 0
Reputation: 129524
I would suggest that you use a struct
to store all your information about a single thing (e.g. a word, it's relevance, etc), then use std::sort
with a function or functor
that compares the relevance values.
Upvotes: 11