简体   繁体   中英

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. 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); it is called this way: 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. supposing that nodeptr is the root of the tree, how can it affect some node which will point to the new node.

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. At such a node, if we traverse to a NULL leaf then we create a new node with 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. 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. 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: 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; this time node is the left child of the current node (which should be 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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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