I wrote this program:
#include <iostream>
#include <string>
#include <ctime>
#include <sstream>
#include <time.h>
#include "TextTable.h"
using namespace std;
int command();
void new_car();
void print();
int c=0;
int c1=0;
char f;
int i=0;
int size1=0;
TextTable t( '-', '|', '*' );
struct car
{
string car_name;
string car_owner_name;
int year;
string car_paint;
string car_performance;
string car_problem;
int time;
};
car *a = NULL;
car *p;
int main ()
{
cout<<"welcome to car repair shop program. to help , press h."<<endl;
command();
}
int command(){
cout<<"admin#car_repair_shop_program # ";
cin>>f;
switch(f)
{
case 'n':
new_car();
break;
case 'h':
cout<<endl<<"help"<<endl<<"p : print"<<endl<<"n : new"<<endl<<"h : help"<<endl<<"q : quit"<<endl;
command();
break;
case 'p':
print();
break;
case 'q':
char tmp;
cout<<"Are you sure you want to quit? (y or n): ";
cin>>tmp;
switch(tmp){
case 'y':
delete [] a;
delete [] p;
return 0;
break;
case 'n':
command();
break;
default:
cout << "error! Please try again"<<endl;
command();
}
default:
cout << "error! Please try again"<<endl;
command();
}
}
void new_car()
{
c++;
string car_name;
string car_owner_name;
int year;
string car_paint;
string car_performance;
string car_problem;
int time;
p = new car[++size1];
if (c==1){
a = new car [size1-1];
}
cout<<"enter car name: ";
cin>>car_name;
cout<<endl<<"enter car owner name: ";
cin>>car_owner_name;
cout<<endl<<"enter car paint: ";
cin>>car_paint;
cout<<endl<<"enter car performance: ";
cin>>car_performance;
cout<<endl<<"enter car problem: ";
cin>>car_problem;
cout<<endl<<"enter time: ";
cin>>time;
cout<<endl<<"enter year: ";
cin>>year;
for(int i = 0 ; i < size1-1 ; ++i)
{
p[i].car_name = a[i].car_name;
p[i].car_owner_name = a[i].car_owner_name;
p[i].car_paint = a[i].car_paint;
p[i].car_performance = a[i].car_performance;
p[i].car_problem = a[i].car_problem;
p[i].time = a[i].time;
p[i].year = a[i].year;
}
delete [] a;
a = p;
a[size1-1].car_name=car_name;
a[size1-1].car_owner_name=car_owner_name;
a[size1-1].car_paint=car_paint;
a[size1-1].car_performance=car_performance;
a[size1-1].car_problem=car_problem;
a[size1-1].time=time;
a[size1-1].year=year;
cout<<"OK!"<<endl;
command();
}
void print()
{
c1++;
if (c1 == 1){
t.add( " car name " );
t.add( " car owner name " );
t.add( " car paint " );
t.add( " car performance " );
t.add( " car problem " );
t.add( " time " );
t.add( " year " );
t.endOfRow();
}
string tmp;
for (;i<size1;){
t.add(p[i].car_name);
t.add(p[i].car_owner_name);
t.add(p[i].car_paint);
t.add(p[i].car_performance);
t.add(p[i].car_problem);
tmp = to_string(p[i].time);
t.add(tmp);
tmp = to_string(p[i].year);
t.add(tmp);
t.endOfRow();
t.setAlignment( i, TextTable::Alignment::LEFT );
i+=1;
}
cout << t;
command();
}
But I can not do this part of the project:
"Check what appropriate Data Type provided by the C/C++ library can be used to store time and date information in the program above, and rewrite your program using these tools" I need to get the time and year variables.
The text of the TextTable.h file also contains the following:
#pragma once
#include <iostream>
#include <map>
#include <iomanip>
#include <vector>
#include <string>
#ifdef TEXTTABLE_ENCODE_MULTIBYTE_STRINGS
#include <clocale>
#ifndef TEXTTABLE_USE_EN_US_UTF8
#define TEXTTABLE_USE_EN_US_UTF8
#endif
#endif
class TextTable {
public:
enum class Alignment { LEFT, RIGHT };
typedef std::vector< std::string > Row;
TextTable() :
_horizontal( '-' ),
_vertical( '|' ),
_corner( '+' ),
_has_ruler(true)
{}
TextTable( char horizontal, char vertical, char corner ) :
_horizontal( horizontal ),
_vertical( vertical ),
_corner( corner ),
_has_ruler(true)
{}
explicit TextTable( char vertical ) :
_horizontal( '\0' ),
_vertical( vertical ),
_corner( '\0' ),
_has_ruler( false )
{}
void setAlignment( unsigned i, Alignment alignment )
{
_alignment[ i ] = alignment;
}
Alignment alignment( unsigned i ) const
{ return _alignment[ i ]; }
char vertical() const
{ return _vertical; }
char horizontal() const
{ return _horizontal; }
void add( std::string const & content )
{
_current.push_back( content );
}
void endOfRow()
{
_rows.push_back( _current );
_current.assign( 0, "" );
}
template <typename Iterator>
void addRow( Iterator begin, Iterator end )
{
for( auto i = begin; i != end; ++i ) {
add( * i );
}
endOfRow();
}
template <typename Container>
void addRow( Container const & container )
{
addRow( container.begin(), container.end() );
}
std::vector< Row > const & rows() const
{
return _rows;
}
void setup() const
{
determineWidths();
setupAlignment();
}
std::string ruler() const
{
std::string result;
result += _corner;
for( auto width = _width.begin(); width != _width.end(); ++ width ) {
result += repeat( * width, _horizontal );
result += _corner;
}
return result;
}
int width( unsigned i ) const
{ return _width[ i ]; }
bool has_ruler() const { return _has_ruler;}
int correctDistance(std::string string_to_correct) const
{
return static_cast<int>(string_to_correct.size()) - static_cast<int>(glyphLength(string_to_correct));
};
private:
const char _horizontal;
const char _vertical;
const char _corner;
const bool _has_ruler;
Row _current;
std::vector< Row > _rows;
std::vector< unsigned > mutable _width;
std::vector< unsigned > mutable _utf8width;
std::map< unsigned, Alignment > mutable _alignment;
static std::string repeat( unsigned times, char c )
{
std::string result;
for( ; times > 0; -- times )
result += c;
return result;
}
unsigned columns() const
{
return _rows[ 0 ].size();
}
unsigned glyphLength( std::string s ) const
{
unsigned int _byteLength = s.length();
#ifdef TEXTTABLE_ENCODE_MULTIBYTE_STRINGS
#ifdef TEXTTABLE_USE_EN_US_UTF8
std::setlocale(LC_ALL, "en_US.utf8");
#else
#error You need to specify the encoding if the TextTable library uses multybyte string encoding!
#endif
unsigned int u = 0;
const char *c_str = s.c_str();
unsigned _glyphLength = 0;
while(u < _byteLength)
{
u += std::mblen(&c_str[u], _byteLength - u);
_glyphLength += 1;
}
return _glyphLength;
#else
return _byteLength;
#endif
}
void determineWidths() const
{
_width.assign( columns(), 0 );
_utf8width.assign( columns(), 0 );
for ( auto rowIterator = _rows.begin(); rowIterator != _rows.end(); ++ rowIterator ) {
Row const & row = * rowIterator;
for ( unsigned i = 0; i < row.size(); ++i ) {
_width[ i ] = _width[ i ] > glyphLength(row[ i ]) ? _width[ i ] : glyphLength(row[ i ]);
}
}
}
void setupAlignment() const
{
for ( unsigned i = 0; i < columns(); ++i ) {
if ( _alignment.find( i ) == _alignment.end() ) {
_alignment[ i ] = Alignment::LEFT;
}
}
}
};
inline std::ostream & operator<<( std::ostream & stream, TextTable const & table )
{
table.setup();
if (table.has_ruler()) {
stream << table.ruler() << "\n";
}
for ( auto rowIterator = table.rows().begin(); rowIterator != table.rows().end(); ++ rowIterator ) {
TextTable::Row const & row = * rowIterator;
stream << table.vertical();
for ( unsigned i = 0; i < row.size(); ++i ) {
auto alignment = table.alignment( i ) == TextTable::Alignment::LEFT ? std::left : std::right;
// std::setw( width ) works as follows: a string which goes in the stream with byte length (!) l is filled with n spaces so that l+n=width.
// For a utf8 encoded string the glyph length g might be smaller than l. We need n spaces so that g+n=width which is equivalent to g+n+l-l=width ==> l+n = width+l-g
// l-g (that means glyph length minus byte length) has to be added to the width argument.
// l-g is computed by correctDistance.
stream << std::setw( table.width( i ) + table.correctDistance(row[ i ])) << alignment << row[ i ];
stream << table.vertical();
}
stream << "\n";
if (table.has_ruler()) {
stream << table.ruler() << "\n";
}
}
return stream;
}
What appropriate Data Type provided by the C/C++ library can be used?
You might want to look up std::time on a site like http://www.cppreference.com. There is a lot of information there.
Related
Aim is to make sure that the user entered input for string 1 and string 2 contains only characters A,T,G or C in any order. If either string contains another other character then error should be displayed. Example:
Input contains error
Error in String #1: aacgttcOgMa
Error in String #2: ggataccaSat
This is my attempt at LCS.cpp file code:
#include "LCS.h"
#include <string>
using namespace std;
bool validate(string strX, string strY)
{
string x = strX;
string y = strY;
char searchItem = 'A';
char searchItem = 'C';
char searchItem = 'G';
char searchItem = 'T';
int numOfChar = 0;
int m = strX.length();
int n = strY.length();
for (int i = 0; i < m; i++)
{
if (x[i] == searchItem)
{
numOfChar++;
}
for (int i = 0; i < n; i++)
{
if (y[i] == searchItem)
{
numOfChar++;
}
}
}
This is my LCS.h file code:
#pragma once
#ifndef LCS_H
#define LCS_H
#include <string>
using namespace std;
bool validate(string strX, string strY);
#endif
And my driver file "Driver6.cpp" has this code:
#include "LCS.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strX, strY;
cout << "String #1: ";
cin >> strX;
cout << "String #2: ";
cin >> strY;
//validate the input two strings
if (validate(strX, strY) == false)
{
return 0;
}
int m = strX.length();
int n = strY.length();
}
Didn't really want to do this but it seems like the best bet rather than going round the houses in the comments:
#include <string>
#include <iostream>
bool validate( const std::string & s ) {
for ( auto c : s ) {
if ( c != 'A' && c != 'T' && c != 'C' && c != 'G' ) {
return false;
}
}
return true;
}
int main() {
std::string s1 = "ATGCCCG";
std::string s2 = "ATGfooCCCG";
if ( validate( s1 ) ) {
std::cout << "s1 is valid\n";
}
else {
std::cout << "s1 is not valid\n";
}
if ( validate( s2 ) ) {
std::cout << "s2 is valid\n";
}
else {
std::cout << "s2 is not valid\n";
}
}
Another technique:
bool validate(const std::string& s)
{
const static std::string valid_letters("ATCGatcg");
for (auto c: s)
{
std::string::size_type position = valid_letters.find_first_of(c);
if (position == std::string::npos)
{
return false;
}
}
return true;
}
The above code searches a container of valid letters.
Below is an old exercise for a class that is no longer being taught at my university (Parallel Processing). The goal is to create and use a Memory Bank to speed up the Lock-Free Sorted Vector implementation. I implemented the Memory Bank myself and the goal is to set aside enough memory to use so I do not have to use new or delete in the LFSV. I believe I need a Get() function that returns the address of the memory (not sure how keep track of the unused memory) and Store should free the memory (somehow mark it as unused).
Inside LFSV (which worked perfectly fine before my intervention), the exercise explains that I should replace the new and delete with new replacement and Store(memory we want freed). How do I go about creating the Get(if this is incorrect) or the Store function to perform like a proper memory bank? I will also take any reference or memory bank examples online that you may know of because I am having trouble finding good resources related to memory banks and multithreading.
There are no errors in this program, but it returns as a "FAIL" since I did not properly manage the memory bank.
#include <algorithm>//copy, random_shuffle
#include <ctime> //std::time (NULL) to seed srand
#include <iostream> // std::cout
#include <atomic> // std::atomic
#include <thread> // std::thread
#include <vector> // std::vector
#include <mutex> // std::mutex
#include <deque> // std::deque
class MemoryBank
{
std::deque< std::vector<int>* > slots;
public:
MemoryBank() : slots(10000)
{
for (int i = 0; i<10000; ++i)
{
slots[i] = reinterpret_cast<std::vector<int>*>(new char[sizeof(std::vector<int>)]);
}
}
~MemoryBank()
{
for (unsigned int i = 0; i < slots.size(); ++i)
{
delete slots[i];
}
slots.clear();
}
void * Get()
{
return &slots;
}
void Store(std::vector<int *> freeMemory)
{
return;
}
};
class LFSV {
std::atomic< std::vector<int>* > pdata;
std::mutex wr_mutex;
MemoryBank mb;
public:
LFSV() : mb(), pdata( new (mb.Get()) std::vector<int> ) {}
~LFSV()
{
mb.~MemoryBank();
}
void Insert( int const & v ) {
std::vector<int> *pdata_new = nullptr, *pdata_old;
int attempt = 0;
do {
++attempt;
delete pdata_new;
pdata_old = pdata;
pdata_new = new (mb.Get())std::vector<int>( *pdata_old );
std::vector<int>::iterator b = pdata_new->begin();
std::vector<int>::iterator e = pdata_new->end();
if ( b==e || v>=pdata_new->back() ) { pdata_new->push_back( v ); } //first in empty or last element
else {
for ( ; b!=e; ++b ) {
if ( *b >= v ) {
pdata_new->insert( b, v );
break;
}
}
}
// std::lock_guard< std::mutex > write_lock( wr_mutex );
// std::cout << "insert " << v << "(attempt " << attempt << ")" << std::endl;
} while ( !(this->pdata).compare_exchange_weak( pdata_old, pdata_new ));
// LEAKing pdata_old since "delete pdata_old;" will cause errors
// std::lock_guard< std::mutex > write_lock( wr_mutex );
// std::vector<int> * pdata_current = pdata;
// std::vector<int>::iterator b = pdata_current->begin();
// std::vector<int>::iterator e = pdata_current->end();
// for ( ; b!=e; ++b ) {
// std::cout << *b << ' ';
// }
// std::cout << "Size " << pdata_current->size() << " after inserting " << v << std::endl;
}
int const& operator[] ( int pos ) const {
return (*pdata)[ pos ];
}
};
LFSV lfsv;
void insert_range( int b, int e ) {
int * range = new int [e-b];
for ( int i=b; i<e; ++i ) {
range[i-b] = i;
}
std::srand( static_cast<unsigned int>(std::time (NULL)) );
std::random_shuffle( range, range+e-b );
for ( int i=0; i<e-b; ++i ) {
lfsv.Insert( range[i] );
}
delete [] range;
}
int reader( int pos, int how_many_times ) {
int j = 0;
for ( int i=1; i<how_many_times; ++i ) {
j = lfsv[pos];
}
return j;
}
std::atomic<bool> doread( true );
void read_position_0() {
int c = 0;
while ( doread.load() ) {
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
if ( lfsv[0] != -1 ) {
std::cout << "not -1 on iteration " << c << "\n"; // see main - all element are non-negative, so index 0 should always be -1
}
++c;
}
}
void test( int num_threads, int num_per_thread )
{
std::vector<std::thread> threads;
lfsv.Insert( -1 );
std::thread reader = std::thread( read_position_0 );
for (int i=0; i<num_threads; ++i) {
threads.push_back( std::thread( insert_range, i*num_per_thread, (i+1)*num_per_thread ) );
}
for (auto& th : threads) th.join();
doread.store( false );
reader.join();
for (int i=0; i<num_threads*num_per_thread; ++i) {
// std::cout << lfsv[i] << ' ';
if ( lfsv[i] != i-1 ) {
std::cout << "Error\n";
return;
}
}
std::cout << "All good\n";
}
void test0() { test( 1, 100 ); }
void test1() { test( 2, 100 ); }
void test2() { test( 8, 100 ); }
void test3() { test( 100, 100 ); }
void (*pTests[])() = {
test0,test1,test2,test3//,test4,test5,test6,test7
};
#include <cstdio> /* sscanf */
int main( int argc, char ** argv ) {
if (argc==2) { //use test[ argv[1] ]
int test = 0;
std::sscanf(argv[1],"%i",&test);
try {
pTests[test]();
} catch( const char* msg) {
std::cerr << msg << std::endl;
}
return 0;
}
}
reinterpret_cast is really a "I know what I'm doing, trust me" cast. The compiler will - if possible - believe you.
However, in this case it's entirely wrong. new char[] does not return a vector<int>*.
I'm having some troubles with searching a string inserted into a trie. I find that if I insert using a string literal, my trie has no issues with finding the word. But if it is streamed from a file, then it cannot do so. I have a suspicion it may have to do with a null terminator, but I'm not sure how to resolve this.
My Code is below:
trie.h
#pragma once
#include <vector>
using namespace std;
class Node {
public:
Node();
~Node();
char Content(); // Returns mContent
void SetContent(char c); // Set Node content to char c
bool WordMarker(); // A boolean flag if a word has formed
void SetWordMarker(); // Sets Word marker in Node
void AppendChild( Node* child ); // Appends an element into array
Node* FindChild(char c); // Locates character and returns Node
//vector<Node*> children( { return mChildren; }
//Node *children() { return mChildren
private:
char mContent;
bool mMarker;
vector<Node*> mChildren;
};
class Trie {
public:
Trie();
~Trie();
void AddWord(string s); // Adds string to the trie
bool SearchWord(string s); // Finds word in trie
private:
Node* root;
};
trie.cpp
#include <vector>
#include <iostream>
#include <string>
#include "trie.h"
using namespace std;
Node::Node() { mContent = ' '; mMarker = false; }
Node::~Node() {}
char Node::Content() { return mContent; }
void Node::SetContent(char c) { mContent = c; }
bool Node::WordMarker() { return mMarker; }
void Node::SetWordMarker() { mMarker = true; }
void Node::AppendChild(Node* child) { mChildren.push_back(child); }
Trie::Trie() { root = new Node(); }
Trie::~Trie() {}
Node* Node::FindChild(char c) {
for ( int i = 0; i < mChildren.size(); i++ ) {
Node* tmp = mChildren.at(i);
if ( tmp->Content() == c ) {
return tmp;
}
}
return NULL;
}
void Trie::AddWord(string s) {
Node* current = root;
if ( s.length() == 0 ) {
current->SetWordMarker(); // an empty word
return;
}
if ( SearchWord(s) ) {
cout << s << " already exists in Trie. Skipping." << endl;
return;
}
for ( int i = 0; i < s.length(); i++ ) {
Node* child = current->FindChild(s[i]);
if ( child != NULL ) {
current = child;
} else {
Node* tmp = new Node();
tmp->SetContent(s[i]);
current->AppendChild(tmp);
current = tmp;
}
if ( i == s.length() - 1 ) {
current->SetWordMarker();
}
}
}
bool Trie::SearchWord(string s) {
Node* current = root;
while ( current != NULL ) {
for ( int i = 0; i < s.length(); i++ ) {
Node* tmp = current->FindChild(s[i]);
if ( tmp == NULL ) {
return false;
}
current = tmp;
}
if ( current->WordMarker() ) {
return true;
} else {
return false;
}
}
return false;
}
My main
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <cstring>
#include <set>
#include "trie.h"
#include "trie.cpp"
std::set <char> CharSet ( char oldArr[4][4], const int n ) {
std::set <char> uniqueCharSet;
for( int i = 0; i < n; i++ ) {
for ( int j = 0; j < n; j++ ) {
uniqueCharSet.insert( oldArr[i][j] );
}
}
return uniqueCharSet;
}
void LoadTrie( std::set <char> charSet, int limit ) {
Trie *trie = new Trie();
std::string filename = "enable1.txt";
std::string word;
std::ifstream dict1;
dict1.open( filename, std::ios::in );
if( dict1.is_open() ) {
bool wordInCharSet = false;
int i = 0;
int wordLength = 0;
while( getline( dict1, word ) ) {
wordLength = word.length();
wordInCharSet = IsWordInCharSet( charSet, word);
if ( wordLength <= limit && wordInCharSet && i < 10 ) {
std::cout << "Inserting: " << word << endl;
trie->AddWord( word );
i++;
std::cout << "Searching for " << word << "\n";
if (trie->SearchWord(word) ) {
std::cout << "Found " << word << " \n";
} else {
std::cout << "NOT FOUND " << word << "\n";
}
}
}
std::cout << i << " words with <= " << limit << " characters transferred\n";
}
std::string newTestWord = "AHA!";
trie->AddWord(newTestWord);
std::cout << "Searching for " << newTestWord << "\n";
if (trie->SearchWord(newTestWord) ) {
std::cout << "Found " << newTestWord << " \n";
} else {
std::cout << "NOT FOUND " << newTestWord << "\n";
}
dict1.close();
}
int main( int agrc, char *argv[] ) {
char matrixArr[4][4] = {{'s','t','n','g'},
{'e','i','a','e'},
{'d','r','l','s'},
{'s','e','p','o'}};
std::set<char> charSet = CharSet ( matrixArr, 4 );
LoadTrie ( charSet, 16);
return 0;
}
Enable1.txt
aah
aahed
aahing
aahs
aal
aalii
aaliis
aals
aardvark
My results:
Inserting: aa
ound aa
Inserting: aah
ound aah
Inserting: aahed
ound aahed
Inserting: aahing
ound aahing
Inserting: aahs
ound aahs
Inserting: aal
ound aal
Inserting: aalii
ound aalii
Inserting: aaliis
ound aaliis
Inserting: aals
ound aals
Inserting: aardvark
ound aardvark
10 words with <= 16 characters transferred
Searching for aah
NOT FOUND aah
As you also notice, I'm missing the first character 'F' when displaying my results. Why is this? What's going on? Is this a string literal vs c-string?
I have a function that is always returning 0. The problem I believe is that data is an unsigned char, which is not part of the library. It needs to be unsigned char. So how can I make this work, because what I have doesn't.
#include <string>
#include <iostream>
int Count( const std::string & str,
const std::string & obj ) {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
std::string ::size_type pos = 0;
while( (pos = obj.find( str, pos ))
!= std::string::npos ) {
a++;
b++;
c++;
d++;
pos += str.size();
}
return a;
return b;
return c;
return d;
}
void printTcpContent(unsigned char *data,int)
{
std::string s = (const char*) data;
int a = Count( "text/html", s );
int b = Count( "text/plain", s );
int c = Count( "image/jpg", s );
int d = Count( "image/png", s );
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
std::cout << d << std::endl;
}
Try this code instead:
int Count( const std::string & strToFind,
const std::string & strToSearch ) {
int n = 0;
std::string ::size_type pos = 0;
while( (pos = strToSearch.find( strToFind, pos )) != std::string::npos ) {
n++;
pos += strToSearch.size();
}
return n;
}
Also, you can test it works by calling it with smaller test strings, eg Count("3", "1234534")
Following is my attempt to write BK-Tree , for 150000 word file it takes around 8 seconds
Is there any way to reduce this time.
Following is my code
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include "Timer.h"
class BkTree {
public:
BkTree();
~BkTree();
void insert(std::string m_item);
private:
size_t EditDistance( const std::string &s, const std::string &t );
struct Node {
std::string m_item;
size_t m_distToParent;
Node *m_firstChild;
Node *m_nextSibling;
Node(std::string x, size_t dist);
~Node();
};
Node *m_root;
int m_size;
protected:
};
BkTree::BkTree() {
m_root = NULL;
m_size = 0;
}
BkTree::~BkTree() {
if( m_root )
delete m_root;
}
BkTree::Node::Node(std::string x, size_t dist) {
m_item = x;
m_distToParent = dist;
m_firstChild = m_nextSibling = NULL;
}
BkTree::Node::~Node() {
if( m_firstChild )
delete m_firstChild;
if( m_nextSibling )
delete m_nextSibling;
}
void BkTree::insert(std::string m_item) {
if( !m_root ){
m_size = 1;
m_root = new Node(m_item, -1);
return;
}
Node *t = m_root;
while( true ) {
size_t d = EditDistance( t->m_item, m_item );
if( !d )
return;
Node *ch = t->m_firstChild;
while( ch ) {
if( ch->m_distToParent == d ) {
t = ch;
break;
}
ch = ch->m_nextSibling;
}
if( !ch ) {
Node *newChild = new Node(m_item, d);
newChild->m_nextSibling = t->m_firstChild;
t->m_firstChild = newChild;
m_size++;
break;
}
}
}
size_t BkTree::EditDistance( const std::string &left, const std::string &right ) {
size_t asize = left.size();
size_t bsize = right.size();
std::vector<size_t> prevrow(bsize+1);
std::vector<size_t> thisrow(bsize+1);
for(size_t i = 0; i <= bsize; i++)
prevrow[i] = i;
for(size_t i = 1; i <= asize; i ++) {
thisrow[0] = i;
for(size_t j = 1; j <= bsize; j++) {
thisrow[j] = std::min(prevrow[j-1] + size_t(left[i-1] != right[j-1]),
1 + std::min(prevrow[j],thisrow[j-1]) );
}
std::swap(thisrow,prevrow);
}
return prevrow[bsize];
}
void trim(std::string& input_str) {
if(input_str.empty()) return;
size_t startIndex = input_str.find_first_not_of(" ");
size_t endIndex = input_str.find_last_not_of("\r\n");
std::string temp_str = input_str;
input_str.erase();
input_str = temp_str.substr(startIndex, (endIndex-startIndex+ 1) );
}
int main( int argc, char **argv ) {
BkTree *pDictionary = new BkTree();
std::ifstream dictFile("D:\\dictionary.txt");
Timer *t = new Timer("Time Taken to prepare Tree = ");
std::string line;
if (dictFile.is_open()) {
while (! dictFile.eof() ) {
std::getline (dictFile,line);
trim(line);
pDictionary->insert(line);
}
dictFile.close();
}
delete t;
delete pDictionary;
return 0;
}
class Timer {
public:
Timer (const std::string &name = "undef");
~Timer (void);
private:
std::string m_name;
std::clock_t m_started;
protected:
};
Timer::Timer (const std::string &name) : m_name(name), m_started(clock()) {
}
Timer::~Timer (void) {
double secs = static_cast<double>(std::clock() - m_started) / CLOCKS_PER_SEC;
std::cout << m_name << ": " << secs << " secs." << std::endl;
}
You can reduce the time by eliminating the I/O. To test your algorithm, remove as many objects out of the equation that are not directly under the control of your program. For example, the OS controls the I/O, it is out of your control. An array of constant text removes much OS involvement (the OS still may page the array depending on OS memory allocation).
Next, most tree structures are data oriented. Their performance times depend on the data. Try three sets of data: sorted ascending, "random", and sorted descending. Note the times for each.
Look at your loops and factor out any constants. Create temporary variables in loops for constant calculations in inner loops. Remove unnecessary operations.
Lastly, if your program and algorithm is very robust, work on other projects. Optimize only if necessary.