【问题标题】:Binary Search Trees二叉搜索树
【发布时间】:2010-10-26 22:46:16
【问题描述】:

我有一个关于 C++ 中的二叉搜索树实现的问题。 这是下面的问题

实现一个存储整数的简单(非模板)BST。提供如下操作:Insert、Remove、inOrder遍历、preOrder遍历、postOrder遍历。

使用递归例程来处理树。

处理一个节点只涉及打印出节点的内容,在这种情况下,它是存储在节点中的整数。

数据应该来自测试文件。主程序应打开数据文件并插入树并演示其他树操作。

本练习的目的是证明您了解 BST。没有必要过度使用它并进行未要求的操作。

到目前为止,我只创建了头文件。任何人都可以看看并建议我是否朝着正确的方向前进?

using namespace std;
#ifndef BSTNODE_H
#define BSTNODE_H
class BSTNode
{
    private:
    //Defines the 'node' structure
    struct tree_node 
    {
     tree_node *left;   // left subtree has smaller elements
     tree_node *right;  // right subtree has larger elements
     int m_data;
    };
    //root * r;
    public:
        //The Constructor
        BSTNode();
        //The Destructor
       ~BSTNode();
       //Inserts a value into a BST, public function
        void insert(const m_data & d);
        //Removes a value from a BST, public function
        void remove(const m_data & d);
        //isEmpty function, public function
        bool isEmpty();
        BSTNode getData();
        void inOrder(const m_data & d);
        void preOrder(const m_data & d);
        void postOrder(const m_data & d);
};
#endif

接下来我必须创建 BSTNode.cpp 文件。感谢您通过邮件回复 jediknight80n@hotmail.com 提前致谢。

【问题讨论】:

  • 是否应该将遍历函数实现为迭代器...?我不太了解 C++ 约定,无法将其添加为答案。
  • 永远不要:使用命名空间标准;在头文件中。

标签: c++ recursion binary-tree implementation


【解决方案1】:

您似乎忘记了 typedef 在各种方法中使用的 m_data 类型,我不明白您为什么要单独的 tree_node 结构(而不​​是使用类本身? ) 也不知道为什么getData 应该返回BSTNode 而不是int

【讨论】:

    【解决方案2】:
       //Inserts a value into a BST, public function
        void insert(const m_data & d);
        //Removes a value from a BST, public function
        void remove(const m_data & d);
        //isEmpty function, public function
        bool isEmpty();
        BSTNode getData();
        void inOrder(const m_data & d);
        void preOrder(const m_data & d);
        void postOrder(const m_data & d);
    

    m_data 是成员,而不是类型。你应该在这里使用 int 。此外,由于您的节点是 tree_node,因此外部类可能应该将树作为一个整体来表示(即 BSTree 而不是 BSTNode)。

    还有'使用命名空间标准;'标题是邪恶的,因为它会强制包含标题的任何内容而无法选择退出。如果您要使用它,我建议将其保存为 .cpp 文件。

    【讨论】:

    • 似乎没有必要使用'using namespace std;'在标题中 - 我看不到任何来自它的东西。
    【解决方案3】:

    这是一个关于 BST 的经典问题 - 任何关于数据结构的好书都会为您提供完整的代码。以下页面包含 C++ http://cslibrary.stanford.edu/110/BinaryTrees.html 的代码示例。

    遍历函数不应该是 BST 类本身的一部分,事实上 BSTNode 应该公开左/右节点指针 - 调用应用程序应该以特定方式调用它。或者使用回调函数,在你的类里面提供遍历代码,这样会干净很多。

    【讨论】:

      【解决方案4】:

      一些事情 - 正如其他人指出的那样,您将不得不使用

      void insert(const int & d);
      //Removes a value from a BST, public function
      void remove(const int & d);
      //isEmpty function, public function
      bool isEmpty();
      BSTNode getData();
      void inOrder(const int & d);
      void preOrder(const int & d);
      void postOrder(const int & d);
      

      另一件事是你已经注释掉了你的根节点。尽管您定义错误,但您必须在类中包含一个根节点。正确的定义是

      tree_node *root;
      

      另外,如前所述,删除

      使用命名空间标准;

      从头文件中改为将其放入您的实现文件中。

      这就是我现在所能看到的。

      【讨论】:

        【解决方案5】:

        另一个问题是指定的类声明了一个嵌套类型和方法,但没有成员数据。


        您可以使用迭代器声明遍历功能:例如preorder 方法返回一个 interator,您可以取消对节点的引用,或者递增以指向 preorder 序列中的下一个节点。

        或者,您可以使用回调声明遍历功能:即调用者将回调实例传递给预排序方法,预排序方法遍历树并为每个节点调用回调方法:回调方法将采用一个节点(或者,更具体地说,节点数据)作为参数,并可能返回一个布尔值,让回调指定它想要终止遍历。

        【讨论】:

          【解决方案6】:

          我也会添加一个搜索方法。

          bool search(int whatIlookfor);
          

          甚至更好

          tree_node* search(int whatIlookfor);
          

          另外,请将tree_node *root 保存在安全的地方。

          【讨论】:

            【解决方案7】:

            一些琐碎的事情:

            tree_node *left;   // left subtree has smaller elements
            

            一般来说,左子树也包含相等的元素。

            【讨论】:

            • 这取决于实现,您可能不会立即包含它们以避免在二叉搜索树中出现重复节点。
            • 确实如此 - 这取决于实施。但是,我只想指出,如果 OP 还没有插入相等的元素,那么他应该关注插入相等的元素。
            【解决方案8】:
            • 在您的示例中使用结构类型的左右指针会限制灵活性 - 假设我采用您的 BST 并遍历根的左子节点,然后想要在这个新子树上调用操作。我不能,因为指针是结构类型的。我宁愿建议使用 BSTNode 类型的两个指针。

              BSTNode *left;

              BSTNode *right;

              这也将解决您的根问题(不需要显式根指针),因为您用于在 main 中引用您的对象的指针无论如何都会指向根。

            • 当遍历函数本质上遍历整个树并打印所有数据项时,它们不应需要任何参数。数据项可以传递给另一个搜索成员函数以搜索其位置,正如 TrueStar 已经指出的那样。

            • 我还建议使用一些私有成员函数来降低公共成员函数的复杂性(DeleteNodeCaseB(int data) 会一次又一次地调用DeleteNodeCaseA(int data))-

              BSTNode * setleft(int data);

              BSTNode * setright(int data);

              void DeleteNodeCaseA(int data) /* 左右孩子中的一个或两个都不存在 */

              void DeleteNodeCaseB(int data) /* 有左右孩子 */

            【讨论】:

              【解决方案9】:

              由于您使用的是 C++,您可能想要考虑使用一些标准库而不是尝试自己实现所有这些? STL 库带有一个红黑树,它可能更适合您的应用程序。二叉树可能会变得不平衡或退化为链接列表。

              PS:当然,这是假设你没有做家庭作业。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2023-03-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多