二叉搜索树

时间:2014-03-10 17:36:08

标签: c++ tree binary-search-tree

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

我的问题是,由于它是模板化的,我不确定在插入或查找时如何对数据项进行比较。

这是头文件:

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:\School\302\Labs\7\BSTree.cpp no match for 'operator>' in 'ptr->BSTree<TestData, int>::BSTreeNode::dataItem > newDataItem' 

49 E:\School\302\Labs\7\BSTree.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;
}

4 个答案:

答案 0 :(得分:0)

我假设您打算添加一个 - &gt;在* ptr之后而不是&gt;之后

if((*ptr)>dataItem > newDataItem)

虽然它仍然是不正确的。几点建议:

  1. 当数据项相等时,您不处理该条件。一个简单的解决方法就是用else替换else-if。
  2. (* ptr).dataItem应替换为ptr-&gt; dataItem
  3. 仍然,从错误看起来你需要重载&lt;和&gt;您的数据类型的运算符。你能用实际的通话代码更新你的帖子吗?

答案 1 :(得分:0)

例如,请查看Compare template parameter passed to std::map

您的模板应调用其比较功能。

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

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

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

答案 2 :(得分:0)

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

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
};

您尚未完成

您需要向BSTree添加功能以扩展此节点重载

// 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); }
}

OR

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

答案 3 :(得分:0)

我有同样的书。我发现因为我们得到了#34;容器&#34;通过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返回,但你应该明白这一点。字符串有一个内置的比较运算符,因此您不必为每个类/结构重写它。