Christopher James Hayward
4 years ago
1 changed files with 146 additions and 0 deletions
@ -0,0 +1,146 @@ |
|||
#+TITLE: Data Structures |
|||
#+AUTHOR: Christopher James Hayward |
|||
|
|||
#+HUGO_BASE_DIR: ~/.local/source/website |
|||
#+HUGO_SECTION: notes |
|||
|
|||
+ Built on primitive data types |
|||
+ Organization and management format |
|||
+ Forms the basis of abstract data types |
|||
|
|||
* Binary Tree |
|||
|
|||
#+begin_example |
|||
a |
|||
/ \ |
|||
b c |
|||
/ \ / \ |
|||
d e f |
|||
#+end_example |
|||
|
|||
+ Hierarchical data structure |
|||
+ Different from Arrays, Lists, Stacks & Queues |
|||
|
|||
| Node | Type | Description | |
|||
|---------+------+-----------------------------------| |
|||
| a | Root | Topmost node of the tree | |
|||
| b, c | Node | Children of a, parents of d, e, f | |
|||
| d, e, f | Node | Leaves (nothing below) | |
|||
|
|||
** Example |
|||
|
|||
Using =C++=, we begin by including the ~stdc++~ header and the ~std~ namespace. |
|||
|
|||
#+begin_src cpp |
|||
#include <bits/stc++.h> |
|||
using namespace std; |
|||
#+end_src |
|||
|
|||
We then define the data structure to represent a =Node= within the tree, including a constructor method for creating new instances easily. |
|||
|
|||
#+begin_src cpp |
|||
struct Node { |
|||
int data; |
|||
struct Node* left; |
|||
struct Node* right; |
|||
|
|||
Node(int d) { |
|||
this->data = d; |
|||
this->left = NULL; |
|||
this->right = NULL; |
|||
} |
|||
}; |
|||
#+end_src |
|||
|
|||
We begin by initializing the root of the tree, leaving us with something like this: |
|||
|
|||
#+begin_example |
|||
1 |
|||
/ \ |
|||
? ? |
|||
#+end_example |
|||
|
|||
Initialize it with the value of ~1~. |
|||
|
|||
#+begin_src cpp |
|||
struct Node* node = new Node(1); |
|||
#+end_src |
|||
|
|||
Creating children for nodes ~2~ and ~3~ will expand the tree outwards in both directions, leaving us with something like this: |
|||
|
|||
#+begin_example |
|||
1 |
|||
/ \ |
|||
2 3 |
|||
/ \ / \ |
|||
? ? ? |
|||
#+end_example |
|||
|
|||
This is done by adding the children to the root. |
|||
|
|||
#+begin_src cpp |
|||
root->left = new Node(2); |
|||
root->right = new Node(3); |
|||
#+end_src |
|||
|
|||
Expanding down the left side only. |
|||
|
|||
#+begin_example |
|||
1 |
|||
/ \ |
|||
2 3 |
|||
/ \ / \ |
|||
4 ? ? |
|||
/ \ |
|||
? ? |
|||
#+end_example |
|||
|
|||
Adding a branch of ~4~ to ~2~ gives us the final result. |
|||
|
|||
#+begin_src cpp |
|||
root->left->left = new Node(4); |
|||
#+end_src |
|||
|
|||
** Inverting |
|||
|
|||
#+begin_quote |
|||
Google: 90% of our engineers use the software you wrote (homebrew), but you can't invert a binary tree on a whiteboard? F*** off! |
|||
#+end_quote |
|||
|
|||
It's actually not as daunting a task as you may think, given the hype around past statements like that. But what is the process of inverting a binary tree? Starting with the given input: |
|||
|
|||
#+begin_example |
|||
1 |
|||
/ \ |
|||
2 5 |
|||
/ \ |
|||
3 4 |
|||
#+end_example |
|||
|
|||
We expect to produce an output matching: |
|||
|
|||
#+begin_example |
|||
1 |
|||
/ \ |
|||
5 2 |
|||
/ \ |
|||
4 3 |
|||
#+end_example |
|||
|
|||
Using a recursive approach, we can operate on the tree as to produce the expected result. |
|||
|
|||
#+begin_src cpp |
|||
Node* invert(Node* root) { |
|||
if (root == NULL) { |
|||
return NULL; |
|||
} |
|||
|
|||
Node* left = invert(root->left); |
|||
Node* right = invert(root->right); |
|||
|
|||
root->left = right; |
|||
root->right = left; |
|||
|
|||
return root; |
|||
} |
|||
#+end_src |
Write
Preview
Loading…
Cancel
Save
Reference in new issue