2017-03-18 70 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的遞歸調用,我寫了另一種方式 –