2012-04-05 241 views
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; 
} 
+0

你從來沒有真正在你的頭文件創建CTree'的'實例你只是聲明變量的名稱,而不是實例化一個。 – 2012-04-05 00:53:28

回答

5

add是一個非靜態成員函數,這意味着你只能把它叫做上實例CTree。例如

CTree myTree; 
myTree.add(num); 
+0

這不適用於我不幸的。我明白你的意思了。現在我在初始化「CTree myTree;」時出錯。 – conman 2012-04-05 01:26:47

1

你都知道,你需要一個實例的類CTree實際使用它的?你假設你正在使用一個類的實例來編寫整個事情。一個實際的樹,而不是一個藍圖它。

正如我之前所說的答案,它不是一個靜態函數或類級別。需要在實例上調用非靜態方法,以便可以將無聲指針this設置爲有意義的,即。你正在使用的實際實例 - 在這種情況下添加一個節點。

附錄

(下面一切正常,而無需修改代碼,只是一個明確的回答你的問題,使之編譯。從「工作的角度來看」,該計劃還遠遠沒有完成。有些片斷甚至沒有意義,許多變量都沒有被使用或未初始化(然後使用),下面進一步詳細說明)

你需要做的是在主進程中添加這個舊進程()發生呼叫:

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

並修改函數進程的參數列表,以包含您希望對其操作的樹的引用。這僅僅是一種可能性,你也可以採取一個指針等,但一提的是清潔:

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

此外,要注意編譯器警告。良好的做法是照顧他們所有人。請記住,這使得它編譯,而不是工作。似乎邊緣未完成和粗糙。

並記住一個類(一個想法)和一個實例(該想法的表現)之間的差異。技術細節現在並不重要,只要確保你有一個實例可以使用,就像你的課堂設計的意圖一樣。在我看來,你並沒有掌握計算機軟件是如何工作的,數據和操作指令如何連接,特別是從內存角度來看。計算機不知道你想要做什麼,它需要知道你想要什麼操作執行(哪些變量或對象或什麼你)。您可以通過值複製並返回,在主函數中執行此操作,將引用或指針傳遞給地址,以便它可以知道內存中的對象/實例位於何處等。如果您只是試驗,可以創建一個全局實例。很多選擇。

重新聲明一切並沒有帶來以前發生的變化(因爲東西超出了範圍)。在課堂級別上調用非靜態成員方法也是沒有意義的 - 甚至不適當。

希望它有助於和快樂的編碼。堅持下去,沒有什麼值得做的事很簡單。

+0

我沒有跟隨,一個實例,我需要創建一個指向樹的每個元素的指針?我以爲我在CTree類的「tree.h」下做了這個。 – conman 2012-04-05 01:31:56

+0

你已經定義了一個類。一個類可以被認爲是製作對象的藍圖。你現在需要一個例子,就像Charlesworth先生的例子所顯示的那樣。但是你也需要積極參考它,所以你可以對它進行操作。這個指針對類的每個非靜態函數都是一個沉默的參數,然後將其放置在成員數據的每個變化中,比如m_intVar到this-> m_intVar。這樣,它是有道理的,並在正確的內存偏移量(或正確的對象/實例)上運行。檢查我的答案上的編輯,使您的代碼編譯。 – 2012-04-05 02:59:00

+0

嘆息我只是從C切換到C++,所以我爲編程的簡短而道歉。我編輯了代碼並編譯。所以非常感謝你的支持。但我仍然遇到運行時錯誤 – conman 2012-04-06 22:35:32

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; 

這些將各自有自己的數據...

祝你好運,

+0

*嘆*我只是從C切換到C++,所以我爲編程的簡潔性而道歉。我編輯了代碼並編譯。所以非常感謝你的支持。但是我仍然遇到運行時錯誤。 – conman 2012-04-05 06:34:07