I'd like to know whether there is a way of checking if an element exists or not in the stack.
Assume that the stack interface has push, pop, isEmpty, getTop, member functions.
I know we can do it, if we get the top, compare it with that element and pop it, till it gets empty. But this method would be costy as we'd have to create another stacks to store the pop-ed elements and restore it again.
Here's some pseudo-code for a method that checks for whether or not an element is in the stack:
template<class T>
bool find (stack<T> source, T value)
{
while (!source.isEmpty() && source.top() != value)
source.pop();
if (!source.isEmpty())
return true;
return false;
}
It's critical that the source stack is passed by value, so that it isn't modified. Also, realize that this solution probably isn't as efficient as using a different container than stack and simply calling a method which checks for a value.
Related
I am trying to use tbb’s concurrent_hash_map to increase my application’s concurrent performance. Read up about it and implemented it according to my application but I am seeing crashes..
So, my application is a multi-threadedd application where I am storing pairs,the key is char* and the value is an integer. Pseudocode looks like this:
In .h file,
typedef tbb::concurrent_hash_map<const void*, unsigned, Hasher> tbb_concurrent_hash;
tbb_concurrent_hash concurrent_hash_table;
tbb_concurrent_hash::accessor write_lock;
tbb_concurrent_hash::const_accessor read_lock;
In .c file,
void storeName(const char * name) {
int id=0;
// This creates a pair object of name and index
std::pair object(name, 0);
// read_lock is a const accessor for reading. This find function searches for char* in the table and if not found, create a write_lock.
bool found = concurrent_hash_table.find(read_lock, name);
if (found == FALSE) {
concurrent_hash_table.insert(write_lock, name);
// Get integer id somehow.
id = somefunction();
write_lock->second = id;
write_lock.release();
} else {
// if the name is found in the table then get the value and release it later
id = read_lock->second;
read_lock.release();
}
}
As per my understanding, I am good with the implementation but as I said, there are multiple crashes coming when find returns me FALSE. Crash have traces of mutexs as well.
Your 'locks', i.e. accessors are declared global in .h file. so, basically you write to a shared scoped_lock instance... which logically leads to a data race. Accessors are like fused std::shared_ptr and std::scoped_lock classes in one, or simpler - a pointer for your result and a lock guard for the data it points. You don't want to use one global pointer from multiple threads. Declare them locally in a scope you want to have that access (and you'd not need to call .release() as well)
Another problem is the data race between find() and insert (). Two or more threads can decide that they have to insert since they found nothing. In this case, the first thread will insert the new element while other threads will return existing element because insert() acts as find() if there's existing element. The problem is that your code doesn't account for that.
I can see why you might want to double check using const_accessor as the read lock is more scalable. But instead, you might want to use bool insert( const_accessor& result, const value_type& value ); with read lock (const_accessor) and value_type instead of a key only, which will initialize the whole pair in the case when a new element is added.
I need some general advice about how to go about solving this question without over-complicating it any further:
Using an array (and not a linked list), write a member function of the class StackType that updates the stack when a page is referenced. Assuming a stack that can hold 5 values and the next page referenced is 7 then:
the function searches the stack for page 7
if it finds 7, removes it from stack and places it at the top
if is does not find 7 in the list, the last page referenced in the stack is removed and 7 places on top of the stack
Use the following driver function:
void updateRecursive(StackType<Type>& s, Type t);
that calls the recursive function
bool updateRecursiveDo(StackType<Type>& s, Type t);
What I have done so far and I will only include the relevant functions:
I've used the concept of an LRU algorithm to understand what is being asked here.
I understand that the only tools I really have at my disposal is push and pop.
RE: the driver function concept, I always understood this to be my main() program. i.e. the program that calls the function usually done in the case of testing but based on what they've provided me I looked up this detail in a textbook and found that a public driver function would be used to call a private recursive function to keep the no. of parameters in the public function to a minimum.
class StackType {
public:
void updateRecursive(StackType<Type>& s, Type t);
private:
bool updateRecursiveDo(StackType<Type>& s, Type t);
}
template <class Type>
bool StackType<Type>::updateRecursiveDo(StackType<Type>& s, Type t) {
if (isEmptyStack())
return 0;
else if(s.top() == t) {
return 1;
}
else {
s.pop();
updateRecursiveDo(s,t);
}
}
template <class Type>
void StackType<Type>::updateRecursive(StackType<Type>& s, Type t) {
updateRecursiveDo(s,t);
}
So this is great, I call the function in main as follows and I've searched for the 7 and found it:
firstStack.updateRecursive(firstStack, 7);
Now what I'm doing is overthinking how to go about implementing the replacement of the numbers back onto the stack:
Store each item I pop into an array and iterate through each item then push them back onto the stack in each instance
Manually push the items back onto the stack but this wouldn't really work in the event that 7 didn't exist in the list
I am not sure if there is an easier way to deal with a search and replace when a stack is an array?
Several points of order:
I do not see any reason for your updateRecursiveDo() to return anything, be it a bool, or anything else. As I read your question, the purpose of updateRecursiveDo() is really to remove t from your stack, if it exists. Whether it exists, and this function removes it, or not, no longer matters at that point, because the only remaining step to be done would be to push the t value on top of the rebuilt stack.
And that step would occur whether or not t was found in the stack, so returning a bool indicator is irrelevant.
Furthermore, your implementation fails to return a bool value in the third case, so this wouldn't work anyway.
And your version of your updateRecursiveDo() doesn't do this correctly. Let's explain what your function does to your rubber duck:
if the stack is empty, don't do anything.
if the value on the top of the stack is t don't do anything.
otherwise remove the value from the top of the stack, and try again.
To that, your rubber duck would then ask the following logical question: "why are you removing everything on the stack, until you come to the value t, is that what you want to do?"
Of course not, based on the description you gave of your question. My interpretation of the three bullet points in your question is that only the value t should be removed from the stack, and not every value between the value t, and the end of the stack. Which could be the entire stack, if it doesn't contain the value t!
Now, how about you try explaining the following, instead, to your rubber duck:
If the stack is empty, do nothing.
Remove the value from the top of the stack.
If the value is t, do nothing.
Call itself recursively, and when the recursion call returns, push the value back on top of the current stack.
Translated into code, this would be:
template <class Type>
void StackType<Type>::updateRecursiveDo(StackType<Type>& s, Type t)
{
if (isEmptyStack())
return;
auto v=s.top();
if (v == t)
return;
updateRecursiveDo(s, t);
s.push(v);
return;
}
template <class Type>
void StackType<Type>::updateRecursive(StackType<Type>& s, Type t)
{
updateRecursiveDo(s, t);
s.push(t);
}
Think of updateRecursiveDo() as a method to delete an element from a stack. If the element is not found, remove the last one.
And after exit, push t to the top.
You're not replacing t but deleting it, then adding it again.
Use each recursive frame to temporally store the popped value in an internal variable, ie:
Pseudocode:
updateRecursiveDo(stackt stack, page t){
x=stack.pop();
if (x==t) return;
if (stack.empty()) return;
updateRecursiveDo(stack,t);
stack.push(x);
}
I'm working on a project that needs unique keys and values so I decided to use maps. Everything works expect for the case where someone may want to change the key value. I'm not sure why, but it causes a fragmentation fault. Can I not do this?
void Journal::set_id(int id){ // journal class
if(join.count(id)){ // join is: static map <int,string> join
cout<<"Journal ID is already being used. Try again."<<endl;
}
else {
join.erase (join.find(id));
join.insert(pair<int,string>(id,name));
}
}
Your logic is flawed.
void Journal::set_id(int id){
if(join.count(id)){
cout<<"Journal ID is already being used. Try again."<<endl;
}
else {
// When you hit this block of the code, there is nothing
// in the map corresponding to 'id'.
// join.find(id) returns the same iterator as join.end()
// Calling erase() with that iterator is causing you the
// problem.
// Don't call erase. Just insert the new item.
// join.erase (join.find(id));
join.insert(pair<int,string>(id,name));
}
}
You have just checked to make sure that id is not being used as a key in the map. If it is, you issue an error. So now you know that id is not in the map. If id is not in the map, join.find(id) will return join.end(), so you really didn't need to call find at all. But more importantly, you then call join.erase(join.end()), which is an error.
See documention for std::map::erase() in cppreference:
The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferencable) cannot be used as a value for pos.
Rather than check whether the key is present, and insert it only if not found, you can simplify the code by just inserting the item, and then checking the return value to see if the insertion succeeded (which it won't if that key was already present).
void Journal::set_id(int id){
if (!(join.insert(std::make_pair(id, name)).second))
cout<<"Journal ID is already being used. Try again."<<endl;
}
This should also improve speed, since it only searches the tree once whereas code doing a count then an insert has to search it twice.
I am currently using tbb's concurrent hash map to perform concurrent insertions into a hash map. Each key is a string and a value is a vector of integers. I would like to achieve the following: during insertions, if the key does not exist, I insert it and add the value to its vector. If it exists, I simply add the value to its vector.
After inspecting the tbb concurrent hash map API, I noticed that both the find and insert functions return booleans only. So how can I return a pointer to the key if it exists?
There are methods which require an accessor in theirs arguments. The accessor is basically a pointer coupled with a scoped_lock protecting concurrent access to the element. Without the lock, an element can be modified concurrently resulting in a data-race. So, never use a pointer to element in concurrent_hash_map directly (unless protected by the accessor).
Also, you don't need a find() method for your task since insert() methods create the element if it does not exist.
According to the Reference manual, the hash map has the following methods which will likely satisfy your needs:
bool insert( accessor& result, const Key& key ); // creates new element by default
bool insert( accessor& result, const value_type& value );// creates new element by copying
Here is an example:
{
hash_map_t::accessor a;
hash_map.insert( a, key ); // creates by default if not exists, acquires lock
a->second.my_vector.push_back( value ); // new or old entry, add to vector anyway
} // the accessor's lock is released here
During insertions, if the key does not exist then key inserted and added the value to its vector.
If it exists, return false and I simply add the value to its vector.
{
hash_map_t::accessor accessor;
bool result = hash_map.insert(accessor, std::make_pair(key, {value})); // creates by default if not exists, acquires lock
if(result == false)
accessor->second.push_back(value); // if key exists
} // the accessor's lock is released here
I'm currently learning C++ and practicing my Knowledge by implementing an simple AddressBook Application. I started with an Entry class and an AddressBook class which implements a STL Map to access the entries by the last names of the persons. Now I arrived at the following code:
Entry AddressBook::get_by_last_name(string last_name){
if(this->addr_map.count(last_name) != 0){
//What can I do here?
} else {
return addr_map[last_name];
}
In Scripting Languages I would just return something like -1, Error Message(A List in Python) to indicate that the Function failed. I don't want throw an exception, because it's part of the application logic. The Calling Class should be able to react to the request by printing something on the console or opening a Message Box. Now I thought about implementing the Scripting Languae Approach in C++ by introducing some kind of an Invalid State to the Class Entry. But isn't that bad practice in C++? Could it be that my whole class design is just not appropriate? I appreciate any help. Please keep in mind that I'm still learning C++.
Some quick notes about your code:
if(this->addr_map.count(last_name) != 0){
//What can I do here?
You probably wanted it the other way:
if(this->addr_map.count(last_name) == 0){
//handle error
But your real problem lies here:
return addr_map[last_name];
Two things to note here:
The operator[] for map can do 2 things: If the element exists, it returns it; If the element doesn't exist, it creaets a new (key,value) pair with the specified key and value's default constructor. Probably not what you wanted. However, if your if statement from before would have been the right way, then the latter would never happen because we would knowthe key exists before hand.
In calling count() before, you effectively tell map to try and find the element. By calling operator[], you are telling map to find it again. So, you're doing twice the work to retrieve a single value.
A better (faster) way to do this involves iterators, and the find method:
YourMap::iterator it = addr_map.find(last_name); //find the element (once)
if (it == addr_map.end()) //element not found
{
//handle error
}
return *it.second; //return element
Now, back to the problem at hand. What to do if last_name is not found?
As other answers noted:
Simplest solution would be to return a pointer (NULL if not found)
Use boost::optional.
Simply return the YourMap::iterator but it seems that you are trying to "hide" the map from the user of AddressBook so that's probably a bad idea.
throw an exception. But wait, now you'll have to first check that calling this method is 'safe' (or handle the exception when appropriate). This check requires a boolean method like lastNameExists which would have to be called before calling get_by_last_name. Of course then we'er back to square 1. We're performing 2 find operations to retrieve a single value. It's safe, but if you're doing A LOT of calls to get_by_last_name then this is potentially a good place to optimize with a different solution (besides, arguably the exception is not very constructive: What's wrong with searching for something that isn't there, huh?).
Create a dummy member for Entryindicating that is not a real Entry but that is very poor design (unmanageable, counter intuitive, wasteful - you name it).
As you can see, the first 2 solutions are by far preferable.
One dead-simple option is to change the return type to Entry* (or const Entry*) and then return either the address of the Entry if found, or NULL if not.
If you use Boost, you could return a boost::optional<Entry>, in which case your success code would be the same, but on not-found you'd say return boost::none. This is fancier, but does about the same thing as using a pointer return type.
Throwing an exception is definitely the 'correct' C++ thing to do, based on your function return type.
You might want a function like this to help you, though:
bool AddressBook::lastNameExists(const string &last_name)
{
return addr_map.count(last_name) > 0;
}
Note that your current code returns the entry 'by value' so modifying the returned entry won't update the map. Not sure if this is by accident or design...
Other answers have given various approaches, most of them valid. I didn't see this one yet:
You could add a second parameter with a default value:
Entry AddressBook::get_by_last_name(string last_name, const Entry& default_value){
if(this->addr_map.count(last_name) == 0){
return default_value;
} else {
return addr_map[last_name];
}
In this particular instance, there might not be a sensible default value for a non-existing last name, but in many situations there is.
In C++ you have several ways of signalling that an issue happened in your function.
You can return a special value which the calling code will recognize as an invalid value. This can be a NULL pointer if the function should return a pointer, or a negative value if your function returns an index in an array, or, in the case of a custom class (e.g. your Entry class) you can define a special Entry::invalid value or something similar that can be detected by the calling function.
Your calling code could look like
if ( entryInstance->get_by_last_name("foobar") != Entry::invalid)
{
// here goes the code for the case where the name is valid
} else {
// here goes the code for the case where the name is invalid
}
On the other hand you can use the C++ exceptions mechanism and make your function throw an exception. For this youcan create your own exception class (or use one defined in the standard library, deriving from std::exception). Your function will throw the exception and your calling code will have to catch it with a try...catch statement.
try
{
entryInstance->get_by_last_name("foobar")
}
catch (Exception e)
{
// here goes the code for the case where the name is invalid
}
// here goes the code for the case where the name is valid
Apart from the fact that you could have more than one entry per surname.
Eliminate the getter, and you've solved the problem, or at least shifted it elsewhere.
Tell the AddressBook to display people with given surnames. If there aren't any it can do nothing.
AddressBookRenderer renderer;
AddressBook contacts;
contacts.renderSurnames("smith", renderer);
contacts.renderCompletions("sm", renderer);
//etc
You can do what std::map (and the other containers do).
You return an iterator from your search function.
If the search does not find a value that is useful return an iterator to end().
class AddressBook
{
typedef <Your Container Type> Container;
public:
typedef Container::iterator iterator;
iterator get_by_last_name(std::string const& lastName) {return addr_map.find[lastName];}
iterator end() {return addr_map.end();}
};
Your address book is a container like object.
Not finding an item in a search is likely to happen but it does not have enough context to incorporate error handling code (As the address book could be used from lots of places and each place would have different error handling ideas).
So you must move the test for not found state out of your address book.
just like "Python" we return a marker. In C++ this is usually an iterator to end() which the calling code can check and take the appropriate action.
AddressBook& ab = getAddressBookRef();
AddressBook::iterator find = ab.get_by_last_name("cpp_hobbyist");
if (find != ab.end())
{
Entity& person *find; // Here you have a reference to your entity.
// you can now manipulate as you want.
}
else
{
// Display appropriate error message
}