二叉搜索树

Binary Search Tree

本文关键字:搜索树      更新时间:2023-10-16

我现在正在做一个学校的项目。任务是在给定相应的头文件的情况下编写模板化二叉搜索树的实现。

我的问题是,因为它是模板化的,我不确定如何在插入或查找数据项之间进行比较。

头文件:

template < typename DataType, class KeyType >    // DataType : tree data item
class BSTree                                     // KeyType : key field
{
  public:
// Constructor
BSTree ();                         // Default constructor
BSTree ( const BSTree<DataType,KeyType>& other );   // Copy constructor
BSTree& operator= ( const BSTree<DataType,KeyType>& other );
                      // Overloaded assignment operator
// Destructor
~BSTree ();
// Binary search tree manipulation operations
void insert ( const DataType& newDataItem );  // Insert data item
bool retrieve ( const KeyType& searchKey, DataType& searchDataItem ) const;
                                              // Retrieve data item
bool remove ( const KeyType& deleteKey );            // Remove data item
void writeKeys () const;                      // Output keys
void clear ();                                // Clear tree
// Binary search tree status operations
bool isEmpty () const;                        // Tree is empty
// !! isFull() has been retired. Not very useful in a linked structure.
// Output the tree structure -- used in testing/debugging
void showStructure () const;
// In-lab operations
int getHeight () const;                       // Height of tree
int getCount () const;            // Number of nodes in tree
void writeLessThan ( const KeyType& searchKey ) const; // Output keys < searchKey
protected:
class BSTreeNode                  // Inner class: facilitator for the BSTree class
{
  public:
    // Constructor
    BSTreeNode ( const DataType &nodeDataItem, BSTreeNode *leftPtr, BSTreeNode *rightPtr );
    // Data members
    DataType dataItem;         // Binary search tree data item
    BSTreeNode *left,    // Pointer to the left child
               *right;   // Pointer to the right child
};
// Recursive helpers for the public member functions -- insert
// prototypes of these functions here.
void showHelper      ( BSTreeNode *p, int level ) const;

// Data member
BSTreeNode *root;   // Pointer to the root node
};

讨论的函数是insert()。

我有以下代码:

template <typename DataType, class KeyType>
void BSTree< DataType,  KeyType>::insert(const DataType& newDataItem)
{
if(isEmpty())
    {
        root = new BSTreeNode(newDataItem, NULL, NULL);
    }
else
    {
        BSTreeNode *ptr = root;
        while(ptr != NULL)
            {
                if((*ptr)>dataItem > newDataItem)
                    {
                        ptr = ptr->left;
                    }
                else if((*ptr).dataItem < newDataItem)
                    {
                        ptr = ptr->right;
                    }
            }
        ptr = new BSTreeNode(newDataItem, NULL, NULL);
    }
}

,我收到以下错误:

44 E:School302Labs7BSTree.cpp no match for 'operator>' in 'ptr->BSTree<TestData, int>::BSTreeNode::dataItem > newDataItem' 
49 E:School302Labs7BSTree.cpp no match for 'operator<' in 'ptr->BSTree<TestData, int>::BSTreeNode::dataItem < newDataItem' 

我该如何处理?是否需要编写重载操作符,如果需要,如何开始?

在这里调用insert:

