SE250:lab-6:dols008

From Marks Wiki
Jump to navigation Jump to search

Task 1

To determine the relationship between tree size and height, I decided to loop through a number of different tree sizes. For each tree size I would generate a random binary tree and record it's height. Here is some sample data:

Size	Height
0	0
100	13
200	17
300	18
400	16
500	19
600	24
700	20
800	20
900	22
1000	24

To make my data more accurate, I decided to generate a number of trees of any particular size and average the heights. Here are the results after averaging 10 trees per size:

Size	Height
0	0.000000
100	13.400000
200	16.000000
300	17.800000
400	18.400000
500	19.700000
600	20.100000
700	20.800000
800	20.700000
900	21.600000
1000	22.100000

I was disappointed to find that there is no given method for freeing binary trees.

Task 2

Implementing the minimum and maximum functions was straight forward, but testing them was a little tricky. I opted to do it by generating a few random trees, printing them out using show_tree and visually checking my minimum and maximum were correct. The output of show_tree was less than intuitive, it took me a while to figure out the tree is actually sideways. I also found that the root of my tree always had a key of 0, so I seeded rand() to get some more interesting data.

Here is my code for minimum and maximum:

Node* minimum( Node* node ) {
  if (node != empty && node->left != empty)
    return minimum(node->left);
  return node;
}

Node* maximum( Node* node ) {
  if (node != empty && node->right != empty)
    return maximum(node->right);
  return node;
}

Task 3

Lookup wasn't hard either, but again it was a pain to test. I had to construct the tree by hand this time so that I knew which numbers were in it (though it occurs to me now I could have used the same seed each time). Here's the code:

Node* lookup( int key, Node* node ) {
  if (node == empty || key == node->key)
    return node;
  if (key > node->key)
    return lookup(key, node->right);
  else
    return lookup(key, node->left);
}

Task 4/5

Preorder took a fair bit of thought. It didn't seem hard at first, but it took a couple of broken versions which got stuck down leaves before I got it right. Once I had a working version I tidied it up a bit and removed an extra variable.

Node* next_pre( Node* node ) {
  if (node == empty)
    return empty;
  if (node->left != empty)
    return node->left;
  if (node->right != empty)
    return node->right;
  while (node->parent != empty)
  {
    if (node->parent->right != empty && node->parent->right != node)
      return node->parent->right;
    node = node->parent;
  }
  return empty;
}

I skipped ahead to next_in, because it seemed more interesting. This one took a couple of tries too. There's less in common between the functions than I expected.

Node* next_in( Node* node ) {
  if (node == empty)
    return empty;
  if (node->right != empty)
  {
    node = node->right;
    while (node->left != empty)
      node = node->left;
    return node;
  }
  while (node->parent && node->parent->right == node)
    node = node->parent;
  return node->parent;
}

It's not getting much easier. next_post took some figuring out too.

Node* next_post( Node* node ) {
  if (node == empty || node->parent == empty)
    return empty;
  if (node->parent->right != empty && node->parent->right != node)
  {
    node = node->parent->right;
    while (node->left != empty)
      node = node->left;
    while (node->right != empty)
      node = node->right;
    return node;
  }
  return node->parent;
}

I'm well over time now. I might come back to this later, it's good practice.