2012-04-05 1 views
1

정말 붙어있어, "CTree.add (num);"에서 오류가 발생했습니다. 'CTree'는 선언되지 않았다. tree.h에서 초기화했기 때문에 의미가 없다.이진 검색 트리 문제

프로그램이 사용자에게 프롬프트를 표시하고 사용자가 명령을 입력하면 (예 : "add 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 directoryTree; CTree fileTree; CTree indexTree; 

...

행운을 빌어 요, 하나를 인스턴스화하지 않습니다. –

답변

5

add는 단지 CTree 인스턴스의에 호출 할 수 있다는 것을 의미 비 정적 멤버 함수이다. 예 :

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

이것은 불행히도 나를 위해 작동하지 않았다. 나는 당신이 의미하는 것을 본다. 이제 "CTree myTree;"를 초기화 할 때 오류가 발생합니다. – conman

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) 

을 또한 경고를 컴파일러에주의를 기울입니다. 좋은 연습은 그들 모두를 돌보는 것입니다. 그리고 이것은 컴파일이되고 작동하지 않는다는 것을 기억하십시오. 그것은 끝나지 않은 미완성이고 거친 것처럼 보인다.

그리고 클래스 (아이디어)와 인스턴스 (해당 아이디어의 표현)의 차이점을 기억하십시오. 기술 세부 사항은 지금 중요하지 않습니다. 클래스 설계가 의도하는대로 작업 할 인스턴스가 있는지 확인하십시오. 컴퓨터 소프트웨어가 어떻게 작동하는지, 컴퓨터 소프트웨어가 작동하는 방법과 특히 메모리의 관점에서 어떻게 연결되는지에 대해 이해하지 못하는 것 같습니다. 컴퓨터가 당신이 원하는 것을 알기에 충분하지 않고, 수행 할 작업 (어떤 변수 나 객체 또는 what-have-you)을 원하는지를 알아야합니다. 값으로 복사하여 되돌리고, 주 함수에서 수행하고, 주소가있는 참조 또는 포인터를 전달하여 메모리에있는 객체/인스턴스의 위치를 ​​알 수 있습니다. 실험 중이라면 글로벌 인스턴스. 많은 옵션이 있습니다.

모든 항목을 다시 선언하면 이전에 발생한 변경 사항이 이전되지 않습니다 (항목이 범위를 벗어나기 때문에). 또한 클래스 수준에서 비 정적 멤버 메서드를 호출하는 것은 의미가 없으며 적절하지도 않습니다.

도움이되고 즐거운 코딩이 되길 바랍니다. 그럴만 한 가치가있는 것은 아무 것도 없다.

+0

나는 트리의 각 요소에 대한 포인터를 생성해야한다는 것을 의미하는 인스턴스를 따르지 않는다. 나는 CTree 클래스의 "tree.h"에서 개인적으로 그렇게했다고 생각했다. – conman

+0

클래스를 정의했습니다. 클래스는 객체가 만들어지는 청사진이라고 생각할 수 있습니다. 찰스 워드 (Charlesworth)의 사례에서 보여준 것과 같은 인스턴스가 필요합니다. 그러나 당신은 또한 그것에 대한 적극적인 참조를 유지해야합니다, 그래서 당신은 그것에 대한 작업을 할 수 있습니다. 이 포인터는 클래스의 모든 비 정적 함수에 대한 자동 인수이며 m_intVar, this-> m_intVar와 같은 멤버 데이터의 모든 변경 사항에 배치됩니다. 그런 식으로 올바른 의미의 메모리 오프셋 (또는 올바른 개체/인스턴스)에서 작동합니다. 코드를 컴파일하도록 내 대답에 편집을 확인하십시오. –

+0

한숨 나는 프로그래밍 방식을 간략하게하기 위해 C에서 C++로 전환하고 있습니다. 코드를 편집하고 컴파일합니다. 혼자서 고맙습니다. 하지만 여전히 런타임 오류가 발생하고 있습니다. – conman

0

나는 그들이 당신의 경험 수준에 대해 약간의 기술을 얻고 있다고 생각합니다. YourCTree 클래스 코드는 CTree 클래스가 무엇이며 어떻게 동작하는지 (청사진) 만들지 만 실제로 코드를 생성하고 참조 할 수있는 방법을 알려야합니다.

는이 같은 스택 변수 인스턴스를 선언 할 수

CTree myTree; 

이 당신의 클래스에 대한 메모리를 할당하고 함수 진입에 생성자를 호출합니다. 그런 다음 점 표기법을 사용하여 인스턴스 이름에서 함수를 참조하여 작업합니다.

myTree.Add(4); 

또는 당신은 CTree에 대한 포인터를 선언하고 포인터 표기법을 사용하여 트리를 참조 그런 다음 new 연산자

CTree *myTree; 

myTree = new CTree(); 

를 사용하여 동적 인스턴스를 만들 수 있습니다 : 당신이 경우

myTree->Add(4); 

을 그렇게하면 할당 된 메모리를 삭제해야합니다.

delete myTree; 

요약하면 여기에 표시되는 종류의 클래스 정의는 클래스를 나타내지 만 클래스를 작성하지는 않습니다 (메소드 코드에 대한 메모리 및 설정 포인터 할당). 이것은 당신의 코드 로직이 그들을 필요로한다면 당신은 많은 나무를 가질 수 있습니다; 당신이 실제로 당신의 헤더 파일에 그냥 변수의 이름을 선언하는 CTree``의 인스턴스를 생성하지

+0

* 한숨 * 프로그래밍의 간결함을 사과드립니다. C에서 C++로 전환하고 있습니다. 코드를 편집하고 컴파일합니다. 혼자서 고맙습니다. 하지만 여전히 런타임 오류가 발생하고 있습니다. – conman