diff --git a/notes/data-structures.org b/notes/data-structures.org deleted file mode 100644 index 4609904..0000000 --- a/notes/data-structures.org +++ /dev/null @@ -1,218 +0,0 @@ -#+TITLE: Data Structures -#+AUTHOR: Christopher James Hayward - -#+ROAM_KEY: https://chrishayward.xyz/notes/data-structures/ - -#+HUGO_BASE_DIR: ~/.local/source/website -#+HUGO_AUTO_SET_LASTMOD: t -#+HUGO_SECTION: notes - -+ Built on primitive data types -+ Organization and management format -+ Forms the basis of abstract data types - -* Linked List - -#+begin_export -(0 ->) (1 ->) (2 ->) (3 ->) (4 ->) -#+end_export - -+ Linear data structure -+ Elements linked using pointers -+ Not stored in a contiguous location - -Benefits to this approach are: - -+ Dynamic size -+ Ease of manipulation - -Drawbacks of this approach: - -+ Random access not allowed -+ Additional memory overhead -+ Not friendly to caching - -** Example - -Begin with the ~stc++~ header and the ~std~ namespace. - -#+begin_src cpp -#include -using namespace std; -#+end_src - -Define the data structure that will represent a single element (node) in the linked list. - -#+begin_src cpp -struct Node { - int data; - struct Node* next; - - Node(int d) { - this->data = d; - this->next = NULL; - } -}; -#+end_src - -Initialize a new linked list, with an initial value of =0=. - -#+begin_example -(0 ->) -#+end_example - -To illustrate our example we will create a simple linked list with three distinct nodes. The first step is creating our root node. - -#+begin_src cpp -Node* head = new Node(0); -#+end_src - -We can then append new items through the ~next~ field, which is a pointer to the next item in the list. When this value is ~NULL~ we have reached the end of the list. - -#+begin_src cpp -head->next = new Node(1); -head->next->next = new Node(2); -#+end_src - -This gives us the expected result of: - -#+begin_example -(0 ->) (1 ->) (2 ->) -#+end_example - -* 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 -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 diff --git a/notes/efficiency-of-algorithms.org b/notes/efficiency-of-algorithms.org deleted file mode 100644 index d7eeb72..0000000 --- a/notes/efficiency-of-algorithms.org +++ /dev/null @@ -1,69 +0,0 @@ -#+TITLE: Efficiency of Algorithms -#+AUTHOR: Christopher James Hayward - -#+ROAM_KEY: https://chrishayward.xyz/notes/efficiency-of-algorithms/ - -#+HUGO_BASE_DIR: ~/.local/source/website -#+HUGO_AUTO_SET_LASTMOD: t -#+HUGO_SECTION: notes - -+ Algorithms must be analyzed to determine resource usage -+ Efficiency is analogous to engineering productivity for a repeating process -+ Measured in complexity of time and space (resources) - -* Background - -Importance of efficiency with respect to time was first emphasized by *Ada Lovelace* in 1843 regarding the babbage machine: - -#+begin_quote -In almost every computation a great variety of arrangements for the succession of the process is possible, and variouis considerations must influence the selections amongst them for the purpose of a calculating engine. One essential object is to chose that arrangement which shall tend to reduce to a minimum the time necessary for completing the calculation. -#+end_quote - -* Analysis - -The most commonly used notation to describe resource consumption (complexity) is using *Donald Knuth's* =Big O= notation. - -| Notation | Name | Example | -|--------------+--------------+----------------------------------------------------------------| -| O(1) | Constant | Finding the median in a sorted list of measurements | -| O(log n) | Logarithmic | Finding an item in an sorted array with a binary search | -| O(n) | Linear | Finding an item in an unsorted array | -| O(n log n) | Linearithmic | Performing a fast sorting algorithm | -| O(n²) | Quadratic | Multiplying two n digit numbers by a simple algorithm | -| O(n²), c > 1 | Exponential | Finding the optimal solution to the traveling salesman problem | - -* Measurement - -Expression as a function of the size of the input ~n~, with the main measurements being: - -+ Time :: How long does the algorithm take to complete? -+ Space :: How much working memory is required? - -Other measurements for devices whose power needs to be factored in, such as for battery operated devices or super computers: - -+ Direct power :: How much power is needed to compute the algorithm? -+ Indirect power :: How much power is needed for cooling, lighting, etc? - -Less commonly used: - -+ Transmission size :: How much data must be transferred for operation? -+ External space :: Space needed physically (such as on disk) -+ Response time :: Relevant in real time applications -+ Total cost :: Cost of hardware dedication - -** Time - -+ Uses time complexity analysis -+ Measured in CPU time usage -+ Detailed estimates needed to compare performance -+ Difficult to measure in parallel processing - -** Space - -Concerned with the usage of memory resources, typically the memory or storage needed to hold: - -+ Code for the algorithm -+ Working space -+ Input data -+ Output data -+ Processing data