我对C中二进制树中的函数不了解的东西

时间:2012-02-07 16:47:03

标签: c pointers recursion binary-tree

下面是将节点插入到树中的代码示例。 该示例来自http://cslibrary.stanford.edu/110/BinaryTrees.html 问题是这样的:我对指针和内存有基本的了解,并且了解整个事情但是插入节点。 这是节点struct:

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

现在,在我提供的页面中,它表示这种插入方法是为了避免通过引用传递。所以不是调用insert(struct node** nodeptr, int some data);而是调用它:nodeptr = insert(data int). 所以我的问题是。我理解指针赋值的一部分,insert函数返回的指针放在nodeptr中。假设nodeptr是树的根,它如何影响将指向新节点的某个节点。

struct node* insert(struct node* node, int data) 
{ 
  // 1. If the tree is empty, return a new, single node 
  if (node == NULL) 
  { 
     return(newNode(data)); 
  } 
  else 
  { 
     // 2. Otherwise, recur down the tree 
     if (data <= node->data) 
     {
        node->left = insert(node->left, data); 
     }
     else 
     {
        node->right = insert(node->right, data);
     }

     return(node); // return the (unchanged) node pointer 
   } 
} 

3 个答案:

答案 0 :(得分:1)

如果没有其他节点连接到它们,则二叉树节点的leftright元素可以是NULL。在这样的节点上,如果我们遍历NULL叶子,那么我们用newNode(data)创建一个新节点。

答案 1 :(得分:1)

if (data <= node->data) 
    node->left = insert(node->left, data); 
else 
    node->right = insert(node->right, data);

如果数据小于当前查看的节点数据,则此代码将在节点的左指针上调用insert,否则它将在节点的insert指针上调用right。最终,当它找到了正确的插入位置时,通过递归调用此insert语句中的这些if中的任何一个,这将是一个NULL节点,因为没有更多的节点,它将创建一个新的一个和return,它将附加到上一个节点的左或右指针。此时它将返回递归堆栈。

答案 2 :(得分:0)

可能有助于遍历代码以进行一些插入。所以,假设我们从函数insert调用foo,我们的调用树看起来像这样:

 foo: root = NULL;
 foo: root = insert(root, 5);

     insert: if (node == NULL)
     insert: return newnode(data); // newnode = 0xff864000

 foo: root = 0xff864000

在第一次调用数据之后,我们的树看起来像这样:

Address       data        left            right
-------       ----        ----            -----
0xff864000       5        0x00000000      0x00000000

现在我们再次调用插入一个新值:

foo: root = insert(root, 3);

    insert: if (node == NULL) // node == 0xff864000
    insert: if (data <= node->data)
    insert: node->left = insert(node->left, data);

现在我们再次致电insert;这次node是当前节点的左子节点(应为NULL):

        insert(2): if (node == NULL) // node == 0x00000000
        insert(2): return newnode(data); // newnode == 0xff86400c

    insert: node->left = 0xff86400c;
    insert: return node; 

foo: root = 0xff864000

因此,对insert的第二次调用的结果被分配给当前节点的左子节点,而我们的树现在看起来像这样:

Address       data        left            right
-------       ----        ----            -----
0xff864000       5        0xff86400c      0x00000000
0xff86400c       3        0x00000000      0x00000000

添加另一个元素:

foo: root = insert(root, 2);

    insert: if (node == NULL)  // node = 0xff864000
    insert: if (data <= node->data)
    insert: node->left = insert(node->left, data);

        insert(2): if (node == NULL)  // node = 0xff86400c
        insert(2): if (data <= node->data)
        insert(2): node->left = insert(node->left, data);

            insert(3): if (node == NULL)
            insert(3): return newnode(data); // newnode = 0xff864018

        insert(2): node->left = 0xff864018
        insert(2): return node;

   insert: node->left = 0xff86400c
   insert: return node;

foo: root = 0xff8640000

现在我们的树看起来像

Address       data        left            right
-------       ----        ----            -----
0xff864000       5        0xff86400c      0x00000000
0xff86400c       3        0xff864018      0x00000000
0xff864018       2        0x00000000      0x00000000

最后:

foo: root = insert(root, 7);

    insert: if (node == NULL)  // node = 0xff864000
    insert: if (data <= node->data)
    insert: node->right = insert(node->right, data);

        insert(2): if (node == NULL)  // node = 0x0x00000000
        insert(2): return newnode(data); // newnode = 0xff864024

    insert: node->right = 0xff864024
    insert: return node;

foo: root = 0xff8640000
Address       data        left            right
-------       ----        ----            -----
0xff864000       5        0xff86400c      0xff864024
0xff86400c       3        0xff864018      0x00000000
0xff864018       2        0x00000000      0x00000000
0xff864024       7        0x00000000      0x00000000