2016-11-13 47 views
0

我試圖寫一個小程序,通過在數字陣列的例子不勝枚舉,只是將它們插入到二叉搜索樹。下面是我有:解析未初始化值轉換爲功能

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

typedef struct node_t node_t; 

struct node_t { 
    int data; 
    node_t *left; 
    node_t *right; 
}; 

int insert(node_t *node, int n); 

int main(void) { 
    int array[8] = {5, 8, 3, 6, 9, 2, 4, 7}; 
    int i; 
    node_t *root; 

    for (i = 0; i < 8; i++) { 
     insert(root, array[i]); 
    } 

    return 0; 
} 

int insert(node_t *node, int n) { 

    if (node == NULL) { 
     node = malloc(sizeof node); 
     node->data = n; 
     return 1; 
    } 

    if (n > node->data) { 
     insert(node->left, n); 

    } else if (n < node->data) { 
     insert(node->right, n); 

    } else { 
     return -1; 
    } 

    return 0; // Suppress 'control reaches end of non-void function' 
} 

,當我用gcc編譯我得到一個警告說「‘根’可以使用此功能初始化」。運行它會導致錯誤(在Windows上至少),但是,在main()打印出root->data產生一個0

我想實現這個想法的insert()功能檢查,如果指針輸入節點是NULL所以然後可以malloc它。另外,由於處理遞歸的方式,插入的數字應該插入該節點。如果節點不等於NULL,那麼我將在應該插入數字的節點一側再次遞歸調用insert()

我明白爲什麼這不起作用,有事情做與指針root不隨地執導,也不root->left/root->right,但是,我不知道我能做些什麼來解決這個問題的原因。任何幫助將不勝感激,謝謝!

+0

無關,但會發生什麼,從遞歸調用返回的值? –

+1

至於你的問題,搜索*模擬c *通過引用傳遞。 –

+0

@Someprogrammerdude對不起,我做了一些修改,因爲代碼是從錯誤的角度考慮的,試圖排除它。就搜索而言,我可能會錯過一些東西,但Google上的3個頂級結果似乎並沒有幫助,他們似乎在討論將初始化變量的地址傳遞給函數,而我將一個指針傳遞給還沒有被告知要存儲的地址。 – Arkantos

回答

1

可能有更多問題您發佈的代碼,但我下面列出了一些問題。

既然是你需要的,如果它包含空值分配內存的節點上,您需要更改此:

if (node->data == NULL) { 

要這樣:

if (node == NULL) { 

此外,您還需要啓動這是根節點,因爲它只包含當時在堆棧上發生的任何事情,它可能是也可能不是NULL(即你想在插入函數中比較的東西)。因此,啓動它,如下所示:

node_t *root = NULL; 

最後一件事就是改變對malloc來釋放calloc函數(或對內存做了memset的零分開)。否則,變量node-> left和node-> right可以包含非NULL值,這可能導致使用未初始化的內存。

+0

感謝您的反饋意見,是的,我發現我剛剛發佈之前的第一件事就是想到了。我現在改變了你說的其他兩件事,現在肯定不會返回任何錯誤。但是,當我在for循環之後進入main並嘗試執行'printf(「%d \ n」,root-> data)時;'程序崩潰,沒有錯誤信息。你知道那裏發生了什麼嗎? – Arkantos

+0

請記住,您需要將地址傳遞給內存,以修改函數內部的那塊內存。換句話說,您需要使用雙指針,否則插入功能將無用。 – staringlizard

1

你的程序沒有一個unintialized root變量確實傳遞給insert()功能。但即使初始化root,您仍然會遇到問題 ,因爲爲了填充樹,您需要將指針傳遞給指針(因爲您希望能夠修改main()中的指針root)。同樣,您也需要修改參數 遞歸調用insert()

我注意到你真的不使用的insert()返回值。所以,它可以只是一個void函數。我添加了一些代碼內註釋來解釋一些問題。

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

typedef struct node_t node_t; 

struct node_t { 
    int data; 
    node_t *left; 
    node_t *right; 
}; 

void print(node_t *r) { /* In order tree traversal. Gives the sorted output. */ 
    if (!r) return; 
    print(r->left); 
    printf("%d ", r->data); 
    print(r->right); 
} 

void insert(node_t **node, int n); 

int main(void) { 
    int array[] = {5, 8, 3, 6, 9, 2, 4, 7};  /* Removed the size. It can be calculated using sizeof and helps when array size changes */ 
    int i; 
    node_t *root = NULL; 

    /* Without hard-coding, array size can be calculated like this. */ 
    for (i = 0; i < sizeof array/sizeof array[0]; i++) { 
     insert(&root, array[i]); 
    } 

    print(root); 
    return 0; 
} 

void insert(node_t **node, int n) { 
    if (*node == NULL) { 
     *node = malloc(sizeof *node); 
    if (*node == NULL) { /* Need to check the return value for failure. */ 
      perror("malloc"); 
      exit(1); 
     } 
    (*node)->left = (*node)->right = NULL; 
     (*node)->data = n; 
    return; 
    } 

    if (n < (*node)->data) /* Insert smaller elements on the left for it to be a binary tree - but not neccessary */ 
     insert(&(*node)->left, n); 
    else /* Another else below this isn't needed. There can't be any error with the number 'n' itself */ 
     insert(&(*node)->right, n); 
} 
+0

感謝您的回覆!我試圖運行你的程序,它編譯得很好,但是當我運行它時崩潰沒有錯誤消息(我在Windows上)。至於指針指針的指針,感謝清除它!當我早點搜索時,這是我遇到的一種方式,但它看起來太亂了,而且看起來畢竟是這樣。無論如何,有什麼我可以做的關於崩潰? – Arkantos

+0

@Arkantos你修改了你現有的程序嗎?我沒有看到我發佈的代碼有任何問題。也許,你試圖用我的建議修改你的程序,並錯過了一些(如'node_t * root = NULL;')?在任何情況下,您都可以運行調試器來查找哪一行代碼導致崩潰。 –