I have a simple digital tree defined as below:
class DTN {
public:
DTN () :
is_word(false), word_to_here(""), children()
{}
DTN (bool iw, std::string wth) :
is_word(iw), word_to_here(wth), children()
{}
bool is_word;
std::string word_to_here;
Map<char,DTN> children;
};
I am having problem to define a function called longest_word (const DTN& dtn) which is suppose to return the longest word in the digital tree with iterator and recursion, shown as follow:
std::string longest_word (const DTN& dtn) {
std::string lw = dtn.word_to_here;
for(auto s:dtn.children){
if(s.second.is_word && lw.length()<s.second.word_to_here.length()){
lw = longest_word(s.second);
}
longest_word(s.second);
}
return lw;
}
Assume we have three words in a digital tree DTN: (ante, anteater, anthebellum), and calling the longest_word(DTN) will give me an empty string "" instead of "anthebellum". Can someone please point out what I did wrong in the longest_word function? With actual code will be appreciated because my English is not good, codes are easier for me to understand. Thanks in advance.
The algorithm for longest_word is completely wrong. You should inspect all children longest_words and return the one which is longer. You cannot return before the loop on children is complete. Notice that your algorithm will always return on first children. I don't even understand why you check for a complete word there...
I could try to write the correct code but I feel it is not useful to you. My suggestion is to get back to simplest algorithms like finding the maximum number in a list of integers.
Related
CppCheck suggest me to replace one of my code by a STL algorithm, I'm not against it, but I don't know how to replace it. I'm pretty sure this is a bad suggestion (There is warning about experimental functionalities in CppCheck).
Here is the code :
/* Cutted beginning of the function ... */
for ( const auto & program : m_programs )
{
if ( program->compare(vertexShader, tesselationControlShader, tesselationEvaluationShader, geometryShader, fragmentShader) )
{
TraceInfo(Classname, "A program has been found matching every shaders.");
return program;
}
}
return nullptr;
} /* End of the function */
And near the if condition I got : "Consider using std::find_if algorithm instead of a raw loop."
I tried to use it, but I can't get the return working anymore... Should I ignore this suggestion ?
I suppose you may need to use that finding function not once. So, according to DRY, you need to separate the block where you invoke an std::find_if algorithm to a distinct wrapper function.
{
// ... function beginning
auto found = std::find_if(m_programs.cbegin(), m_programs.cend(),
[&](const auto& prog)
{
bool b = prog->compare(...);
if (b)
TraceInfo(...);
return b;
});
if (found == m_programs.cend())
return nullptr;
return *found;
}
The suggestion is good. An STL algorithm migth be able to choose an appropriate
approach based on your container type.
Furthermore, I suggest you to use a self-balancing container like an std::set.
// I don't know what kind of a pointer you use.
using pProgType = std::shared_pointer<ProgType>;
bool compare_progs(const pProgType &a, const pProgType &b)
{
return std::less(*a, *b);
}
std::set<std::shared_pointer<prog_type>,
std::integral_constant<decltype(&compare_progs), &compare_progs>> progs.
This is a sorted container, so you will spend less time for searching a program by a value, given you implement a compare operator (which is invoked by std::less).
If you can use an stl function, use it. This way you will not have to remember what you invented, because stl is properly documented and safe to use.
the search function will take in a key value which is a const string& and it will look in the hashtable to see if the key value item is found or not..
my code here works except for a few cases (for example when i pass in "ZZ0" in to the function).
not sure if its because i'm using == instead of strcmp
But i can't see why it would not work simply because of that. can someone please explain if i'm missing something here?
void HT::search(const string& item)
{
int index=hash(item);
bool found=false;
for(unsigned int i=0;i<hsize;i++)
{
if(hTable[(index+i)%hsize].key==item)
{
found=true;
cout<<"item found";
break;
}
}
if(!found)
{
cout<<" : Item not found!"<<endl;
}
cout<<endl;
}
I see you use open address for collision and I don't see any problem here. Are you sure that your string "ZZO" has been inserted into the hash table correctly? I suggest you do a unit test to check that. Just insert the string and iterate the hashtable see whether it exists.
BTW, I suggest you use Separate chaining to implement the hashtable because it's easy to implemented and generally more efficient(Well definitely depends on your hash function). And it could be further extended to be thread-safe.
Even without seeing your insert function code -- I suggest to you that your 'insert' function is the problem -- it most likely does not handle hash collisions and simply override some values/elements -- why don't you post your code for the insert function as well?
i've got some problem/ i don't understand something and it cause this problem :)
Here is some code:
list<Walec>lista;
remove_copy_if(vec.begin(),vec.end(), lista.begin(),Warunek_na_Wysokosc(sredniasu));
copy(lista.begin(),lista.end(),ostream_iterator<Walec>(cout, " \n"));
And here is Warunek_Na_Wysokosc definition:
struct Warunek_na_Wysokosc
{
double wys;
Warunek_na_Wysokosc(const double& h_): wys(h_){ }
bool operator()(const Walec& w)
{
return w.h >= wys;
}
};
The thing is i get some memory problems if i let it be like that, i mean instructions in main function, and there are none if i set list size. But i want it to be set automatically, should i use some insert function? How to correct this? :) Thanks!
I think you want to use inserter here:
remove_copy_if(vec.begin(),vec.end(),
std::inserter(lista,lista.end()),
Warunek_na_Wysokosc(sredniasu));
I have some lines of code about a binary search tree (BSTreeBag) which I can not quite figure out.
The "operator +=(const BSTreeBag& addend)" requires to insert what's in the addend into the current tree we have. If the current tree we have is the same with "addend" we need to double our tree(to make duplicates of all items in the tree)
Here is my code
template <class ItemType>
void BSTreeBag<ItemType>::operator +=(const BSTreeBag& addend)
{
if(this==&addend)//This works
{
binary_tree_node<ItemType>* addroot_ptr=root_ptr;//create a pointer
//that points to the current tree
insert_all(addroot_ptr);//This is a helper function that insert
//every item of the addend into the current tree. It works fine.
}
else
{
insert_all(addend.root_ptr);
}
}
The lines of code works perfectly whenever it is not doing self-assignment. It always stops at the line
insert_all(addroot_ptr);
without giving any information about segmentation fault or other problem. Could someone explain what is going on?
A very likely problem is that you have an infinite loop when you add one tree to itself. Like in, you add nodes while iterating over the tree, but since there are new nodes being added you continue iterating and adding them, ad infinitum.
Lets give an example with a simple list. Lets say you have the following list:
root -> A
Now if you try to add the list to itself, you iterate over the list from the root pointer, finding the node A, so you add that. Now your list looks like
root -> A -> A
You continue the iteration and find... node A (again), and so you add it:
root -> A -> A -> A
And so on and so on.
You should probably create a completely new tree from root_ptr and then add that.
This is what mine looks like (I think both the instructions AND the test file are a little wack):
template <class ItemType>
void BSTreeBag<ItemType>::operator+=(const BSTreeBag& addend)
{
if (this != &addend)
insert_all(addend.root_ptr);
else
{
BSTreeBag<ItemType> new_bst = addend;
insert_all(new_bst.root_ptr);
tree_clear(new_bst.root_ptr);
}
}
I'm keeping track of a player's "job" by setting his job to a number, and incrementing it by one if he changes job, and determining which job he currently is by whether the number is even or odd. (Only two jobs right now). However, I know there are better ways of doing this, and soon I'll need to implement for a third and fourth job, so I cannot keep using the even/odd check.
Here's my code for reference: (Please note that I only include relevant code)
GameModeState.cpp
// If changeJob's parameter number is 1, it increments the job. If number is 2, it only returns the current job
int GameModeState::changeJob(int number)
{
// Default job is even (landman)
static int job = 1;
if (number == 1)
{
job = (job+1);
return job;
}
else
{
return job;
}
}
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
// If the player opens the "stat sheet", it changes their job
void GameModeState::_statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
changeJob(1);
}
GameModeState.h
class GameModeState : public GameState::State
{
public:
/// Changes the player's job if number is 1, or returns current job if number is 2
static int changeJob(int number);
/// Returns the current job number by calling changeJob appropriately
static int getJob();
private:
// Opening the player sheet will change the player's job
void _statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output);
};
ZoneMovementState.cpp (This is where I check for current job)
#include "GameModeState.h"
#include <EnergyGraphics/ZoneParser.h>
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
}
else //otherwise they are a landman
{
ZoneParser::getSingleton().load("../media/zones/landman_zone.xml", false);
}
transitionHandler->go();
}
I'm thinking either arrays or enums of the jobs will be the better way to deal with this, but I'm not sure how to implement this into my code. If you know a better way, please include examples or at least a point in the right direction. I will greatly appreciate it!
Don't use static variables to save anything like that inside a class. Use a member variable instead.
IMO the easiest way to do something like that and make it extensible is using a enum:
enum PlayerJob
JOB_NONE = 0,
JOB_GEOLOGIST,
JOB_LANDMAN,
...
NUM_JOBS // this element is optional but can be useful for range checking.
};
...
PlayerJob job = JOB_NONE;
...
switch(job)
{
case JOB_NONE:
break;
case JOB_GEOLOGIST:
...
break;
...
default:
error("Unhandled palyer job: %d", job);
break;
}
Also I'd think about somehow organizing such "job relevant" stuff into some kind of array or list or whatever to make it easier to call "job specific" things:
std::map<PlayerJob,std::string> jobzones;
jobzones.push_back(JOB_GEOLOGIST, "geozone.xml");
...
transitToZone(jobzones[job]);
Enums are nice, you may also think about using a std::stack or something similar for the GameState, so that you can push/pop etc.
You may want to look at the State pattern.