2014-01-22 28 views
0

我正在學習C++,並且我將其指定爲項目來構建一個給定字符串的樹(例如「hello world hello one world」),它必須創建一個節點爲字符串中的每個不同的單詞,並且節點的一部分必須包含一個空間來保存單詞,另一個節點保存外觀的頻率(例如hello | 2,one | 1,world | 2),但是當我把單獨使用meter()函數的話是沒有問題的,但是問題是當我試圖獲取整個字符串的單詞時,出於一些奇怪的原因,只是將該字符串的最後一個單詞加入到樹中,字符串中的字數。我已經嘗試過用不同的方法來分割字符串中的字符串,將它們添加到樹中,但所有這些方法總是讓我得到相同的結果。C++中的二叉樹,用於添加帶有字詞頻率的字符串

#include <iostream> 
#include <conio.h> 
#include <cstring> 
#include <sstream> 

using namespace std; 

typedef char* tipo; 
typedef int tipo1; 

class Nodo{ 
    tipo1 f; 
    tipo dato; 
    Nodo *izq; 
    Nodo *der; 
    friend class Arbol; 
}; 

typedef Nodo* pNodo; 

class Arbol{ 
     pNodo raiz; 
     public: 
      Arbol(); 
      pNodo getRaiz(); 
      tipo getDato(); 
      void insertarNodo(tipo x, pNodo &p); 
      void meter(tipo x); 
      void eliminaNodo(tipo x, pNodo &p); 
      void eliminar(tipo x); 
      void inOrden(pNodo p); 
      tipo1 pertenece(tipo x, pNodo p); 
      tipo menor(pNodo p); 
      tipo1 pertenece1(tipo x); 
      int estaVacia(); 
      void arbolito(tipo x); 
}; 

Arbol::Arbol(){ 
     raiz=NULL; 
} 

pNodo Arbol:: getRaiz(){ 
     return raiz; 
} 

int Arbol:: estaVacia(){ 
    return raiz==NULL; 
} 

void Arbol::insertarNodo(tipo x, pNodo &p){ 
    if (p==NULL){ 
     p=new Nodo(); 
     p->f=1; 
     p->dato=x; 
     p->izq=NULL; 
     p->der=NULL; 
    } 
    else if(strcmp(x, p -> dato)<0){ 
      insertarNodo(x, p->izq); 
    } 
    else if(strcmp(x, p -> dato)>0){ 
      insertarNodo(x,p->der); 
    } 
    else if(strcmp(x, p -> dato)==0){ 
      p -> f ++; 
    } 
} 

void Arbol:: meter(tipo x){ 
    insertarNodo(x,raiz); 
} 

tipo Arbol:: menor(pNodo p){ 
    if (estaVacia()){ 
         return "Error: Arbol vacio"; 
    }else{ 
      if (p->izq==NULL){ 
          return p->dato; 
      }else{ 
       return menor(p->izq); 
      } 
    } 
} 

void Arbol:: eliminaNodo(tipo x, pNodo &p){ 
    if (p!=NULL){ 
        if (strcmp(x, p -> dato)==0){ 
        (p->f)--; 
        if (p->izq==NULL && p->f==0){ 
             pNodo q=p; 
             p=p->der; 
             delete q; 
        }else if(p->der==NULL && p->f==0){ 
          pNodo q=p; 
          p=p->izq; 
          delete q; 
        }else if(p->izq!=NULL && p->der!=NULL & p->f==0){ 
          tipo m=menor(p->der); 
          p->dato=m; 
          eliminaNodo(m,p->der); 
        } 
        }else if (strcmp(x, p -> dato)<0){ 
         eliminaNodo(x,p->izq); 
        }else{ 
         eliminaNodo(x, p->der); 
        } 
    }else{ 
      cout<<"No se encontro el dato"; 
    } 
} 

void Arbol:: eliminar(tipo x){ 
    eliminaNodo(x, raiz); 
} 

void Arbol:: inOrden(pNodo p){ 
    if (p!=NULL){ 
        inOrden(p->izq); 
        cout<<p->dato<<"="<<p->f<<endl; 
        inOrden(p->der); 
    } 
} 

tipo1 Arbol:: pertenece(tipo x, pNodo p){ 
    if (p==NULL){ 
       return 0; 
    } 
    if (p->dato==x){ 
        return p->f; 
    }else if(strcmp(x, p -> dato)<0){ 
      return pertenece(x, p->izq); 
    }else if(strcmp(x, p -> dato)>0){ 
      return pertenece(x,p->der); 
    } 
} 

tipo1 Arbol:: pertenece1(tipo x){ 
     return pertenece(x,raiz); 
} 

int main() 
{ 
    Arbol tree; 
    tipo a,b; 
    string x; 
    string s="hjk This is"; 
    s=s+" "; 
    int i=0; 
    a=strchr(s.c_str(),' '); 
    while (s[i]!=' ' && i<s.size()){ 
      x=x+s[i]; 
      i++; 
      if (i==a-s.c_str()){ 
      strcpy(b, x.c_str()); 
      cout <<x.c_str()<<endl; 
      tree.meter(b); 
      i++; 
      a=strchr(a+1,' '); 
      x=""; 
      } 
    } 
    tree.inOrden(tree.getRaiz()); 
    getch(); 
    return 0; 
} 
+0

使用std :: string。查看其所有成員,特別是'find_first'和'substr'。 –

+0

對於C風格字符串,請查看函數'strchr'和'strstr'。 –

+0

問題是沒有得到的話,(我已經分割字符串,並得到的話),問題是當我使用meter()函數,因爲該函數讀取所有單詞,但只是返回最後一個,當我打印它帶有inOrden()函數。但感謝您的幫助。 –

回答

0

我認爲你的問題是因爲你使用char*而不是字符串。

將節點插入到數據結構中時,只會將指針的副本保留爲該字符串,並且不會獲取該字符串的副本。

當您的代碼解析句子中的下一個單詞時,您將新單詞分配給指針b。然後全部您的節點現在指向同一個單詞 - 在處理完句子後,它將始終是最後一個單詞。

更改您的代碼以使用strcpy複製該單詞並將其存儲在節點中,而不僅僅是指針的副本。 (不要忘記爲拷貝分配內存,另一個原因改爲使用string而不是char*,所有的內存管理都是爲你處理的。)

+0

現在你說出來了。這真的好像是問題所在,我會盡力解決它,謝謝。 –

+0

@JorgeRamos - 我無法強調你應該從'char *'改變爲'string'。你標記了你的問題'C++',所以沒有理由不使用可用的庫來簡化操作。如果你想堅持'char *',那麼不要使用'typedef';在學習編碼時,它可以掩蓋何時需要複製而不是分配,如本例所示。祝你好運! – Tony

+0

如果你需要複製你的字符串,'strdup'是你的朋友。語言的最終選擇是你的,但我的建議是將C字符串作爲練習。當然,std :: strings更容易使用,但是您可能會從掌握幕後背後的知識中學到一些有價值的東西。 –