简体   繁体   中英

How to use double pointers in binary search tree data structure in C?

I'm working on implementing a binary search tree data structure in C, but I got stuck at the part where you point to the left or right child. I understand that if the value you're inserting is smaller than the root, it goes to the left and to the right if it's larger. I'm just struggling with the double pointers part as shown in the code below. Let's take bs_tree_insert_left for example, I want pos->left_child to point to the left_child in order to place the value given there, but I'm not sure how I would write this. For context regarding the main function, the numbers in arr[] will be randomly shuffled but I removed that part of the code to keep the post short and compact.

struct node
{
    int value;
    struct node *left_child;
    struct node *right_child;
};

typedef struct node BSTree;
typedef struct node* BSTreePos;

BSTree *bs_tree_make(int value){
  // Allocate memory for new node
  struct node* origin = (struct node*)malloc(sizeof(struct node));
  // Assign data to this node
 origin->value = value;

 // Initialize left and
 // right children as NULL
 origin->left_child = NULL;
 origin->right_child = NULL;
 return (origin);
}

BSTreePos bs_tree_insert_left(int value, BSTreePos pos){
  
  pos->left_child = bs_tree_make(value);
  return pos->left_child;
}
void insert_value(int value, BSTreePos pos)
{
  if (pos == NULL) return bs_tree_make(value);
  if (value < pos->value)
  {
  pos->left_child = bs_tree_insert_left(value, pos->left_child);
  }
  else if (value > pos->value)
  {
  pos->right_child = bs_tree_insert_right(value, pos->right_child);
  }

}

int main(void)
{
    // Create an array with the values 1, 2, ..., 10 and print out the content.
    int n = 10;
    int arr[n];

for (int i = 0 ; i < n ; i++) {
    arr[i] = i + 1;
}

print_array(n, arr);
BSTree *tree = bs_tree_make(arr[0]);
for (int i = 1 ; i < n ; i++) {
    BSTreePos pos = bs_tree_root(tree);
    insert_value(arr[i], pos);
}
return 0;

}

You know what, I'm just going to write the correct algorithm that uses the double pointer to maximum effect.

void insert_value(int value, struct node **node)
{
    if (*node == NULL) {
        *node = malloc(sizeof(struct node));
        node[0]->value = value;
        node[0]->left_child = NULL;
        node[0]->right_child = NULL;
    } else if (node[0]->value < value)
        insert_value(value, &node[0]->left_child);
    else if (node[0]-> value > value)
        insert_value(value, &node[0]->right_child);
    /* else duplicate value found -- don't insert (from OP's code) */
}


    BSTree *tree = NULL;
    for (int i = 0 ; i < n ; i++) {
        insert_value(arr[i], &tree);
    }

node[0]->value is the idiomatic way of accessing a struct through a double pointer.

But let's look at how this works and how much value this gets out of the double pointer. The empty tree is stored as the NULL pointer. This makes initializing the tree and adding a node to the tree the same code. Notice how insert_value takes a double pointer to the tree; this allows it to fill out the root node when adding the first node, or any child node thereof. Thus double pointer which is pointer to pointer is used to update a pointer to a node when we make a new one.

With this algorithm, having a bs_tree_insert_left literally makes no sense. The whole idea is the code that does the insertion doesn't know where it is inserting the node.

Fun fact: the compiler will transform away the recursion for us when compiling with optimizations.

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