Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 days ago.
Improve this question
I have a vector of custom objects and am required to sort it under various criteria(i.e. cannot use set). I also have a comparator to do the sorting, which forces me to use a vector of pointers. This way, the code compiles but it is now failing to remove duplicates.
vector<customObj*> vec;
//code to remove duplicate
vector<customObj*>::iterator it;
it = unique(vec.begin(), vec.end());
vec.resize(distance(vec.begin(), it));
//code to sort a vector
bool Comp(customObj *a, customObj *b) {
if (condition) {
return (a->getValue() < b->getX=Value());
}
}
It seems there is a typo in the comparison function
//code to sort a vector
bool Comp(customObj *a, customObj *b) {
if (condition) {
return (a->getValue() < b->getX=Value());
^^^^^^^^^^^^^^^^
}
}
Also the comparison function returns nothing if the condition does not evaluate to true.
I think you mean
//code to sort a vector
bool Comp(customObj *a, customObj *b) {
return condition && (a->getValue() < b->getValue());
}
In the call of std::unique you need to use a binary predicate like
//code to sort a vector
bool Equal(customObj *a, customObj *b) {
return consdition && (a->getValue() == b->getValue());
}
vector<customObj*>::iterator it;
it = unique(vec.begin(), vec.end(), Equal);
vec.resize(distance(vec.begin(), it));
Pay attention to that if objects in the vector were dynamically allocated then you need to free them. Otherwise you will have memory leaks.
Instead of raw pointers you should use smart pointer std::unique_ptr.
Related
I am using a vector to map source line numbers to code addresses. It looks like if the address argument is higher than the highest in the table, the iterator points to the next, non-existing element. For error protection, I want to disallow out-of-range input arguments. Is there a more elegant method, than I use below?
findLinenoToAddress(unsigned int A)
{
if (A > AddressToLineMap[AddressToLineMap.size()-1]->Address)
A = AddressToLineMap[AddressToLineMap.size()-1]->Address;
std::vector<AddressToLineRecord*>::const_iterator it;
for(it = AddressToLineMap.begin(); it != AddressToLineMap.end(); it+=1)
{
if ((*it)->Address >= A)
break;
}
return (*it)->Lineno;
}
Indeed, as AndyG commented, your code suggests that the vector is sorted.
Because of this you should really use a binary search algorithm:
https://en.wikipedia.org/wiki/Binary_search_algorithm,
Where can I get a "useful" C++ binary search algorithm?
That is the reason why the current code is slow and definitely should not be used.
But trying to answer the exact question the minimal changes to your code could be like this (note checking for emptiness and immediate returns from ifs):
int findLinenoToAddress(unsigned int A)
{
if (AddressToLineMap.empty())
return 0;
if(A>AddressToLineMap[AddressToLineMap.size()-1]->Address)
return AddressToLineMap[AddressToLineMap.size()-1]->Lineno;
std::vector<AddressToLineRecord*>::const_iterator it;
for(it = AddressToLineMap.begin(); it != AddressToLineMap.end(); it+=1)
{
if((*it)->Address >= A) break;
}
return (*it)->Lineno;
}
The other method is to use a „sentinel”:
https://en.wikipedia.org/wiki/Sentinel_node
This method needs that you warrant that your vector ALWAYS has additional item at its end with UINT_MAX as Address (also it means that it is never empty).
Then the code could look like this:
int findLinenoToAddress(unsigned int A)
{
std::vector<AddressToLineRecord*>::const_iterator it;
for(it = AddressToLineMap.cbegin(); it != AddressToLineMap.cend(); it++)
{
if((*it)->Address >= A)
return (*it)->Lineno;
}
throw "an unreachable code";
}
This code should be greatly improved by using find_if:
Using find_if on a vector of object, but it will be as slow as other examples here.
So again - choose binary search instead.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am writing two functions, the first one does a linear search and is supposed to return the position of the first found value if it is in the vector. The second method is a binary search that is done using equal_range and it is supposed to return the same thing as the linear search. Currently they are checking every value as a match. Any help is appreciated.
int linearSearch( const vector<int>& vec, int z)
{
vector<int>::iterator iter = find(vec.begin(), vec.end(), z);
if (iter != vec.end())
return (iter-vec.begin());
else
return -1;
}
int binarySearch( const vector<int>& vec, int z)
{
pair<vector<int>::const_iterator, vector<int>::const_iterator> bounds;
bounds = equal_range(vec.begin(),vec.end(), z);
if (bounds.first != vec.end())
return (bounds.first -vec.begin());
else
return -1;
}
Your description is unclear, but I'll point out some concerns with the code.
In binarySearch() search, there is
bounds = equal_range(vec.begin(),vec.end(), z);
if (bounds.first != v.end())
return (bounds.first -v.begin());
v is not declared anywhere. If the code compiles then, presumably, it is declared somewhere in code you haven't shown. But it may have no relationship to vec. The behaviour of the code (particularly the return) will be undefined.
A rather fundamental difference between the functions is because std::equal_range() assumes a sorted (or partitioned) range, and std::find() does not.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Basically I have a edgeCostMap of type
map<pair<int, float>, int>
and a vector of 42 vertices. I loop through the vector of vertices and add values to the map as follows:
for(int vertexIndex = 0; vertexIndex < V.size(); vertexIndex++)
{
pair<int, float> toAdd;
toAdd.first = vertexIndex;
toAdd.second = V[vertexIndex].edgeCollapseCost;
edgeCostMap[toAdd] = vertexIndex;
}
However after the loop has been finished and I print out the map contents as follows:
for(map<pair<int, float> ,int>::iterator it = edgeCostMap.begin(); it != edgeCostMap.end(); it++)
{
logFile<<"Vertex "<<it->second<<" has cost "<<it->first.second<<" has "<<mapVF[it->second].size()<<"neighbors"<<endl;
}
I only get back 12 statements. Is my mapping done incorrectly?
Compare function:
class comparator {
public:
bool operator()(const std::pair<int, float>& a, const std::pair<int, float>& b) const {
return a.second < b.second;
}
};
Your comparator considers two keys equal (neither less than the other) if their floats are equal. You cannot put two equal keys in a map. You probably want to use the default comparator but put the float first in the set. This will sort first on the float and second on the integer, ensuring the keys are not equal if their integers differ.
This question already has answers here:
Performance issue for vector::size() in a loop in C++
(10 answers)
Closed 8 years ago.
When i looked at the typical way of iterating through a vector...
for (size_t i = 0; i < my_vector.size(); i++)
{
doSomething(my_vector[i]);
}
...i thought it might be faster this way...
size_t i = 0, size = my_vector.size();
for (i; i < size; i++)
{
doSomething(my_vector[i]);
//I know, the size of the vector must not be changed here
}
...because size() will be called only once and not every loop.
Maybe somebody is able to make this clear for me, Thanks!
P.S. Should i use std::vector::iterator?
(sry for bad english)
That might well be faster, but since you're using C++, an alternative might be to use an iterator instead:
// declare it to be some appropriate type of iterator
for (it = my_vector.begin(); it != my_vector.end(); ++it)
doSomething(*it);
You will want to be careful here, though, that you're not inadvertently constructing temporary copies of each item in my_vector.
If you're using C++11, another option is to use range-for:
for (const auto &thing : my_vector)
doSomething(thing);
Note that the use of const and & mean that we avoid copying each item in my_vector.
If you don't want to modify the elements, you can try this:
for (const auto &elem : my_vector)
{
//
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Is there a code that will check if a certain string is inside an array?
For example I have a string "John" then I need to check if "John" is already in the array names[10].
std::find does exactly that:
auto i = std::find(std::begin(a), std::end(a), "John");
if (i != std::end(a)) … // item found!
However, beware that this does a linear pass over the elements. That’s not a problem for 10 items but it becomes inefficient quickly with larger number. For very large sets, use std::unordered_set instead of an array, to attain (theoretically) constant runtime. Alternatively, if you know that the array is sorted you may employ std::binary_search to attain logarithmic runtime.
Here’s the same code, wrapped inside a convenience function:
template <typename It, typename T>
bool contains(It begin, It end, T const& value) {
return std::find(begin, end, value) != end;
}
And here’s a convenience overload for C arrays:
template <typename T, typename U, std::size_t N>
bool contains(T (&arr)[N], U const& value) {
return std::find(arr, arr + N, value) != arr + N;
}
(The syntax for passing arrays to functions is a bit weird.)
If you want to go archaic:
function in_array(String my_array[], String findthis){
len=sizeof my_array;
for(int i=0;i<len;i++){
if(my_array[i]==findthis){
return true;
}
}
return false;
}
then
in_array(array_of_strings, "john");
I wrote this hastily and I'm very tired, but hopefully it can be of some use.