2016-08-16 183 views
-1

所以我想學習如何在C中創建一個二叉樹,到目前爲止我已經得到了這個。C中的遞歸二叉樹插入

void addRecordsToTree(struct date *in, struct date *root) { 
    if (root == NULL) { 
     root = malloc(sizeof(struct date)); 
     root = in; 
     return; 
    } else { 
     //Right side of tree processing 
     if (compareTwoRecords(in, root) >= 0) { 
      addRecordsToTree(in, root->right); 
      return; 
     } else { 
      root->right = in; 
      return; 
     } 
     //Left side of tree processing. 
     if (compareTwoRecords(in, root) < 0) { 
      addRecordsToTree(in, root->left); 
      return; 
     } else { 
      root->left = in; 
      return; 
     } 
    } 
} 

int main() { 
    loadFiles(); 
    struct date treeRoot; 
    struct date *old = malloc(sizeof(struct date)); 
    old = loadContentsIntoHeap(files[file2014]); 

    addRecordsToTree(&old[0], &treeRoot); 
    addRecordsToTree(&old[1], &treeRoot); 
    addRecordsToTree(&old[2], &treeRoot); 
    addRecordsToTree(&old[3], &treeRoot); 
    addRecordsToTree(&old[4], &treeRoot); 
    addRecordsToTree(&old[5], &treeRoot); 

    printRecord(7, old); 

    return 0; 
} 

問題是當我在調試器中檢查程序的狀態時,只是混亂了數據。我認爲這可能是一個類型問題,我發現指針是一個令人難以置信的概念。我不確定我是否已經正確使用它們。所以這裏是調試器的屏幕截圖。

debugger shot of last addRecordsToTree() call

正如你可以在底部看到結構稱爲「老」是我試圖讓樹出來的樹根和在這裏我想將它,但我不明白爲什麼數據我得到這些垃圾值。

什麼是與左右的內存地址?我沒有正確創建它們嗎?

我做的另一個觀察是,當我在調試器中觀察我的代碼時,似乎root永遠不是== NULL並且永遠不會被設置,爲什麼?

+4

'root = malloc(sizeof(struct date)); root = in;' - 所以你正在分配內存,然後通過重新分配相同的指針來泄漏它。 –

+0

那部分永遠不會運行。 – Definity

+0

無論如何,你的代碼粘貼缺少*關鍵*部分。像分配和初始化一樣。 –

回答

0

我看到你的「addRecordsToTree」 - 函數另外一個問題:

「樹處理//右側」的IF-塊

將百達從函數返回。無論「IF」 - 表達是真還是假。 所以你的樹的左葉永遠不會被插入。所以你probalby應該檢查/調試該功能。

+0

是的,這是我的意圖,因爲它自稱它永遠不會到達返回,因爲遞歸調用是阻礙的,​​它只是一旦到達插入點,它將從堆棧幀返回,然後返回。其他只是一個任務,一旦分配它可以返回。這是我的noob邏輯無論如何 – Definity

1

你只是做了以下內容:

int x = 2; 
int y = x; 
y = 5; 

是這裏的第二行必要的或第三個。如果你這樣做,這是完全不合邏輯的程序。你只是用指針而不是整數來做同樣的事情。你首先有一個指向動態內存基址的指針,然後你通過第二次初始化它來覆蓋它。

而且,迭代方法比遞歸方法好得多。我共享代碼以遞歸和迭代方式在二叉樹中插入節點:

void insert(struct node *temp, struct node **root) 
{ 
    while (*root != NULL) 
     root = (*root)->element < temp->element ? &(*root)->left : &(*root)->right; 
    *root = temp; 
} 

#if 0 
/* Recursive approach */ 
void insert(struct node *temp, struct node **root) 
{ 
    if(*root == NULL) 
     *root = temp; 
    else if ((*root)->element < temp->element) 
     insert(temp, &(*root)->left); 
    else 
     insert(temp, &(*root)->right); 
} 
#endif 

void create_node(int x, struct node **root) 
{ 
    struct node *temp = (struct node *) malloc(sizeof(struct node)); 

    if (temp == NULL) 
     printf("Unable to allocate memory. Free some space.\n"); 
    else 
    { 
     temp->left = NULL; 
     temp->right = NULL; 
     temp->element = x; 
     insert(temp, root); 
    } 
} 

int main() 
{ 
    struct node *root = NULL; 
    create_node(1, &root); 
    create_node(2, &root); 
    create_node(3, &root); 
    return 0; 
} 
+1

迭代爲什麼比遞歸好得多?我發現它更容易閱讀,並且可能具有相同的性能。 – anatolyg

+0

關於遞歸只是一件事:堆棧溢出。那是一個不同的話題。 –

+0

只有在迭代方法太差或比遞歸更長時才應用它。如果兩個選項具有相同的時間複雜度,那麼您應該始終遵循迭代的方法。我可能沒有在修改鏈接對象時使用所謂的「雙指針」用法。一般來說,理解更爲困難,但是更爲一般的方法。 https://www.youtube.com/watch?v=GiAhUYCUDVc –