At first, I had Database
to contain std::list<Student> students
, but because there are over 2000 students, searching by students should not be done in linear time. However, searching for students can be by name or by student number. To enable both searches in logarithmic time, I decided to give Database
two maps that hold the same 2000+ students. Inserting and removing a student will have to update both maps. This doubles the time, but I figured that \$2*O(logN)\$ is still much better than \$O(N)\$. If there are to be k different search criteria later on, then \$k*O(logN)\$ is still better than \$O(N)\$ up to, say, k = 20 or so. Agree?
Space complexity is a different matter though. Is the doubling of memory usage bad design here, for 2000+ students? Tripling? Quadrupling?
Is there a better solution altogether?
#include <iostream>
#include <string>
#include <memory>
#include <map>
class Student {
std::string surname, firstName;
long studentNumber;
public:
std::string getSurname() const {return surname;}
std::string getFirstName() const {return firstName;}
std::string fullName() const {return firstName + ' ' + surname;}
long getStudentNumber() const {return studentNumber;}
};
class Database {
std::multimap<std::string, std::shared_ptr<Student>> mapByName;
std::map<long, std::shared_ptr<Student>> mapByStudentNumber;
public:
void insertStudent (const std::shared_ptr<Student>& p) {
mapByName.emplace (getName(p), p);
mapByStudentNumber.emplace (p->getStudentNumber(), p);
// 2 insertions needed.
}
inline void removeStudentByStudentNumber();
inline void removeStudentByName();
private:
void remove (const std::shared_ptr<Student>& p) {
mapByName.erase(getName(p));
mapByStudentNumber.erase(p->getStudentNumber());
// 2 removals needed.
}
std::string getName (const std::shared_ptr<Student>& p) const {return p->fullName();}
};
inline void Database::removeStudentByStudentNumber() {
long studentNumber;
std::cout << "Student number? ";
std::cin >> studentNumber;
const auto it = mapByStudentNumber.find(studentNumber);
if (it == mapByStudentNumber.end()) {
std::cout << "No student with that student number exists.\n\n";
return;
}
remove(it->second);
}
inline void Database::removeStudentByName() {
// Similar to above
}
int main() {}