1

我真的被卡住了,我在“CTree.add(num);”处遇到错误 说“CTree”是未声明的,这没有意义,因为我在 tree.h 中对其进行了初始化?

该程序应该提示用户,用户输入一个命令(即“加 3”,只有 0-9 个整数),然后我希望它将该数字插入树中。

//File: tree.h

class CTree
{
private:
    CTree* m_pLeft;
    CTree* m_pRight;
    CTree* m_pRoot;
    int m_nData;

public:

    CTree();

    bool isEmpty() const { return m_pRoot; }
    bool search(int);
    void print_inorder();
    void inorder(CTree*);
    void Add(int);
    void remove(int);
    void height();
};

//File: CTree.cpp

#include <iostream>
#include <cstdlib>

using namespace std;

CTree::CTree()
{
 m_pRoot=NULL;
}

bool CTree::search(int x)
{
    if(x==m_nData) return true;
    if(x < m_nData){ //go left
       if(m_pLeft != NULL) //if possible
            return m_pLeft->search(x);
    }
    else //go right
       if(m_pRight != NULL) //ifpossible
            return m_pRight->search(x);
    return false;
}

void CTree::Add(int x)
{
CTree* t = new CTree;
CTree* parent;
t->m_nData = x;
t->m_pLeft = NULL;
t->m_pRight = NULL;
parent = NULL;

if(isEmpty()) m_pRoot = t;
else
{
     //insert leaf nodes
    CTree* leaf;
    leaf = m_pRoot;
     // find parent
    while(leaf)
    {
        parent = leaf;
        if(t->m_nData > leaf->m_nData)
            leaf = leaf->m_pRight;
        else
            leaf = leaf->m_pLeft;
    }

    if(t->m_nData < parent->m_nData)
       parent->m_pLeft = t;
    else
       parent->m_pRight = t;
}
}

void CTree::remove(int x)
{
bool found = false;
if(isEmpty())
{
    cout<< "Tree is empty!" <<endl;
    return;
}

CTree* current;
CTree* parent;
current = m_pRoot;

while(current != NULL)
{
     if(current->m_nData == x)
     {
        found = true;
        break;
     }
     else
     {
         parent = current;
         if(x > current->m_nData) current = current->m_pRight;
         else current = current->m_pLeft;
     }
}
if(!found)
{
    cout<< "Not found!" <<endl;
    return;
}

// Node with single child
if((current->m_pLeft == NULL && current->m_pRight != NULL)|| (current->m_pLeft != NULL&& current->m_pRight != NULL))
{
   if(current->m_pLeft == NULL && current->m_pRight != NULL)
   {
       if(parent->m_pLeft == current)
       {
         parent->m_pLeft = current->m_pRight;
         delete current;
       }
       else
       {
         parent->m_pRight = current->m_pRight;
         delete current;
       }
   }
   else // left child present, no right child
   {
      if(parent->m_pLeft == current)
       {
         parent->m_pLeft = current->m_pLeft;
         delete current;
       }
       else
       {
         parent->m_pRight = current->m_pLeft;
         delete current;
       }
   }
 return;
}

             //We're looking at a leaf node
             if( current->m_pLeft == NULL && current->m_pRight == NULL)
{
    if(parent->m_pLeft == current) parent->m_pLeft = NULL;
    else parent->m_pRight = NULL;
                             delete current;

//Node with 2 children
// replace node with smallest value in right subtree
if (current->m_pLeft != NULL && current->m_pRight != NULL)
{
    CTree* check;
    check = current->m_pRight;
    if((check->m_pLeft == NULL) && (check->m_pRight == NULL))
    {
        current = check;
        delete check;
        current->m_pRight = NULL;
    }
    else // right child has children
    {
        //if the node's right child has a left child
        // Move all the way down left to locate smallest element

        if((current->m_pRight)->m_pLeft != NULL)
        {
            CTree* lcurrent;
            CTree* lcurrent_parent;
            lcurrent_parent = current->m_pRight;
            lcurrent = (current->m_pRight)->m_pLeft;
            while(lcurrent->m_pLeft != NULL)
            {
               lcurrent_parent = lcurrent;
               lcurrent = lcurrent->m_pLeft;
            }
            current->m_nData = lcurrent->m_nData;
            delete lcurrent;
            lcurrent_parent->m_pLeft = NULL;
       }
       else
       {
           CTree* tmp;
           tmp = current->m_pRight;
           current->m_nData = tmp->m_nData;
           current->m_pRight = tmp->m_pRight;
           delete tmp;
       }

    }
             return;
}
}
}

void CTree::print_inorder()
{
 inorder(m_pRoot);
}

void CTree::inorder(CTree* x)
{
  if(x != NULL)
{
    if(x->m_pLeft) inorder(x->m_pLeft);
    cout<<" "<<x->m_nData<<" ";
    if(x->m_pRight) inorder(x->m_pRight);
}
else return;
}

