Reputation: 87
So I have created a binary search tree that is stored within an array. This binary search tree (BST) stores a user input ID, Age, and Name, then places it within the array sorted in ascending order by the ID.
I'm attempting to write a delete function that takes a user input ID, loops through the vector, and if it finds a matching ID, it deletes it.
However, I can't seem to get BinaryTree.erase() to work due to an error.
Severity Code Description Project File Line Suppression State Error (active) E0304 no instance of overloaded function "std::vector<_Ty, _Alloc>::erase [with _Ty=Node, _Alloc=std::allocator]" matches the argument list Project_4CS210
After erasing, I plan on organizing the vector so that there aren't any open spots, however, I want to make sure that I can delete the node first. Any suggestions? I am a beginner, so most of this is rather new to me.
Here's my delete function.
#include "BinaryTree.h"
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int index;
struct Node
{
int ID;
int age;
string name;
Node()
{
}
Node(int id, int Age, string nm)
{
this->ID = id;
this->age = Age;
this->name = nm;
}
};
vector<Node> binaryTree;
void BST::Delete()
{
int input_id;
cout << "What is the ID of the person to be deleted" << endl;
cin >> input_id;
for (unsigned int i = 0; i < binaryTree.size(); i++)
{
if (input_id == binaryTree.at(i).ID)
binaryTree.erase(i);
}
}
Upvotes: 2
Views: 2368
Reputation: 504
Considering you wish to remove all the items in the vector or a specific item. You can actually erase items from a vector using erase
while iterating. Keep in mind the erase
actually provides you with the iterator to the next item. So you may not need to increment the iterator unless it fulfills the condition.
Here is a sample code:
for (std::vector<Node>::iterator it = binaryTree.begin(); it != binaryTree.end();)
{
if(it == yourItem) //Conditional check if it matches with your object.
{
it = binaryTree.erase(it);
}
else
{
++it;
}
}
You can see that i am actually getting the iterator to the next item in the list without incrementing it. You can process it in whatever way you may like.
Upvotes: 0
Reputation: 6317
std::vector::erase
takes an iterator, not an index.
You can use binaryTree.begin() + i
to get the iterator for the i-th element of a vector (note that some containers have iterator types without +
, so you'd need to use std::advance
there).
Overall, binaryTree.erase(binaryTree.begin() + i)
should do the job you want, but for what you are trying to do you could also look into std::remove_if
.
To expand on this last point (because someone in the comments mentioned the remove/erase idiom):
vector.erase(std::remove_if(vector.begin(),
vector.end(),
[](const auto& element) { return condition(element); }),
vector.end());
This will remove all elements from the vector where condition(element)
returns true
, and is generally better than iterating over the vector by hand:
If you want to remove more than one element with your method, you might miss some. Take a vector where the elements you want to remove are at indices i
and i + 1
. Then, you remove the element at index i
normally, and the element at i + 1
moves to index i
- however, in the next iteration you already check index i + 1
, so you miss the item that you wanted to remove
Each time you remove an element from the vector, all the elements behind that are moved around in memory. If your items are fairly big, that can be expensive. Using remove_if
should ensure that each element isn't moved more than necessary, which can be more efficient especially if you remove many elements.
Upvotes: 4
Reputation: 1374
You shouldn't remove elements from vector while iterating over it, you can miss some indexes while iterating, use std::remove_if
to send elements needed to remove at the end of vector and then erase them from vector with erase()
method:
auto It = std::remove_if(binaryTree.begin(), binaryTree.end(), [input](const Node& node)
{
if( node.ID == input )
{
return true;
}
return false;
});
binaryTree.erase(It,binaryTree.end());
Method erase()
accepts iterators to remove range or one iterator to remove one element. std::remove_if
will return iterator for the first elements pushed at the end to remove.
Upvotes: 3