Online Book Reader

Home Category

Professional C__ - Marc Gregoire [426]

By Root 1455 0
the calls to nameExists() are followed by a call to incrementNameCount(). If you look back at the code, you can see that these functions are almost identical; they could probably be combined. In addition, most of what they are doing is searching the vector. It would probably be better to use a sorted data structure to reduce the searching time.

Second Attempt

With these two observations from the gprof output, it’s time to redesign the program. The new design uses a map instead of a vector. Chapter 12 explains that the STL map keeps the entries sorted, and provides O(log n) lookup instead of the O(n) searches in the vector.

The new version of the program also combines nameExists() and incrementNameCount() into one nameExistsAndIncrement() method.

Here is the new class definition:

#include

#include

#include

using std::string;

class NameDB

{

public:

NameDB(const string& nameFile) throw (std::invalid_argument);

int getNameRank(const string& name) const;

int getAbsoluteNumber(const string& name) const;

protected:

std::map mNames;

bool nameExistsAndIncrement(const string& name);

void addNewName(const string& name);

};

Code snippet from NameDB\SecondAttempt\NameDB.h

Here are the new method implementations:

// Reads the names from the file and populates the database.

// The database is a map associating names with their frequency.

NameDB::NameDB(const string& nameFile) throw (invalid_argument)

{

// Open the file and check for errors.

ifstream inFile(nameFile.c_str());

if (!inFile) {

throw invalid_argument("Unable to open file");

}

// Read the names one at a time.

string name;

while (inFile >> name) {

// Look up the name in the database so far.

if (!nameExistsAndIncrement(name)) {

// If the name exists in the database, the

// method incremented it, so we just continue.

// We get here if it didn't exist, in which case

// we add it with a count of 1.

addNewName(name);

}

}

inFile.close();

}

// Returns true if the name exists in the database, false

// otherwise. If it finds it, it increments it.

bool NameDB::nameExistsAndIncrement(const string& name)

{

// Find the name in the map.

auto res = mNames.find(name);

if (res != mNames.end()) {

res->second++;

return true;

}

return false;

}

// Adds a new name to the database

void NameDB::addNewName(const string& name)

{

mNames[name] = 1;

}

// Returns the rank of the name.

// First looks up the name to obtain the number of babies with that name.

// Then iterates through all the names, counting all the names with a higher

// count than the specified name. Returns that count as the rank.

int NameDB::getNameRank(const string& name) const

{

int num = getAbsoluteNumber(name);

// Check if we found the name.

if (num == -1) {

return -1;

}

// Now count all the names in the map that have

// count higher than this one. If no name has a higher count,

// this name is rank number 1. Every name with a higher count

// decreases the rank of this name by 1.

int rank = 1;

for (auto it = mNames.cbegin(); it != mNames.cend(); ++it) {

if (it->second > num) {

rank++;

}

}

return rank;

}

// Returns the count associated with this name.

int NameDB::getAbsoluteNumber(const string& name) const

{

auto res = mNames.find(name);

if (res != mNames.end()) {

return res->second;

}

return -1;

}

Code snippet from NameDB\SecondAttempt\NameDB.cpp

Profile of the Second Attempt

By following the same steps shown earlier, you can obtain the gprof performance data on the new version of the program. The data are quite encouraging:

index %time self children called name

[1] 100.0 0.00 0.21 main [1]

0.02 0.18 1/1 NameDB::NameDB [2]

0.00 0.01 1/1 NameDB::~NameDB [13]

0.00 0.00 3/3 NameDB::getNameRank [28]

[2] 95.2 0.02 0.18 1 NameDB::NameDB [2]

0.02 0.16 500500/500500 NameDB::nameExistsAndIncrement [3]

0.00 0.00 1000/1000 NameDB::addNewName [24]

0.00 0.00 1/1 map::map [87]

If you run this on your machine, the output will be different. It’s even possible that you will not see the data for NameDB methods

Return Main Page Previous Page Next Page

®Online Book Reader