This is my assignment and i have completed the coding but not displaying the output correctly. The find function below and used in main also does not display and there is a memory leak when checked with valgrind ./a.out but does not tell me where the leak is. Help me out please
#include < map >
#include < queue >
#include < string >
#include < iostream >
using namespace std;
// trie_node
// Implements a trie. This version is hard-coded to use char. The
// end-of-sequence value is a map entry of { char{}, nullptr }.
// This permits char{} values to be within the string as no other
// map entries will have nullptr values stored in them in the entire
// trie.
// NOTE: Some functions are provided and some are not. You must write
// the missing code.
class trie_node
{
public:
using value_type = char;
`private:
using elem_type = char;
using child_node_type = trie_node*;
map< elem_type, child_node_type > children;
public:
// Default construction is simple: since the children map has a default
// constructor, no data is needed in it, and that is the only data
// member, let the compiler generate the code...
trie_node() = default;
// Copy construction performs a breadth-first search (BFS) of the trie
// being copied from. The BFS is tracked using a std::vector as a queue
// where the vector is a pair of trie_node*. The pair of trie_node*
// is used to simultaneously track the BFS in the source trie with the
// corresponding element in the BFS construction of the *this trie.
// Know that a BFS traversal of a tree uses a queue. Essentially, one
// visits a node, queues all its children, and then repeat processing
// the next element at the front of the queue until the queue is empty.
// For time reasons this code has been provided to you. Do take note
// how the solution is crafted using contrainers, etc.
trie_node( trie_node const& n )
{
// stack: breadth first search, std::pair< newtrie, oldtrie >
std::vector< std::pair<trie_node*, trie_node const*> > stack;
std::vector< std::pair<trie_node*, trie_node const*> > bfs;
// Start stack with ( this, &n )...
stack.emplace_back( this, &n );
do
{
auto curpos = stack.back(); bfs.pop_back();
// If this node has no children, then record such and loop...
if ( curpos.second == nullptr )
{
curpos.first = nullptr;
continue;
}
// Enumerate all children...
for (
auto i=begin( curpos.second->children ) ,
iEnd = end( curpos.second->children ) ;
i != iEnd;
++i
)
{
// Create the child trie_node iff i->second != nullptr.
// If i->second == nullptr then it is an end-of-sequence character.
trie_node* tmp_node{
( i->second != nullptr )
? new trie_node
: nullptr
};
// Copy the new node...
curpos.first->children.emplace(
i->first, tmp_node
);
// And continue updating the stack queue...
stack.emplace_back( tmp_node, i->second );
}
} while ( !stack.empty() );
}
// TODO: Write copy assignment operator.
// HINT: 1) Create a local trie_node variable as n is const.
// 2) Use swap.
trie_node& operator = ( trie_node const& n )
{
trie_node tmp( n );
swap( tmp );
return *this;
}
// TODO: Move constructor.
// HINT: There is only one data member. Try moving it! :-)
// RESTRICTION: No code must appear inside the { } braces.
trie_node( trie_node&& n ) : children(std::move(n.children)) {}
// TODO: Move assignment operator.
// HINT: The trie_node class has a swap() member function. Use it!
trie_node& operator =( trie_node&& n )
{
swap( n );
return *this;
}
// TODO: Destructor.
// HINT: The trie_node class has a clear() member function. Use it!
~trie_node()
{
clear();
}
// TODO: swap().
// HINT: You know how to swap variables using a temporary variable.
// Do exactly this.
// Now add std::move() around each variable on the right-hand
// side of each assignment operator. This will allow moves
// instead of copies where possible.
void swap( trie_node& n )
{
trie_node tmp = move( n ) ;
n = move( *this );
*this = move( tmp );
}
// TODO: clear()
// HINT: Like the copy constructor, clear() will traverse the trie
// using breadth-first search.
// Look up std::queue in your textbooks. You'll notice the
// functions: push(), pop(), front(), back(), and empty().
// Pseudocode is given in the task description within the
// project.
// RESTRICTION: You must use std::queue<trie_node*> to do this
// solution.
void clear()
{
std::queue<trie_node*> bfs;
bfs.push( this );
while(!bfs.empty())
{
trie_node* node_ptr ;
node_ptr = bfs.front();
bfs.pop();
for( auto i = bfs.front(); i != bfs.back() ; i++ )
{
if( node_ptr != nullptr )
{
bfs.push( node_ptr );
free( node_ptr );
}
}
bfs.pop();
if( node_ptr == this )
{
delete node_ptr;
}
}
}
// This is the code done in class for the add() function except
// support has been added to handle an end-of-sequence marker.
//
// NOTE: Notice the use of emplace() instead of insert().
// The emplace() function passes its arguments directly
// to the constructor of the std::pair in the map.
void add(std::string const& s)
{
// Start at this (root) node...
trie_node* curpos = this;
// Build trie for s...
for ( auto i=begin(s), iEnd=end(s); i != iEnd; ++i )
{
// Add the next sequence value...
// result's type: pair<iterator, bool>
auto result = curpos->children.emplace(elem_type(*i), nullptr);
// If the next sequence value was inserted, then ensure
// a default trie_node is allocated with new...
if ( result.second )
{
// *i is not already stored and next entry must at least
// be end-of-string...
result.first->second = new trie_node;
}
// Continue with next node's information...
curpos = result.first->second;
}
// When done adding the sequence, ensure there is an end-of-sequence
// value added...
curpos->children.emplace(elem_type{}, nullptr);
}
// This is the code done in class for the find() function except
// support has been added to handle an end-of-sequence marker.
bool find( std::string const& s ) const
{
bool retval = false;
trie_node const * curpos = this;
for (auto curvalue : s)
{
auto const sEnd = end(curpos->children);
auto iter = curpos->children.find(elem_type(curvalue));
if (iter != sEnd)
curpos = iter->second;
else
curpos = nullptr; // not found
if (curpos == nullptr)
return retval;
}
// If we get here, then the sequence is in the trie iff
// there is an end-of-sequence character...
auto result = curpos->children.find( elem_type{} );
if ( result != end( curpos->children ) && result->second == nullptr )
retval = true;
return retval;
}
// You might need to debug your code. Also you might wonder how
// to obtain every sequence in the trie. This recursive function
// shows how to do an inorder traversal of the trie. It will
// output all sequences to the basic_ostream os.
template <typename Ch, typename ChTr>
void print_inorder(
std::basic_ostream<Ch,ChTr>& os,
std::vector<elem_type> prefix={}
)
{
for ( auto&& child : this->children )
{
prefix.push_back( child.first );
if ( child.second != nullptr )
child.second->print_inorder( os, prefix );
else
{
auto i = begin( prefix );
auto iEnd = end( prefix );
// Discard the end of string marker...
if ( iEnd != i )
--iEnd;
// Output sequence...
for ( ; i != iEnd; ++i )
os << *i;
os << endl;
}
prefix.pop_back();
}
}
};
// TODO: swap()
// HINT: Simply invoke trie_node's swap()!
// NOTE: This is needed to support calling a free swap() function.
// One may or may not know about the member function --but one
// shouldn't have to know about it at all if this function is
// provided!
inline void swap( trie_node& a, trie_node& b )
{
swap( a , b );
}
int main()
{
trie_node n;
string test = "ab";
n.add( test );
n.add( string ( "abcde" ) );
n.add( string ( "abcdd" ) );
n.add( string ( "airplane" ) );
n.add( string ( "airlock" ) );
n.print_inorder( cout );
trie_node o = n;
bool b2 = o.find( string ( "airplane" ) );
bool b3 = o.find( string ( "airlock" ) );
bool b4 = o.find( string ( "a" ) );
cout << b2 << b3 << b4 << '\n';
// Outputs: 110
return 0;
}
Aucun commentaire:
Enregistrer un commentaire