class TestData
{
  public:
void setKey ( int newKey )
    { keyField = newKey; }   // Set the key
int getKey () const
    { return keyField; }     // Returns the key
  private:
int keyField;                // Key for the data item
};
int main()
{
BSTree<TestData,int> testTree;   // Test binary search tree
TestData testData;               // Binary search tree data item
int inputKey;                    // User input key
char cmd;                        // Input command
print_help();
do
{
    testTree.showStructure();                     // Output tree
    cout << endl << "Command: ";                  // Read command
    cin >> cmd;
    if ( cmd == '+'  ||  cmd == '?'  ||
         cmd == '-'  ||  cmd == '<'     )
       cin >> inputKey;
    switch ( cmd )
    {
      case 'P' : case 'p' :
           print_help();
           break; 
      case '+' :                                  // insert
           testData.setKey(inputKey);
           cout << "Insert : key = " << testData.getKey()
                << endl;
           testTree.insert(testData);
           break;
}

我没有包括开关的其余部分,因为它在示例中不需要。

我假设这个问题是因为我正在比较两种不同的数据类型或尝试。我该怎么解决这个问题?

我用下面的代码解决了我的问题:

template <typename DataType, class KeyType>
void BSTree< DataType,  KeyType>::insert(const DataType& newDataItem)
{
BSTreeNode* temp = new BSTreeNode(newDataItem, NULL, NULL);
if(isEmpty())
    {
        root = temp;
    }
else
    {
        BSTreeNode* ptr = root;
        while(ptr != NULL)
            {
                if(ptr > temp)
                    {
                        ptr = ptr->left;
                    }
                else
                    {
                        ptr = ptr->right;
                    }
            }
        ptr = temp;
    }
}

template <typename DataType, class KeyType>
bool BSTree<DataType, KeyType>::BSTreeNode::operator>(const BSTreeNode*& other)
{
if((*other).dataItem < (*this).dataItem)
    {
        return true;
    }
return false;
}

我假设您的意思是在*ptr之后添加->而不是在

之后添加>
if((*ptr)>dataItem > newDataItem)

,尽管它仍然是不正确的。几个建议:

  1. 您没有处理数据项相等的情况。一个简单的解决方法就是用else替换else-if。
  2. (* ptr)。dataItem应替换为ptr->dataItem

仍然,从错误中看起来你需要重载<和>操作符的数据类型。你能把实际的电话号码更新一下你的帖子吗?

例如,查看传递给std::map的Compare模板形参。

你的模板应该调用它的Compare函数

它的默认比较方法应该是std::less。

如果一个类型定义了operator <,则它支持std::less;如果它不想这样做,那么它可以将一个非默认的比较函数作为模板参数传递给你的模板。

您也不需要定义operator >,因为您可以编写模板代码来测试if (b < a)而不是if (a < b)

您需要定义以下重载(注意,这是您需要做的,这还没有完成):

class BSTreeNode                  // Inner class: facilitator for the BSTree class
{
  public:
    // Constructor
    BSTreeNode ( const DataType &nodeDataItem, BSTreeNode *leftPtr, BSTreeNode *rightPtr );
    // New overloads
    inline bool operator< (const X& lhs, const X& rhs){ /* do actual comparison */ }
    inline bool operator> (const X& lhs, const X& rhs){return  operator< (rhs,lhs);}
    // Data members
    DataType dataItem;         // Binary search tree data item
    BSTreeNode *left,    // Pointer to the left child
               *right;   // Pointer to the right child
};

您还没有完成

你需要添加功能到你的btree来扩展这个Node重载

// Binary search tree manipulation operations
void insert ( const DataType& newDataItem );  // Insert data item
bool retrieve ( const KeyType& searchKey, DataType& searchDataItem ) const;
inline bool operator< (const X& lhs, const X& rhs){ return this->dataItem->operator<(lhs,rhs); }
inline bool operator> (const X& lhs, const X& rhs){ return this->dataItem->operator>(lhs,rhs); }

我们可以将它们全局定义为命名空间

的一部分
namespace MyBSTree 
{
  inline bool operator< (const X& lhs, const X& rhs){ return this->dataItem->operator<(lhs,rhs); }
  inline bool operator> (const X& lhs, const X& rhs){ return this->dataItem->operator>(lhs,rhs); }
}

您可以提取最后一个值,而不是在比较中使用节点对象。深入为内部值创建一个get,这样比较的是基本数据类型,而不是对象。

我也有这本书。我发现,因为我们通过DataType参数获得了对象的"容器"类型,所以我可以实例化一个保存DataType的项目并调用. getkey()函数。效果很好。这可能已经超过了截止日期,但这个想法对书中的其他结构有很大帮助。以下是我的意思。

template<typename DataType, typename KeyType>
void BSTree<DataType,KeyType>::insert ( const DataType& newDataItem )
   {
    DataType hold = newDataItem;
    KeyType holdKey = newDataItem.getKey(); //All our parameters must have getKey() return int
    insertHelper( root, holdKey, newDataItem ); // or however yours went
   }

这允许您通过创建虚拟持有人并调用虚拟的. getkey()来比较键值。

编辑:对不起,把错误的收件人数据类型作为getKey返回,但你应该得到的想法。字符串有一个内置的比较操作符,因此您不必为每个类/结构重写它。