简体   繁体   English

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

[英]Something I don't understand about a function in Binary Trees in C

Below is the code example for the insert code of a node into a tree. 下面是将节点插入到树中的代码示例。 The example is taken from http://cslibrary.stanford.edu/110/BinaryTrees.html The problem is this: I have a basic understanding of pointers and memory, and understand the whole thing but the insert node. 该示例来自http://cslibrary.stanford.edu/110/BinaryTrees.html问题是这样的:我对指针和内存有基本的了解,并且了解整个事情,但是插入节点。 here's the node struct: 这是节点结构:

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

Now, in the page I provided, it says that this method of insertion is done to avoid the pass by reference. 现在,在我提供的页面中,它表示这种插入方法是为了避免通过引用传递。 so instead of calling insert(struct node** nodeptr, int some data); 所以不要调用insert(struct node** nodeptr, int some data); it is called this way: nodeptr = insert(data int). 它以这种方式调用: nodeptr = insert(data int). so my question is. 所以我的问题是。 I understand the part of pointer assignment, that the pointer returned by the insert function is placed into nodeptr. 我理解指针赋值的一部分,insert函数返回的指针放在nodeptr中。 supposing that nodeptr is the root of the tree, how can it affect some node which will point to the new node. 假设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 
   } 
} 

The left and right elements of a node of a binary tree can be NULL if there are no further nodes connected to them. 如果没有连接到它们的其他节点,则二叉树的节点的leftright元素可以是NULL At such a node, if we traverse to a NULL leaf then we create a new node with newNode(data) . 在这样的节点上,如果我们遍历NULL叶子,那么我们用newNode(data)创建一个新节点。

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

This code will call insert on the node's left pointer if the data is smaller than the currently looked at node's data, or else it will call insert on the node's right pointer. 如果数据小于当前查看的节点数据,则此代码将在节点的左指针上调用insert ,否则它将在节点的right指针上调用insert Eventually, when it has found the right place to insert, by recursively calling either of these insert s in this if statement, this will be a NULL node as there's no more nodes, it will create a new one and return that, which will be appended to the previous node's left or right pointer. 最终,当它找到了正确的插入位置时,通过在这个if语句中递归调用这些insert中的任何一个,这将是一个NULL节点,因为没有更多节点,它将创建一个新节点并return它,这将是附加到上一个节点的左或右指针。 At this point it will go back up the recursion stack. 此时它将返回递归堆栈。

It might help to walk through the code for a few inserts. 可能有助于遍历代码以进行一些插入。 So, assuming we're calling insert from function foo , our call tree would look something like this: 所以,假设我们从函数foo调用insert ,我们的调用树看起来像这样:

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

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

 foo: root = 0xff864000

After this first call to data, our tree looks something like this: 在第一次调用数据之后,我们的树看起来像这样:

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

Now we make a second call to insert a new value: 现在我们再次调用以插入一个新值:

foo: root = insert(root, 3);

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

Now we call insert again; 现在我们再次调用insert ; this time node is the left child of the current node (which should be NULL): 这个时间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

So the result of this second call to insert is assigned to the left child of the current node, and our tree now looks something like this: 因此,第二次调用insert的结果被分配给当前节点的左子节点,我们的树现在看起来像这样:

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

Add another element: 添加另一个元素:

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

And now our tree looks like 而现在我们的树看起来像

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

And finally: 最后:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM