简体   繁体   中英

In C++ can I create a Binary Search Tree using objects/structs as the node?

In other related c++ work I managed to create a sort of binary search tree template. The implication here is that using this template, I can create a BST for all sorts of data types... Int, string, so on. I've been asked to use a BST as a data structure. Let's imagine it's weather data. A measuring device records the temperature several times daily so I have a date and a time as well as the temperature. Each record I want to use a struct as a container, so I want something like this:

struct Record 
{
string DateTime;
float temperature;
};

DateTime is a string here because it has a format like dd/mm/yyyy xx:xx. I could convert that into an int perhaps.

With thousands of records, I want to insert them all into my BST. This isn't going to work, my BST template has no idea how to compare 2 Records to say which one will go into the left link and right link. Can I just write a bool operator > function that will take 2 Records, compare the datetimes of both, then say whether a Record made later is 'greater than' a Record made earlier, thus it goes into the tree here and so on? Will this work in general?

Should I do something like create a map with an int called DateTime paired with a record, then insert all the integer values representing the DateTimes into my BST. Then when I need to get back my data, first I search the BST to check whether there is an entry, then use that result against my map, which is then supposed to give me the object I want.

The reason why I need to do all this is because I would like to perform calculations such as, 'give me the average temperature for each month in the year of 2018'. Then I would search my BST to give me back all my DateTimes for each month of 2018, then access my Records through the map to tally up the temperatures and average them.

Please feel free to point me in the right directions. I found that googling how to create BSTs of objects and structs gave me implementations of BST using integer nodes, which is not enough...?

DateTime is a string here because it has a format like dd/mm/yyyy xx:xx. I could convert that into an int perhaps.

You could.

Can I just write a bool operator > function that will take 2 Records, compare the datetimes of both, then say whether a Record made later is 'greater than' a Record made earlier, thus it goes into the tree here and so on? Will this work in general?

Yes it will.

Should I do something like create a map with an int called DateTime paired with a record

That is one possibility, although it should not be a separate data structure. One node in your BST would be keyed by the int and have as payload the associated Record (so a struct with an int and a Record ). Alternatively, you could pair the int with just the temperature (again as a struct ) if space efficiency is a concern. Then define a function that can convert an int back to a date string.

Another alternative is that you change the DateTime string format to ISO 8601 format : yyyy-mm-ddThh:mm:ss, and do this at the source of your data, so no back-and-forth conversion is needed.

This has two advantages:

  • It is a good standard, supported by many services/libraries/APIs
  • The lexical order is the order you would expect for date/time. This means you no longer need the conversion to int , but can use the records as nodes in your BST and just compare dates with string comparison.

As trincot pointed out, there are quite a number of ways to use a binary search tree with structures. I kept in mind that I should NOT use a separate structure to store my records, as they rightly pointed out that using my BST template it should generally be declared as BST< Record > rather than BST< int >.

In my earlier example I used a struct to store Record data. I decided to use a class instead. In my new Record class I added operator functions so that my BST template knew what to do when comparing 2 objects.

Imagine that my new Record class looks something like this:

class Record
{
    public:
        /* 
        member variables
        */
        void printValues();
        bool operator>(const Record& otherRecord) const;
        bool operator==(const Record& otherRecord) const;
};

ostream & operator<<(ostream &out, const Record &REC);
//implementation below
bool Record::operator>(const Record& otherRecord) const
{
    return (date > otherRecord.date);
}

bool Record::operator==(const Record& otherRecord) const
{
    return (date == otherRecord.date);
}

As you can see I overloaded the > and == operators. For example in my template, functions that use these operators look like this (this is just 1 of the functions for illustration):

template<class T>
void BSTTemplate<T>::insert(const T& insertItem)
{
    Node<T>* current;
    Node<T>* trailCurrent;
    Node<T>* newNode;

    newNode = new Node<T>;
    newNode->info = insertItem;
    newNode->leftLink = nullptr;
    newNode->rightLink = nullptr;

    if (root == nullptr)
        root = newNode;
    else
    {
        current = root;
        while (current != nullptr)
        {
            trailCurrent = current;
            if(current->info == insertItem)
            {
                cout << "Item is already in tree. Duplicates not allowed." << endl;
                return;
            }
            else if(current->info > insertItem)
                current = current->leftLink;
            else
                current = current->rightLink;

        }
        if (trailCurrent->info > insertItem)
            trailCurrent->leftLink = newNode;
        else
            trailCurrent->rightLink = newNode;
    }
}// end insert()

Without the overloaded operators, statements like

if(current->info == insertItem)

and

else if(current->info > insertItem)

would not work for the objects that I wish to create and use.

I was advised by other users that I should type out an answer that helped me solve my problem, so there you go. Hope that helps someone else...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM