2012-11-13 41 views
1

我正在嘗試將int插入節點到樹中。據我所知,我的插入函數完美工作,但在函數之外,就像它從未發生過。這裏是我的代碼:無法更改函數調用之外的節點參數

lcrs.h:

using namespace std; 
#include <cstdlib> 
#include <iostream> 

class node{ 
     public: 
     int data; 
     node *right; 
     node *below; 

     node() 
     { 
       right = NULL; 
       below = NULL; 
     } 
}; 

class lcrs{ 
     public: 
     node *root; 
     bool search(int, node*); 
     void print(node*); 
     void insert(int, node*); 
     int getHeight(node*); 

     lcrs() 
     { 
       root = NULL; 
     } 
}; 

而且lcrs.cpp:

using namespace std; 
#include "lcrs.h" 

bool lcrs::search(int x, node *b) 
{ 
     if(b == NULL) 
       return false; 
     else 
     { 
       if(b->data == x) 
         return true; 
       else 
       { 
         return search(x, b->right) || search(x, b->below); 
       } 
     } 
} 

void lcrs::print(node *z) 
{ 
     if(z->right == NULL && z->below == NULL) 
     { 
       cout << z->data << endl; 
     } 
     else if(z->below == NULL && z->right != NULL) 
     { 
       cout << z->data << ", "; 
       print(z->right); 
     } 
     } 
     else if(z->below != NULL && z->right == NULL) 
     { 
       cout << z->data << ", "; 
       print(z->below); 
     } 
     else 
     { 
       print(z->right); 
       print(z->below); 
     } 
} 

void lcrs::insert(int x, node *a) 
{ 
     if(a == NULL) 
     { 
       node *newnode; 
       newnode = new node; 
       newnode->data = x; 
       a = newnode; 
       cout << a->data << endl; 
     } 
     else if(a->data < x) 
     { 
       if(a->right != NULL) 
       { 
         insert(x, a->right); 
       } 
       else 
         a->right->data = x; 
     } 
     else 
     { 
       if(a->below != NULL) 
       { 
         insert(x, a->below); 
       } 
       else 
       { 
         a->below->data = x; 
       } 
     } 
} 

int lcrs::getHeight(node *h) 
{ 
     int height = 0; 
     if(h->below != NULL) 
     { 
       height ++; 
       return getHeight(h->below); 
     } 
     else 
       return height; 
} 

最後我的main.cpp:

using namespace std; 
#include <iostream> 
#include <cstdlib> 
#include <cstring> 
#include "lcrs.h" 

int main() 
{ 
char *temp1; 
char *temp2; 
temp1 = new char; 
temp2 = new char; 

lcrs tree; 

do{ 
     cout << "LCRS> "; 
     cin >> temp1; 
     if(strcmp(temp1, "quit") == 0) 
     { 
       return 0; 
     } 
     if(strcmp(temp1, "insert") == 0) 
     {  cin >> temp2; 
       bool error; 
       for(int i=0; i<strlen(temp2)-1; i++) 
       { 
         if(!isdigit(temp2[i])) 
         { 
           cout << "Error!" << endl; 
           error = true; 
         } 
       } 
       if(!error) 
       { 
         tree.insert(atoi(temp2), tree.root); 
         if(tree.root == NULL) 
           cout << "Root is null." << endl; 
         else 
           cout << tree.root->data << endl; 
       } 
     } 
     else if(strcmp(temp1, "height") == 0) 
     { 
       if(tree.root == NULL) 
         cout << "-1" << endl; 
       else 
         cout << tree.getHeight(tree.root); 
     } 
     else if(strcmp(temp1, "preorder") == 0) 
     { 
       tree.print(tree.root); 
     } 
}while(strcmp(temp1, "quit") !=0); 

return 0; 
} 

所以,我明白,我insert函數實際上並沒有改變root,我只是不明白爲什麼。

非常感謝您的幫助。

+0

查找通過引用並按值傳遞 - 您正在通過值傳遞,但您希望它的行爲像通過引用一樣。 – John3136

回答

2

您的代碼:

void lcrs::insert(int x, node *a) 
{ 
     if(a == NULL) 
     { 
       node *newnode; 
       newnode = new node; 
       newnode->data = x; 
       a = newnode; 

↑這種分配不更新實際的參數,因爲它是按值傳遞。

   cout << a->data << endl; 
     } 
     else if(a->data < x) 
     { 
       if(a->right != NULL) 
       { 
         insert(x, a->right); 
       } 
       else 
         a->right->data = x; 

↑在這裏你知道(已確保),a->right是一個空指針。取消參考零點指針產生未定義的行爲。例如崩潰。

 } 
     else 
     { 
       if(a->below != NULL) 
       { 
         insert(x, a->below); 
       } 
       else 
       { 
         a->below->data = x; 
       } 

↑在這裏你知道(已經確保)a->below是一個空指針。取消參考零點指針產生未定義的行爲。例如崩潰。 } }

作爲一般性評論,belowright混合了兩個隱喻。最好稱它們爲belowaboveleftright。後一種選擇非常普遍。

而不是通過引用傳遞節點指針(以解決非更新問題),請考慮將其作爲函數結果返回。

+0

謝謝!這有很大幫助。 另外,樹的設置方式就像一個L,所以** **和** right **在視覺上是有道理的。 –

1

您正在將指針傳遞給按值傳遞;要通過參考,您需要使用void lcrs::insert(int x, node * & a),它通過引用a而不是a本身。會發生什麼情況是指向該節點的指針被複制到本地變量中,在該函數內引用爲a。然後該函數可以自由地更改副本(甚至是它指向的內存),但是當函數返回時,調用者不知道副本發生了什麼,因爲它仍然在查看原始內容。

通過引用傳遞,調用方和被調用函數都使用相同的事物,而不是一個使用副本,另一個使用原始方法。