2017-08-03 70 views
-1

我想學習遞歸,所以我嘗試了一個程序來創建一個完整的二叉樹,然後打印其所有元素的總和,我自己寫了插入部分,我困惑的是我的指針變量"curr"它指向一個樹節點,爲什麼我能夠做"curr = curr->left",因爲它只是一個指向節點的指針。不僅應該在實際的樹節點中包含這些左右字段嗎?只要給我一個關於這個新手的疑問。我很驚訝我的計劃能夠完成這項工作。添加到一個完整的二叉樹使用遞歸C

謝謝:)

#include<stdio.h> 
#include<stdlib.h> 

struct node{ 
    int data; 
    struct node *left,*right; 
}; 

struct node *head = NULL; 
struct node *curr = NULL; 

void insert_Data(int val,struct node* curr){ 
    struct node *tempnode = (struct node*)malloc(sizeof(struct node)); 
    tempnode->data = val; 
    tempnode->left = NULL; 
    tempnode->right = NULL; 
    if(head==NULL){ 
     head = tempnode; 
     curr = head; 
     printf("head element is : %d\n",head->data); 
    } 
    else{ 
     if(curr->left == NULL){ 
      curr->left = tempnode; 
     } 
     else if(curr->right == NULL){ 
      curr->right = tempnode; 
     } 
     else{ 
      curr = curr->left; 
      insert_Data(val,curr); 
     } 
    } 
} 

//to test program 
int sumNode(struct node* root) { 
    // if there is no tree, its sum is zero 
    if(root == NULL) { 
    return 0 ; 

    } else { // there is a tree 
    printf("element is = %d\n",root->data); 
    return root->data + sumNode(root->left) + sumNode(root->right) ; 
    } 
} 

int main() { 
    int arr[] = {1,2,3,4,5,6,7,8,9}; 
    int i; 
    for(i=0;i<9;i++){ 
     insert_Data(arr[i],head); 
    } 
    int result = sumNode(head); 
    printf("\n\n%d",result); 
    return 0; 
} 
+0

'curr'是一個指向'node'結構實例的指針。 'node'結構的成員有'left'和'right'。我不確定你的困惑來自哪裏? –

+0

感謝您的快速回復@some程序員哥們,其實我的困惑是我們創建的指向實際節點的節點指針是否也包含這些字段作爲實際節點呢? –

+2

也許這有助於:curr-> left與(* curr).left相同。指針不包含任何字段。它只是指向那個結構。 –

回答

1

對於箭頭操作->的含義看到此相關的問題Arrow operator (->) usage in C

關於問題的標題,我建議遞歸insert方法,即遵循,深挖模式的根:

// in: the value to be inserted as new node 
//  the head of the sub-tree that should contain the new node 
// out: the new head of the subtree 
struct node* insert_Data(int val, struct node* subtreeRoot); 

只要你不重新平衡樹,這將基本上導致一種行爲,其中任何有效的輸入將自行返回,並在樹層次結構下添加新值,並且輸入NULL將返回新創建的節點作爲輸出。

struct node* insert_Data(int val, struct node* subtreeRoot) 
{ 
    if (subtreeRoot == NULL) 
    { 
     struct node *tempnode = (struct node*)malloc(sizeof(struct node)); 
     tempnode->data = val; 
     tempnode->left = NULL; 
     tempnode->right = NULL; 
     return tempnode; 
    } 
    else if (val < subtreeRoot->data) 
    { 
     subtreeRoot->left = insert_Data(val, subtreeRoot->left); 
    } 
    else // val is bigger than the subtree root data 
    { 
     subtreeRoot->right = insert_Data(val, subtreeRoot->right); 
    } 
    return subtreeRoot; 
} 

使用像:

head = insert_Data(arr[i], head); 

現在,返回值僅有助於保持NULL比較在一個地方。但正如所說的,這個簽名和用法還允許更復雜的插入方法,其中子樹結構在插入時完全更改。

+0

感謝您指出我的內存泄漏錯誤@ grek40 ,還有一個疑問,如果完整的二叉樹應該像左邊的孩子那樣排序,那它應該比右邊的孩子低,或者它可以是任何孩子的任何值?此外,爲了加總這些值,我必須需要一個指向根節點的指針嗎? (以便我可以遍歷它) –

+0

@CodeSpy實際上,排序只與二叉搜索樹有關。我只是用它,因爲我沒有想到更好的標準 - 當你的節點已經包含一個正確的孩子時,你總是會離開的想法會造成非常不平衡的樹。您可以根據需要任意選擇左右兩種方式 - 但最好選擇一種策略,使得生成的樹會有所平衡。另外,正如評論,如果你真的需要一個**完整的二叉樹,你必須改變你的方法。 – grek40

+0

謝謝@ grek40這個解釋清除了我的懷疑:) –