2014-02-23 3 views
0

나는 모든 종류의 (등 INT, 플로트, 문자열)파일에 일반 트리를 저장하려면 어떻게해야합니까?

template<class T> class Tree { 
public: 
// Class interface 
private: 
T node; 
std::list<Tree<T>*>* children; 
}; 

를 저장할 수있는 C++로 작성된 일반적인 트리 구현을하고 난 입력 소스 트리로 받아 프로그램 (C++로 작성된)이 (파일에 저장된) 규칙 집합을 기반으로 다른 트리를 출력 할 수 있습니다.

Any instance of class A become an instance of class X 
Any instance of class B become an instance of class Y 
Any instance of class C become an instance of class Z 

예를 들어, I는 (B (C))이 입력 트리 값이 가정 (노드 (A)는 아이로서 B를 갖고 B는 자식으로 C를 갖는다). 규칙의 파일을 기반으로 내 프로그램은이 트리 X (Y (Z))를 제공합니다. 내 질문은 : 어떻게 파일에 규칙 집합을 저장할 수 있습니까? 이 파일에 트리 유형을 저장하려면 어떻게해야합니까?

<translationUnit> 
    <from> 
    <A> 
     <B> 
     <C></C> 
     </B> 
    </A> 
    </from> 
    <to> 
    <X> 
     <Y> 
     <Z></Z> 
     </Y> 
    </X> 
    <to> 
</translationUnit> 

XML을 사용하여 규칙을 저장하려고하지만 클래스 유형을 어떻게 저장할 수 있습니까?

+0

Apache thrift 또는 Google Protobuf와 같은 일부 직렬화 라이브러리를 사용해야합니다. 그러나 데이터 유형으로서의 트리는 지원되지 않을 수 있으므로이를 해결해야합니다. 하지만 템플릿 클래스에서 작동하게하는 것은 실제 문제가 될 것입니다. ( –

+0

고마워요 ... –

+0

_ '나는 XML을 사용하여 규칙을 저장하려고하지만 어떻게 클래스 유형을 저장할 수 있습니까?' XML의 경우, 엘리먼트 이름이나 열거 형 속성과 같은 어떤 종류의 식별자가 필요할 것입니다 .BTW,'Tree *'et.al. –

답변

0

트리의 각 값에 대해 유형을 연결해야합니다. 따라서 트리의 각 요소는 값과 값의 유형 및 자식 목록의 쌍입니다. 파일에서 각 노드에 대해이 정보를 저장해야합니다.

당신은 json이 트리의 직렬화 된 버전을 저장한다고 생각할 수 있습니다. 읽기 쉽고 많은 좋은 C++ 라이브러리가 존재합니다. 예를 들어, 입력 나무가 될 것입니다 : 당신이 원하는 경우

[ 
    { from: "A", to: "X" }, 
    { from: "B", to: "Y" }, 
    { from: "C", to: "Z" } 
] 

: 각 유형 변환을 저장할 수

{ 
    type: "X", 
    value: "value of the first node, 
    children: [ 
     { 
      type: "Y" 
      value: "a value ...", 
      children: [ 
        { 
         type: "Z", 
         value: "a value ...", 
        } 
      ] 
     } 
    ] 
} 

및 구성 파일 :

{ 
    type: "A", 
    value: "value of the first node, 
    children: [ 
     { 
      type: "B" 
      value: "a value ...", 
      children: [ 
        { 
         type: "C", 
         value: "a value ...", 
        } 
      ] 
     } 
    ] 
} 

당신의 결과가 될 것입니다 A와 B가 기본 유형을 공유해야하고, 포인터를 사용하여 노드 구성원을 저장해야합니다. 당신이 관리하지 않는 경우 수동으로 unique_ptr 사용 : 당신이 나무에 대한 포인터의 목록에 대한 포인터를 가지고, 그 후

unique_ptr<T> node; 

을 당신이를 피하려면, 그것을 관리하는 포인터의 많은이야 포인터를 목록에 추가하면 불완전한 형식의 컨테이너를 허용하는 boost::container::list을 사용할 수 있습니다. 그런 다음 목록에 저장된 트리에 대한 포인터를 가질 필요가 없으며 Tree 값이 작업을 수행합니다.

boost::container::list<Tree<T> > children; 
+0

아이디어가 훌륭하지만 왜 unique_ptr을 사용하여 부스트리스트를 개선해야하는지 설명해 주시겠습니까? 당신의 대답은 json의 xml istead에서 작동합니까? – WileTheCoyot

+0

코드를 읽었을 때, T가 트리의 모든 값에 대한 기본 유형이되어야하지만 그렇지 않으면 트리는 T의 트리가됩니다. 즉, 트리는 가질 수 없게됩니다. children B. B의 트리입니다. 여기에 다형성 타입이 필요합니다. 다형성 타입이 있다면 포인터를 사용해야합니다. 포인터가 있으면 고유 포인터가 RAII를 적용하는 데 좋습니다. boost :: container :: list는 목록에 대한 원시 포인터를 피하기 위해 여기에 있습니다. 물론 json 대신 xml을 사용할 수 있습니다. serialization 형식 인 –

+0

입니다. 왜냐하면 완성되었으므로뿐만 아니라 unique_ptr 및 boost list에 대한 팁을 제공했기 때문에 답을 수락했습니다. – WileTheCoyot

0

노드 간의 관계에 대한 포인터를 사용하는 것 같습니다. 예 :

class node{ 
int value; 
node* first_child; 
node* next_sibling; 
}; 

포인터 대신 색인을 사용하여 직렬화 노드를 만들 수 있습니다. 다음과 같습니다.

class node2{ 
    int value; 
    int id_first_child; 
    int id_next_sibling; 
}; 

이제 트리를 플랫 할 수 있습니다. 그것을 배열로 바꾸는 것을 의미합니다.

모든 노드를 포인터에 벡터의 인덱스로 변환하는 데 사용되는 vector<node*>map<node*,int>에 대한 포인터를 추가합니다.

은 이제 포인터 대신 색인을 사용하여 노드에 파일을 씁니다.

파일에서 읽을 때 반대 방향으로해야하고 색인을 포인터로 변환하십시오.

+0

귀하의 솔루션을 사용하여 어떻게 포인터를 int로 변환합니까? 지도를 저장해야합니까? 또한 포인터를 저장할 필요가 없습니다. 파일을로드 할 때 트리를 다시 작성할 수 있습니다. – WileTheCoyot

+0

아니요, 나무는 일반적으로이 방법으로 저장되지 않습니다. 이는 프로그래머의 노력을 낭비하는 것입니다. 대신, 나무는 대개'(root, [child1, child2, ... childN])'과 같이 재귀 적으로 저장됩니다. 여기서'root'는 루트 노드의 값이고'left'와'right'는 어린이. 빈 트리는'()'입니다. 이것은 단지 예일 뿐이며 구분 기호 (괄호, 대괄호 및 쉼표)를 노드 값과 구분할 수 있다면 실제 형식은 거의 모든 것이 될 수 있습니다. –

+0

지금은 파서가 많이 있기 때문에 sav 트리에 xml을 사용하지만 아이디어는 매우 좋습니다 – WileTheCoyot

관련 문제