Advertisement
clairec

get_node

Feb 7th, 2017
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.81 KB | None | 0 0
  1. // Written by Claire Cavanaugh, 2016
  2.  
  3.  
  4.     tlnode<T>* get_node(std::size_t n) {
  5.         /* Gets the nth node of the tree or returns an error if 0 is
  6.          * received as an argument. This was a bit of a weird thing to
  7.          * write. Essentially, say you have a tree that looks like
  8.          * this:            __________64(1)__________________
  9.          *          ____28(2)_______                     ___53(3)____
  10.          *     __13(4)___        ___19(5)__         43(6)            0(7)
  11.          *   2(8)      1(9)   3(10)        XX(11)
  12.          *
  13.          * Where the number in parenthasis is the index that node
  14.          * would be if we were using a vector-based approach, OR the
  15.          * number in the parentheses is the number assigned to the
  16.          * node starting at 1 for the root and counting up, going left
  17.          * right, top to bottom. I'll refer to that number as simply
  18.          * the node number.
  19.          *
  20.          * In the diagram our tree size is 10. Let's say we wanted to
  21.          * add another value (bringing the total size up to 11). In
  22.          * order to add a node at 11 (notated with XX's in the
  23.          * diagram), we need the address of the parent of the
  24.          * soon-to-be node (node 5, value of 19). Finding a path down
  25.          * to this node seems rather tricky given just the number 5,
  26.          * and at first this really confused me, but I figured out
  27.          * (all by myself!! I'm proud of this) that when you convert a
  28.          * node number to binary, you wind up with "directions" to the node.
  29.          *
  30.          * Let's try this out. The binary representation of 5 is
  31.          * 101. The root node is always going to be a 1 in the number
  32.          * because all binary numbers except zero start with 1
  33.          * (discounting leading zeros). The 0 tells us to go to the
  34.          * left child, then the 1 tells us to go to the left. If we
  35.          * try this with 11, our representation is 1011, and as you
  36.          * can see, following the "zero is left, one is right"
  37.          * convention, 0 1 1 leads us to node 11.
  38.          *
  39.          * So this function uses recursion to cleverly convert to
  40.          * binary in a way. We give it the node number we want, and it
  41.          * says "okay, I'm node 11. 11 % 2 is 1 so whatever the path
  42.          * to me is, it ends in 1, which makes me the right child of
  43.          * my parent, but who is my parent?. My parent's node number
  44.          * must be 11 / 2 = 5, so I'll call get_node(5) to find out
  45.          * the address of my parent.". Get_node(5) deduces that it too
  46.          * is the right child of it's parent (5 % 2 = 1), and that its
  47.          * parent is node 2 (5 / 2), and so it requests the address of
  48.          * its parent with get_node(2). get_node(2) sees that 2 % 2 is
  49.          * 0, so it's the left child of it's parent, and goes to find
  50.          * out who it's parent is with get_node(2 / 2),
  51.          * i.e. get_node(1). And hey! We know where node number 1 is, that's
  52.          * the root node! So we hand the root node over to
  53.          * get_node(2), get_node(2) uses the knowledge to return
  54.          * root->left to get_node(5), get_node(5) uses it to return
  55.          * root->left->right to get_node(11), and get_node(11) finally
  56.          * returns root->left->right->right to its caller.
  57.          *
  58.          * That is quite the journey. I think I had more fun writing
  59.          * this one function than I did the rest of the project.
  60.          */
  61.         if (n == 0) {
  62.             throw std::logic_error("Tried to get 0th node. Is the queue empty?");
  63.         }
  64.         if (n == 1) {
  65.             return root;
  66.         }
  67.         tlnode<T>* my_parent = get_node(n / 2);
  68.         if (n % 2 == 0) {
  69.             return my_parent->left;
  70.         }
  71.         else {
  72.             return my_parent->right;
  73.         }
  74.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement