2017-03-18 67 views
0

我想保存我的二叉树到txt文件。下面是我有二叉树文件与超载ostream和两个类

qt.h 
#ifndef QT_H_INCLUDED 
#define QT_H_INCLUDED 

#include<iostream> 

using namespace std; 

template<typename T> 
class Node{ 
    T data; 
    Node<T> *left; 
    Node<T> *right; 
public: 
    Node(T d) : data(d), left(nullptr), right(nullptr){} 
    void print(){ 
     cout << data << endl;} 
    T getData()const { 
     return data; 
    } 
    void setData(const T &value){ 
     data = value; 
    } 
    template<typename X> friend class Tree; 
    template<T> friend ostream& operator<<(ostream &os, Node &n); 
}; 

template<typename T> 
ostream& operator<<(ostream &os, Node<T> &n){ 
    os << n->data; 
    return os; 
} 
#endif // QT_H_INCLUDED 

然后tree.h中

#ifndef TREE_H_INCLUDED 
#define TREE_H_INCLUDED 

#include "qt.h" 
#include <fstream> 
#include <iostream> 
namespace std; 

template<typename T> 
class Tree{ 
    Node<T> *root; 
    void insertIntoTree(T &d, Node<T> *&r); 
    void printTree(Node<T> *r); 
    void deleteTree(Node<T> *&r); 
    Node<T>* findInTree(T &d, Node<T> *r, Node<T> *&parent); 
    void deleteLeaf(Node<T> *p, Node<T> *q); 
    void deleteInBranch(Node<T> *p, Node<T> *g); 
    void zapisDoSouboru(Node<T> *r); 
public: 
    Tree() : root(nullptr){} 
    ~Tree(){ 
     clean(); 
    } 
    bool find(T d){ 
     Node<T> *dummy=nullptr; 
     return findInTree(d, root, dummy); 
    }; 
    void clean(){ 
     deleteTree(root);} 
    void insert(T d){ 
     insertIntoTree(d, root);} 
    void print(){ 
     printTree(root); 
    } 
    bool deleteNode(T d); 
    void zapis(){ 
     zapisDoSouboru(root); 
    } 
} 


template<typename T> 
void Tree<T>::zapisDoSouboru(Node<T> *r){ 
    fstream f; 
    f.open("mytext.txt", ios_base::app); 
    if(r){ 
    f << r; 
    } 
    f.close(); 
    zapisDoSouboru(r->left); 
    zapisDoSouboru(r->right); 
} 

的想法是超负荷运营商< <的节点,然后使用递归的zapisDoSouboru并保存节点的节点。不幸的是它不起作用。 有谁知道,问题在哪里? 感谢您帮助

编辑 在

class Tree{ 
void zapis(ostream& f, Node<T> *r); 
public: 
void zapisDoSouboru(){ 
    fstream f; 
    f.open("mytext.txt", ios_base::app); 
    zapis(f, root); 
    f.close(); 
    } 
} 

template<typename T> 
void Tree<T>::zapis(ostream& f,Node<T> *r){ 
    if(r){ 
    zapis(f, r->left); 
    f << r; 
    zapis(f, r->right); 
    } 
} 

我改变了整个递归,但现在它看起来像它的工作原理,但它不写在文件中任何东西。不是对f的引用错误?该文件打开并关闭,zapis()遍历所有节点。

+0

请参考[如何提出一个好问题](http://stackoverflow.com/help/how-to-ask)。 当你没有详细说明什么不起作用时,不可能提供帮助。 – mcrlc

回答

0

在函数zapisDoSouboru中,您需要检查子节点是否为nullptr,否则只要它到达叶节点就会发生段错误。

下面是修改的版本: 模板

void Tree<T>::zapisDoSouboru(Node<T> *r){ 
    fstream f; 
    f.open("mytext.txt", ios_base::app); 
    if(r){ 
    f << r; 
    } 
    f.close(); 

    if(nullptr != r->left) { 
     zapisDoSouboru(r->left); 
    } 
    if(nullptr != r->right) { 
     zapisDoSouboru(r->right); 
    } 
} 
 

而且你为它不被编译器拿起节点定义操作。 这是一件您的操作者的代码:

template<typename T> 
ostream& operator<<(ostream &os, Node<T> &n){ 
    os << n->data; 
    return os; 
} 

可变n它通过引用传递与要与其->一个希望将指针访问它。代码编译的原因是因为当你调用f << r时,你实际上调用了Node<T>*的操作符,所以编译器不使用期望Node<T>&的模板函数。这意味着模板功能从未实例化。

我认为在这种情况下运营商超载没有多少必要。

  • 我想尝试的unique_ptr
  • 使用我会尽量避免使用友元类
  • 我会重构:你可以简单地调用r->getData()

    而且一般的事情,我一边看着代码注意在每次递归调用时不打开和关闭文件的代码

让我知道您是否需要任何说明

+0

谢谢,我现在要看看uniqe_ptr –

+0

现在我无法避开朋友班或递归电话,这是学校的任务,但我会牢记在心。我又经历了一次,超载运营商的错误“现在已经清楚了。随着zapisDoSouboru的递归调用,我写了另一种方式 –