//File: main.cpp

#include <iostream>
#include <cstdlib>
#include <sstream>
#include <locale>
#include <string>
#define PROMPT "bst> "

using namespace std;

int getNumber(string s)
{
    int num;

for(int i; i<=s.length();i++)
{
        if(isdigit(s[i]))
        {
              num= s[i]-48;
        }
}

return num;
} // getNumber

bool process(const string& s, CTree* aTree)
{
    bool mustquit=false;
    int num;
    istringstream iss(s);

do
{
    string sub;
    iss >> sub; //               
    if(sub=="add" || sub=="insert")
    {
        num=getNumber(s);
        cout<<num<<endl;
        aTree->Add(num);
    }
    else if(sub=="delete" || sub=="remove")
    {
        num=getNumber(s);
        cout<<num<<endl;
    }
    else if(sub=="search" || sub=="find")
    {
         num=getNumber(s);
         cout<<num<<endl;
    }
    else if(sub=="height")
    {
         //do stuff
    }
    else if (sub=="quit") 
        return mustquit;
    //else cout<<"INPUT ERROR"<<endl;    
 }  while (iss);     




 return mustquit;
 }// process


int main(){ 

string input="";
CTree *myTree;
myTree = new CTree();

bool finished=false;
int i;


    cout<<PROMPT;
    while(!finished)
    {
            if(input!="")cout<<PROMPT;
            getline(cin,input);
            finished=process(input, myTree);
            delete myTree;
    }//while

return 0;
}
4

3 回答 3

5

add是一个非静态成员函数,这意味着您只能在CTree. 例如

CTree myTree;
myTree.add(num);
于 2012-04-05T00:52:36.387 回答
1

你知道你需要一个类的实例CTree来实际使用它吗?您在假设您正在对类的实例进行操作的情况下编写了整个内容。一棵实际的树,而不是它的蓝图

正如我之前的答案所说,它不是静态函数或类级别。需要在实例上调用非静态方法,以便可以将静默指针this设置为有意义的东西,即。您正在使用的实际实例 - 在这种情况下添加一个节点。

附录

(下面的所有内容都可以在不修改您的代码的情况下工作,只是对您的问题的明确回答,以使其编译。从“工作的角度”来看,该程序远未完成。有些部分甚至没有意义,许多变量未使用或未初始化(然后使用)。让我在下面进一步详细说明。)

你需要做的就是在你的 main 中添加旧的 process() 调用:

CTree myTree; // you could also add (), even though it's a default constructor
finished=process(input, myTree);

并修改函数进程的参数列表以包含对您希望操作的树的引用。这只是其中一种可能性,您也可以使用指针等。但是引用更清晰:

bool process(const string& s, CTree& aTree)

另外,请注意编译器警告。好的做法是照顾好所有人。请记住,这使它编译,而不是工作。它似乎未完成且边缘粗糙。

并记住类(一个想法)和一个实例(该想法的体现)之间的区别。技术细节现在并不重要,只要确保你有一个可以使用的实例,就像你的类设计想要的那样。在我看来,您似乎不了解计算机软件的工作原理,在其上运行的数据和指令如何连接,尤其是从内存的角度来看。计算机只知道你想做什么是不够的,它需要知道你想要执行什么操作(哪些变量或对象或你有什么)。您可以按值复制并返回,在主函数中执行此操作,传递带有地址的引用或指针,以便它可以知道您的对象/实例在内存中的位置等。如果您只是在试验,您可以创建一个全局实例。很多选择。

重新声明所有内容不会延续之前发生的更改(因为内容超出了范围)。在类级别调用非静态成员方法也没有意义——甚至不正确。

希望它有所帮助并快乐编码。坚持下去,没有什么值得做的事情是简单的。

于 2012-04-05T01:14:18.727 回答
0

我认为他们对你的经验水平来说有点太技术化了。YourCTree 类代码创建 CTree 类是什么以及它的行为方式(蓝图),但实际上您必须告诉您的代码构造一个,然后有一种方法来引用它。

您可以像这样声明堆栈变量实例:

CTree myTree;  

这会为您的类分配内存并在进入函数时调用构造函数。然后,您可以通过使用点表示法从实例名称中引用函数来使用它。

myTree.Add(4);

或者您可以声明一个指向 CTree 的指针并使用 new 运算符创建一个动态实例

CTree *myTree;

myTree = new CTree();

然后使用指针表示法引用树:

myTree->Add(4);

如果你这样做,你将需要删除你分配的内存

delete myTree;

因此,总而言之,您在此处显示的类定义描述了一个类,但不会创建一个类(分配内存并设置指向方法代码的指针)。如果您的代码逻辑需要它们,这允许您拥有许多树;

CTree directoryTree;
CTree fileTree;
CTree indexTree;

这些每个都有自己的数据......

祝你好运,

于 2012-04-05T03:14:19.443 回答