From 173ccf225425587cdd85e6c6e6de6f27c3adfb2e Mon Sep 17 00:00:00 2001 From: lomna Date: Sun, 30 Jul 2023 18:22:06 +0530 Subject: [PATCH] Initial Commit --- imgs/Heap-as-array.svg | 677 +++++++++++ imgs/tree_actual.jpg | Bin 0 -> 119325 bytes imgs/tree_representation.jpg | Bin 0 -> 126176 bytes main.html | 2065 ++++++++++++++++++++++++++++++++++ main.org | 1161 +++++++++++++++++++ main.tsk | 7 + src/export.el | 9 + src/htmlize.el | 1864 ++++++++++++++++++++++++++++++ src/org.css | 137 +++ 9 files changed, 5920 insertions(+) create mode 100644 imgs/Heap-as-array.svg create mode 100644 imgs/tree_actual.jpg create mode 100644 imgs/tree_representation.jpg create mode 100644 main.html create mode 100644 main.org create mode 100644 main.tsk create mode 100644 src/export.el create mode 100644 src/htmlize.el create mode 100644 src/org.css diff --git a/imgs/Heap-as-array.svg b/imgs/Heap-as-array.svg new file mode 100644 index 0000000..a632998 --- /dev/null +++ b/imgs/Heap-as-array.svg @@ -0,0 +1,677 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 100 + 19 + 36 + 17 + 12 + 25 + 5 + 13 + 8 + 1 + 4 + 9 + 15 + 6 + 11 + + + + + + + + + + + + + + + + 100 + 19 + 36 + 17 + 12 + 25 + 5 + 13 + 8 + 1 + 4 + 9 + 15 + 6 + 11 + + + diff --git a/imgs/tree_actual.jpg b/imgs/tree_actual.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05378f0634695438c0bc59b51d8ef20756b2f404 GIT binary patch literal 119325 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

U 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

;3P>naJy$ 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 literal 0 HcmV?d00001 diff --git a/imgs/tree_representation.jpg b/imgs/tree_representation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5b8931ed5a59040fef049cc1be778b905df3e155 GIT binary patch literal 126176 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 P2PHuE#Z!@Ria-C^pb>Pq literal 0 HcmV?d00001 diff --git a/main.html b/main.html new file mode 100644 index 0000000..b568c1e --- /dev/null +++ b/main.html @@ -0,0 +1,2065 @@ + + + + + + + +Data Structures + + + + + + + + +

+

Data Structures

+
+

Table of Contents

+
+ +
+
+ +
+

1. Stack

+
+

+A stack is a data structure which only allows insertion and deletion from one end of the array. The insertion is always on the extreme end of the array. The deletion can only be done on the element which was most recently added. +
+It is similar to stacking plates. The plate can only be added at the top of the stack and also only the last added plate to the stack can be removed (which will be on top). +
+Due to this property, Last In elements are removed First from a stack. Therefore, it is called a Last In First Out (LIFO) data structure or a First In Last Out (FILO) data structure. +
+To create a stack, we will keep track of the index which is the top of the array. This top index will increment when we insert element and decrement when we remove element. +

+
+ +
+

1.1. Operation on stack

+
+

+A stack has two operations +

+
+
+
+ +
+

2. Direct Address Table

+
+

+Direct Address Tables are useful when we know that key is within a small range. Then, we can allocate an array such that each possible key gets an index and just add the values according to the keys. +
+This also assumes that keys are integers +

+ +
    +
  • Table creation
  • +
+ +
+
struct table{
+  int * values;
+  size_t min_key;
+  size_t max_key;
+};
+
+struct table create_table(size_t min_key, size_t max_key){
+  struct table r;
+  r.values = (int * ) malloc(sizeof(int) * (max_key - min_key + 1) );
+  r.min_key = min_key;
+  r.max_key = max_key;
+  return r;
+}
+
+
+ +
    +
  • Table insert
  • +
+ +
+
void table_insert(struct table t, size_t key, int value){
+  if(key > t.max_key || key < t.min_key)
+    assert(false && "Key value out of boundry");
+
+  t.values[key - t.min_key] = value;
+}
+
+
+ +
    +
  • Table delete
  • +
+ +
+
void table_delete(struct table t, size_t key){
+  if(key > t.max_key || key < t.min_key)
+    assert(false && "Key value out of boundry");
+
+  t.values[key - t.min_key] = 0x00;
+}
+
+
+ +
    +
  • Table Search / Table Get
  • +
+ +
+
int table_get(struct table t, size_t key){
+    if(key > t.max_key || key < t.min_key)
+      assert(false && "Key value out of boundry");
+
+    return t.values[key - t.min_key];
+}
+
+
+ +

+Using direct address tables is very useful when keys are enum values. +

+
+
+ +
+

3. Hash Table

+
+

+When the set of possible keys is large, it is impractical to allocate a table big enough for all keys. In order to fit all possible keys into a small table, rather than directly using keys as the index for our array, we wil first calculate a hash for it using a hash function. Since we are relying on hashes for this addressing in the table, we call it a hash table. +
+
+For a given key \(k_i\) in direct address table, we store value in \(table[k_i]\). +
+
+For a given key \(k_i\) in hash table, we store value in \(table[h(k_i)]\), where \(h()\) is the hash function. +
+
+So the main purpose of the hash function is to reduce the range of array indices. +

+
+ +
+

3.1. Collision

+
+

+Because we are reducing the range of indices, the hash function may hash two keys to the same slot. This is called a collision. +
+
+We should try to find a hash funtion which will minimise the number of collisions. +
+
+The number of keys is going to be greater than number of slots in table. Therefore avoiding all collisions is not possible. +
+There are two ways we will look at to resolve collision. +

+
    +
  1. Chaining
  2. +
  3. Open addressing
  4. +
+
+ +
+

3.1.1. Chaining

+
+

+In chaining, rather than storing values in table slots. We will have linked lists at each slot which will store (key, value) pairs. +
+
+When the hash gives us a slot, we will add the value to linked list at that slot. +

+ +
    +
  • Linked List structure
  • +
+ +
+
struct linked_list{
+  size_t key;
+  int value;
+  struct linked_list * next;
+};
+
+
+ +
    +
  • Table structure
  • +
+ +
+
struct table{
+  struct linked_list * table[];
+  size_t table_size;
+};
+
+
+ +
    +
  • Insertion
  • +
+ +

+Insertion can be done in \(\theta (1)\) time if we assume that key being inserted is not already in the linked list. But we can add a check to see if the key was already inserted and modify that value. +

+ +
+
// linked_list_add(struct linked_list * ll, size_t key, int value)
+// adds the given key,value to the start of the list
+void chained_hash_insert(struct table t, size_t key, int value){
+  linked_list_add(t.table[ h(key) ], key ,value);
+}
+
+
+ +
    +
  • Get / Search
  • +
+ +
+
// linked_list_search(struct linked_list * ll, size_t key)
+// gets the value stored with the given key
+void chained_hash_get(struct table t, size_t key){
+  return linked_list_search(t.table[ h(key) ], key);
+}
+
+
+ +
    +
  • Delete
  • +
+ +
+
// linked_list_delete(struct linked_list * ll, size_t key)
+// delete the node with the given key
+void chained_hash_delete(struct table t, size_t key){
+  linked_list_delete(t.table[ h(key) ], key);
+}
+
+
+
+
+ +
+

3.1.2. Performance of chaining hash table

+
+

+The load factor is defined as number of elements per slot and is calculated as +\[ \alpha \text{(Load factor)} = \frac{\text{number of elements in hash table}}{\text{number of slots in hash table}} \] +The worst case for chaining is when all keys are assigned to a single slot. In this case searching for an element takes \(\theta (n)\) time. +
+
+If we assume that any given element is equally likely to be hashed into any of the slots, this assumption is called simple uniform hashing. +
+
+If we also assume that hash funtion takes constant time, then in the average case, the time complexity for searching key in the chaining hash table is +\[ \text{Average Case Searching} : \theta (1 + \alpha) \] +

+
+
+
+

3.1.3. Open Addressing

+
+

+In open addressing, all the key and value pair of entries are stored in the table itself. Because of this, the load factor \(\left( \alpha \right)\) can never exceed 1. +
+
+When we get a key whose slot is already taken, we will look for another empty slot. This is done by what is called probing. To get which slot to check next, we have various methods. +
+
+The sequence in which empty slots are looked for is fixed for given key, this sequence is called probe sequence.
+It is necessary to keep probe sequence fixed for any given key, so that we can search for it later. +

+
+ +
    +
  1. Linear probing
    +
    +

    +For a given ordinary hash function \(h(k)\), the linear probing uses the hash function +\[ linear\_h(k, i) = (h(k) + 1)\ mod\ m \] +We refer to \(h(k)\) as the auxiliary hash function. +
    +
    +In linear probing, we first check the slot [h(k)], if it is not empty, we check [h(k) + 1] then [h(k) + 2] …. upto slot [m - 1] after which we wrap around to [1], [2] … till we have checked all the slots. +
    +
    +Linear probing is easy to implement, but it suffers from primary clustering. In long runs of linear probing, keys tend to cluster together. This causes the performance of operations on hash table to degrade. The time to query a random element from table degrades to \(\theta (n)\). +

    +
    +
  2. + +
  3. Quadratic probing
    +
    +

    +For given auxiliary hash function \(h(k)\), the quadratic probing uses +\[ quadratic\_h(k, i) = \left( h(k) + c_1i + c_2i^2 \right) \ mod\ m \] +Where, \(c_1\) and \(c_2\) are positive auxiliary constants. +

    +
      +
    • If m is not considered, we just assume \(c_1 = 0, c_2 = 1\), this is the simplest form of quadratic probing.
    • +
    • For \(m = 2^n\), a good choice for auxiliary constants is \(c_1=c_2=1/2\).
    • +
    • For \(m = n^p\) where m, n and p are positive integers greater or equal to 2, constants \(c_1 = 1, c_2 = n\) are a good choice.
    • +
    + +

    +Quadratic probing works much better than linear probing. +
    +
    +If \(quadratic\_h(k_1, 0) = quadratic\_h(k_2,0)\), then that implies that all \(quadratic\_h(k_1, i) = quadratic\_h(k_2,i)\), i.e, they will have the same probe sequence. This leads to a probe sequence getting clustered. This is called secondary clustering. This also effects performance but not as drastically as primary clustering. +

    +
    +
  4. +
  5. Double Hashing
    +
    +

    +Double hashing is one of the best available method for open addressing.
    +Double hashing uses two auxiliary hashing functions. +\[ double\_h(k, i) = \left( h_1(k) + i \times h_2(k) \right) \ mod\ m \] +The value of \(h_2(k)\) must be relatively prime (i.e, coprime) to number of slots (m).
    +

    +
      +
    • A convenient way to ensure this is let m be a power of 2 and \(h_2(k)\) be a hash function that always produces an odd number.
    • +
    • Another way is to let m be a prime and make \(h_2(k)\) such that is always produces a positive integer less than m.
    • +
    +

    +If we use one of the above two methods (either m is a power of 2 or a prime), then double hashing improves over linear and quadratic probing since keys will have distinct probe sequences. +
    +
    +When using the above values of m, performance of double hashing is very close to the performance of "ideal" scheme of uniform hashing. +*n Performace of open addressing +In open addressing load factor \(\left( \alpha \right) \le 1\). We will assume uniform hashing i.e, any element is equally likely to be hashed in any slot. We will also assume that for any key, each possible probe sequence is equally likely. +
    +
    +Under these assumptions, for load factor \(\alpha\). The number of probes in an unsuccessful search is at most \(1/(1 - \alpha )\) +
    +This means that for a constant load factor, an unsuccessful search will run in \(\theta (1)\) time. +
    +
    +The number of probes on average for inserting an element under these assumptions is \(1/(1- \alpha )\) +
    +The number of probes on averge in a successful search is at most \(\frac{1}{\alpha} ln\left( \frac{1}{1-\alpha} \right)\) +

    +
    +
  6. +
+
+
+
+

3.2. Hash Functions

+
+

+A good hash funtion will approximately satisfy the simple uniform hashing, which means that any element is equally likely to be hashed to any slot. +

+ +

+\[ m : \text{Number of slots in hash table} \] +\[ n : \text{Number of elements in hash table} \] +

+ +

+Suppose we knew that our keys are from a set of real numbers and the keys are picked uniformly. In this case, we could simply use the hash function \(h(k) = floor(mk)\). +
+
+Similarly, in many cases we can make a reasonably good hash funtion if we know the distribution of keys. +
+
+We will look at a few ways to make a hash function. +

+
+ +
+

3.2.1. The division method

+
+

+In division method, we map a key \(k\) into one of the \(m\) slots by taking the remainder of k divided by m. +\[ h(k) = k\ mod\ m = k\ \%\ m \] +In most cases, +\[ m : \text{Number of slots in hash table} \] +But there are some cases where \(m\) is chosen to be something else. +

+
    +
  • If \(m\) is a power of 2, then \(k\ mod\ m\) will give us the least significant \(log_2m\) bits of \(k\). When making a hash function, we want a function that depends on all bits of the key. So, we should not use this method if m is a power of 2.
  • +
  • A prime number not close to a power of 2 is a good choice for \(m\) in many cases. So when deciding the number of slots for the hash table, we can try to make \(m\) a prime which will accomodate our elements with less load factor.
  • +
+
+
+ +
+

3.2.2. The multiplication method

+
+

+In multiplication method, we first multiply the key \(k\) with a constant \(A\) which is in range \(0 < A < 1\). Then we get the fractional part of \(kA\). Then we multiply the fractional part by \(m\) and floor it to get the hash. +\[ h(k) = floor(m \times decimal\_part(kA) ) \] +The advantage of multiplication method is that we can choose any value of \(m\). We can even choose \(m\) to be a power of 2. +
+We can choose any value of \(A\). The value depends on characteristics of data, +\[ A \approx \frac{\sqrt{5} - 1}{2} \] +will work reasonably well. +
+
+Example, Suppose +

+ +

+\[ key\ (k) = 1234 \] +\[ m = 128 \] +And our value of \(A\) is, +\[ A = 0.618 \] +Then to get our \(h(k)\), +\[ kA = 762.612 \] +\[ decimal\ part(kA) = 0.612 \] +\[ floor(m \times decimal\_part(kA) ) = h(k) = 78 \] +

+ +

+In C language, +

+
+
size_t hash(size_t key, size_t m){
+  double kA = key * 0.618;
+  // get decimal part only
+  double kA = kA - ((int) kA);
+  // floor the product of decimal part and m
+  size_t h = floor(m * kA);
+  return h;
+}
+
+
+
+
+ +
+

3.2.3. Mid square method

+
+

+In this method, we square the keys and then we choose some digits from the middle. +Example, +\[ h(10) = middle\ digit \left( 10 \times 10 \right) = midlle\ digit (100) = 0 \] +\[ h(11) = middle\ digit \left( 11 \times 11 \right) = midlle\ digit (121) = 2 \] +\[ h(12) = middle\ digit \left( 12 \times 12 \right) = midlle\ digit (144) = 4 \] +With huge numbers, we need to take care of overflow conditions in this method. +

+
+
+ +
+

3.2.4. Folding method

+
+

+While this method can be used on integers, this method is usually used where the key is segmented. For example in arrays or when key is a string. +
+
+In this method, we add all of the segments and then we mod it with the number of slots. +\[ h(k) = \left( \text{Sum of all the segments} \right) mod\ m \] +Example, for string "hello" +
+sum = 'h' + 'e' + 'l' + 'l' + 'o' +
+sum = 104 + 101 + 108 + 108 + 111 = 532 +
+
+If m = 100, then +
+h(k) = 532 mod 100 +
+h(k) = 32 +

+
+
+
+ +
+

3.3. Universal Hashing

+
+

+TODO: Basics of universal hashing. +

+
+
+
+

3.4. Perfect Hashing

+
+

+NOTE: This doesn't seem to be in B.Tech syllabus, but it seems cool. +
+

+
+
+
+ +
+

4. Representing rooted trees using nodes

+
+

+We can represent trees using nodes. A node only stores a single element of the tree. What is a node will depend on the language being used. +
+In C, we make a struct which will store the element and pointers to other node structs. +

+ +
+
struct tree_node{
+  int element;
+  struct tree_node * left_child;
+  struct tree_node * right_child;
+};
+
+
+

+
+In languages with oop, we create node class which will store refrences to other node objects. +

+
+
class Node {
+    int value;
+    Node left;
+    Node right;
+
+    Node(int value) {
+        this.value = value;
+        right = null;
+        left = null;
+    }
+}
+
+
+
+ +
+

4.1. Fixed number of children

+
+

+When we know how many children any given node can have, i.e, the number of children is bounded. We can just use refrences or pointers to the nodes directly. +
+For example, if we know we are making a binary tree, then we can just store refrence to left children and right childern. +

+ +
+
struct tree_node{
+  int element;
+  struct tree_node * left_child;
+  struct tree_node * right_child;
+};
+
+
+
+
+ +
+

4.2. Unbounded number of children

+
+

+When we don't know how many children any given node will have. Thus any node can have any number of children, we can't just use refrences. We could create an array of refrences to nodes, but some nodes will only have one or two childs and some may have no childs. This will lead to a lot of wasted memory. +
+There is a way to represent such trees without wasting any memory. This is done by using sibling refrences or pointers. +
+

+
+
struct tree_node{
+  int element;
+  struct tree_node * left_child;
+  struct tree_node * right_sibling;
+};
+
+
+ +

+The right sibling pointer will point to the right sibling of the node. This allows us to chain siblings and have unbounded number of siblings to the given node, therefore having unbounded number of children to any given parent. To make this approach easier to use, we can also add a pointer back to the parent node, though it is not compulsary. +

+ +
+
struct tree_node{
+  struct tree_node * parent;
+
+  int element;
+
+  struct tree_node * left_child;
+  struct tree_node * right_sibling;
+};
+
+
+ +

+So a tree which is like : +
+tree_actual.jpg +
+
+can be represented using refrences and pointers as : +
+tree_representation.jpg +
+

+
+
+
+ +
+

5. Binary Search Trees

+
+

+A tree where any node can have only two child nodes is called a binary tree. +
+A binary search tree is a tree where for any give node the nodes stored in left sub-tree are less than the parent node and the nodes stored in right sub-tree are greater than the parent node (or vice versa). So the left-subtree always have smaller elements and right sub-tree always have greater elements. +
+
+This property allows us easily search for elements from the data structure. We start our search at the root node. If the element we want is less than the current node, we will go to the left node ,else we will go to the right node. The concept is similar to the binary search on arrays. +

+ +

+In C, we can make a binary tree as +

+
+
struct binary_tree{
+  int value;
+  struct binary_tree * left_child;
+  struct binary_tree * right_child;
+};
+
+
+
+ +
+

5.1. Quering a BST

+
+

+Some common ways in which we usually query a BST are searching for a node, minimum & maximum node and successor & predecessor nodes. We will also look at how we can get the parent node for a given node, if we already store a parent pointer then that algorithm will be unnecessary. +

+
+
+

5.1.1. Searching for node

+
+

+We can search for a node very effectively with the help of binary search tree property. The search will return the node if it is found, else it will return NULL. +

+
+
struct binary_tree *
+search_recursively(struct binary_tree * root, int value){
+  // If we reach a null, then value is not in tree
+  if(root == NULL)
+    return NULL;
+  // if we found the value, return the current node
+  if(root->value == value)
+    return root;
+  // compare value we are looking for
+  // and go to either left or right sub-tree
+  if(value < root->value)
+    return search_recursively(root->left, value);
+  else
+    return search_recursively(root->right, value);
+}
+
+
+

+We can also search iteratively rather than recursively. +

+
+
struct binary_tree *
+search_iterative(struct binary_tree * root, int value){
+  while(root != NULL){
+    // if we found the value, return the current node
+    if(root->value == value) return root;
+    // compare value and go to left or right sub-tree
+    root = (value < root->value) ? root->left : root->right;
+  }
+  // if not found then return NULL
+  return NULL;
+}
+
+
+
+
+
+

5.1.2. Minimum and maximum

+
+

+Finding the minimum and maximum is simple in a Binary Search Tree. The minimum element will be the leftmost node and maximum will be the rightmost node. We can get the minimum and maximum nodes by using these algorithms. +

+
    +
  • For minimum node
  • +
+
+
struct binary_tree * minimum(struct binary_tree * root){
+  if(root == NULL) return NULL;
+  while(root->left != NULL)
+    root = root->left;
+  return root;
+}
+
+
+
    +
  • For maximum node
  • +
+
+
struct binary_tree * maximum(struct binary_tree * root){
+  if(root == NULL) return NULL;
+  while(root->right != NULL)
+    root = root->right;
+  return root;
+}
+
+
+
+
+ +
+

5.1.3. Find Parent Node

+
+

+This algorithm will return the parent node. It uses a trailing node to get the parent. If the root node is given, then it will return NULL. This algorithm makes the assumption that the node is in the tree. +

+
+
struct binary_tree * 
+find_parent(struct binary_tree * tree, struct binary_tree * node){
+  if(tree == node) return NULL;
+
+  struct binary_tree * current_node = tree;
+  struct binary_tree * trailing_node = tree;
+
+  while(current_node != node){
+    trailing_node = current_node;
+    current_node = (node->value < current_node->value) ?
+      current_node->left :
+      current_node->right;
+  }
+
+  return trailing_node;
+}
+
+
+
+
+
+

5.1.4. Is ancestor

+
+

+This algorithm will take two nodes, ancestor and descendant. Then it will check if ancestor node is really the ancestor of descendant node. +

+
+
bool
+is_ancestor(struct binary_tree *ancestor,
+            struct binary_tree *descendant){
+  // both ancestor and descendant
+  // should not be NULL
+  if(ancestor == NULL || descendant == NULL)
+    return false;
+
+  while(ancestor != NULL){
+    if(ancestor == descendant) return true;
+    ancestor = (descendant->value < ancestor->value) ?
+               ancestor->left :
+               ancestor->right;
+  }
+  return false;
+}
+
+
+
+
+
+

5.1.5. Successor and predecessor

+
+

+We often need to find the successor or predecessor of an element in a Binary Search Tree. The search for predecessor and succesor is divided in to two cases. +

+
+ +
    +
  1. For Successor
    +
    +
    +
    // get successor of x
    +struct binary_tree *
    +successor(struct binary_tree * tree, struct binary_tree * x){
    +  // case 1 : right subtree is non-empty
    +  if(x->right != NULL){
    +    return minimum(x->right);
    +  }
    +  // case 2 : right subtree is empty
    +  struct binary_tree * y = find_parent(tree, x);
    +  while(y != NULL){
    +    if(is_ancestor(y, x) && is_ancestor(y->left, x)) return y;
    +    y = find_parent(tree, y);
    +  }
    +  return NULL;
    +}
    +
    +
    +

    +Case 1 : If the node x has a right subtree, then the minimum of right subtree of x is the succesor. +
    +Case 2 : If the node x has no right subtree, then successor may or may not exist. If it exists, the successor node will be the ancestor of x whose own left node is also the ancestor of x. +

    +
    +
  2. +
  3. For Predecessor
    +
    +
    +
    struct binary_tree *
    +predecessor(struct binary_tree * tree, struct binary_tree * x){
    +  // case 1 : left subtree is non-empty
    +  if(x->left != NULL){
    +    return maximum(x->left);
    +  }
    +  // case 2 : left subtree is empty
    +  struct binary_tree * y = find_parent(tree, x);
    +  while(y != NULL){
    +    if(is_ancestor(y, x) && is_ancestor(y->right, x)) return y;
    +    y = find_parent(tree, y);
    +  }
    +  return NULL;
    +}
    +
    +
    +

    +Case 1 : If the node x has a left subtree, then the maximum of left subtree of x is the predecessor. +
    +Case 2 : If the node x has no left subtree, then predecessor may or may not exist. If it exists, the predecessor node will be the ancestor of x whose own right node is also the ancestor of x. +

    +
    +
  4. +
+
+
+
+

5.2. Inserting and Deleting nodes

+
+

+When inserting and deleting nodes in BST, we need to make sure that the Binary Search Tree property continues to hold. Inserting node is easier in a binary search tree than deleting a node. +

+
+
+

5.2.1. Insertion

+
+

+Insertion is simple in a binary search tree. We search for the node we want to insert in the tree and insert it where we find first NULL spot. +

+
+
void
+insert_node(struct binary_tree ** tree, struct binary_tree * node){
+  // if found a null spot, insert the node
+  if(*tree == NULL){
+    *tree = node;
+    return;
+  }  
+  if(node->value < (*tree)->value){
+    // the node is to be inserted into left subtree
+    struct binary_tree ** left_tree = &((*tree)->left);
+    insert_node(left_tree, node);
+  }else{
+    // the node is to be inserted into right subtree
+    struct binary_tree ** right_tree = &((*tree)->right);
+    insert_node(right_tree, node);
+  }
+}
+
+
+

+The recursive algorithm for inserting into a Binary search tree is simpler than the iterative algorithm. +
+
+The algorithm for iterative insertion is +

+
+
void
+insert_node(struct binary_tree **tree, struct binary_tree * node){
+  // if no nodes in tree, then just node and return
+  if((*tree) == NULL){
+    *tree = node;
+    return;
+  }
+
+  struct binary_tree ** current_node = tree;
+  struct binary_tree ** trailing_node = tree;
+
+  // look for an empty place using current_node
+  while(*current_node != NULL){
+    trailing_node = current_node;
+    current_node = (node->value < (*current_node)->value) ?
+      &((*current_node)->left) : &((*current_node)->right);
+  }
+
+  // we need to insert node on the trailing node
+  if(node->value < (*trailing_node)->value)
+    (*trailing_node)->left = node;
+  else
+    (*trailing_node)->right = node;
+}
+
+
+
+
+
+

5.2.2. Deletion

+
+

+Deletion in Binary Search Trees is tricky because we need to delete nodes in a way that the property of the Binary Search Tree holds after the deletion of the node. So we first have to remove the node from the tree before we can free it. +
+
+TODO : Write four cases of node deletion here +

+
+
    +
  1. Implementation in code
    +
    +

    +We also use a helper function called Replace Child for deletion of node. This function will simply take parent node, old child node and new child node and replace old child with new child. +

    + +
    +
    void
    +replace_child(struct binary_tree *parent,
    +              struct binary_tree *old_child,
    +              struct binary_tree *new_child){
    +  if(parent->left == old_child) parent->left = new_child;
    +  else parent->right = new_child;
    +}
    +
    +
    + +

    +We will create a funtion that will remove the root node from a given subtree and then return the root node of the result subtree. +This will allow us to apply remove root node funtion on any node and then reattach the new subtree. +
    +
    +Making remove root node a different funtion will also allow us to not worry about attaching the the subtree immediately in the same funtion. +

    + +
    +
    struct binary_tree *
    +remove_root_node(struct binary_tree *root){
    +  // case 1 : no child
    +  // this case can be skipped in real implementation
    +  // as it is covered by the case 2
    +  if(root->left == NULL && root->right == NULL){
    +    return NULL;
    +  }
    +
    +  // case 2 : one child
    +  if(root->left == NULL){
    +    return root->right;
    +  }else if(root->right == NULL){
    +    return root->left;
    +  }
    +
    +  struct binary_tree *successor = minimum(root->right);
    +  // case 3 : two child and successor is right node of root node
    +  if(successor == root->right){
    +    successor->left = root->left;
    +    return successor;
    +  }
    +
    +  // case 4 : two child and successor is not the right node of root node
    +  struct binary_tree *successor_parent = find_parent(root, successor);
    +  replace_child(successor_parent, successor, successor->right);
    +  successor->left = root->left;
    +  successor->right = root->right;
    +  return successor;
    +}
    +
    +
    + +

    +Now we can make a delete node function which will remove the node, reattach the subtree and also free or delete the node. +

    + +
    +
    void
    +delete_node(struct binary_tre **tree, struct binary_tree *node){
    +  struct binary_tree *new_root = remove_root_node(node);
    +
    +  // if deleting root node of tree
    +  if(node == (*tree)){
    +    (*tree) = new_root;
    +    free(node);
    +    return;
    +  }
    +
    +  // when not deleting root node of tree
    +  replace_child(find_parent(*tree, node)
    +                ,node ,new_root);
    +  free(node);
    +}
    +
    +
    +
    +
  2. +
+
+
+ +
+

5.3. Performance of BST

+
+

+The performance of the search operation depends on the height of the tree. If the tree has \(n\) elements, the height of a binary tree can be between \(n\) and \(floor\left( 1+ log_2(n) \right)\). +
+
+To perform an operation on BST, we need to find the node where we have perform the operation. Since even in worst case we only need to traverse the height of the search tree to search for any node, the time taken to perform any operation on a Binary Search Tree is \(\theta (h)\) where, \(h\) is the height of the tree. +
+
+A binary tree with height of \(floor(1 + log_2(n))\) is called a balanced binary tree, otherwise it is an unbalanced tree. A balanced binary tree is the shortest height a binary tree with that number of nodes can have. +
+
+The worst case is when tree has a single branch, making the height of tree n. In this case, the worst case for any operation takes \(\theta (n)\) time. +
+A balanced binary search tree in worst case for any operation will take \(\theta (log_2n)\) time. +

+
+
+ +
+

5.4. Traversing a Binary Tree

+
+

+There are three ways to traverse a binary tree, inorder tree walk, preorder tree walk and postorder tree walk. All three algorithm will take \(\theta (n)\) time to traverse the \(n\) nodes. +

+
+ +
+

5.4.1. Inorder tree walk

+
+

+This algorithm is named so because it first traverses the left sub-tree recursively, then the node value and then traverses right sub-tree recursively. +

+ +
+
void inorder_print(struct binary_tree * node){
+  if(node == NULL)
+    return;
+  // recursively print left sub-tree
+  inorder_print(node->left_child);
+  // print the node value
+  printf("%d\t", node->value);
+  // recursively print right sub-tree
+  inorder_print(node->right_child);
+}
+
+
+ +
    +
  • Inorder algorithm will traverse the binary search tree in a sorted order. Thus, it can be used to get nodes in a sorted order.
  • +
  • This algorithm is not suitable to delete or free the nodes of the tree. It should not be used to delete a binary tree.
  • +
  • This algorithm cannot we used to make a copy of a binay search tree.
  • +
+
+
+
+

5.4.2. Preorder tree walk

+
+

+This algorithm is called preorder algorithm because it will first traverse the current node, then recursively traverses the left sub-tree and then recursively traverse the right sub-tree. +

+
+
void preorder_print(struct binary_tree * node){
+  if(node == NULL)
+    return;
+  // print the node
+  printf("%d\t", node->value);
+  // recursively print left sub-tree
+  preorder_print(node->left_child);
+  // recursively print right sub-tree
+  preorder_print(node->right_child);
+}
+
+
+
    +
  • This algorithm is used to create a copy of the Binary Search Tree. If we store nodes in an array using this algorithm and then later insert the nodes linearly in a simple binary search tree, we will have an exact copy of the tree.
  • +
  • This algorithm traverses the tree in a topologically sorted order.
  • +
  • This algorithm cannot be used to delete or free the nodes of the tree.
  • +
+
+
+
+

5.4.3. Postorder tree walk

+
+

+In this algorithm, we first traverse the left sub-tree recursively, then the right-sub tree recursively and finally the node. +

+
+
void postorder_print(struct binary_tree * node){
+  if(node == NULL)
+    return;
+  // recursively print left sub-tree
+  postorder_print(node->left_child);
+  // recursively print right sub-tree
+  postorder_print(node->right_child);
+  // print the node
+  printf("%d\t", node->value);
+}
+
+
+
    +
  • This algorithm can be used to delete or free all the nodes of a binary tree.
  • +
  • This algorithm cannot be used to create a copy of the tree
  • +
+
+
+
+
+ +
+

6. Binary Heap

+
+

+Heap is a data structure represented as a complete tree which follows the heap property. All levels in a heap tree are completely filled except possible the last one, which is filled from left to right. +
+
+The most common implementation of the heap is a binary heap. The binary heap is represented as a binary tree. We can use an array to implement binary heaps. +
+
+The heap data structure is used to implement priority queues. In many cases we even refer to heaps as priority queues and vice versa. +

+
+ +
+

6.1. Heap Property

+
+

+Heaps are of two types +

+
    +
  • min-heap : the smallest element is at the root of the tree.
  • +
  • max-heap : the largest element is at the root of the tree.
  • +
+

+The heap property is different for min-heaps and max-heaps. +

+
    +
  • for min-heap : the key stored in parent node is always less than or equal \((\le)\) to the key of child node.
  • +
  • for max-heap : the key stored in parent node is always greter than or equal \((\ge)\) to the key of child node.
  • +
+
+
+ +
+

6.2. Shape of Heap

+
+

+Also reffered to as shape property of heap. +
+A heap is represented as a complete tree. A complete tree is one where all the levels are completely filled except possible the last. The last level if not completely filled is filled from left to right. +

+
+
+
+

6.3. Array implementation

+
+

+We can implement binary heap using arrays. The root of tree is the first element of the array. The next two elements are elements of second level of tree and children of the root node. Similary, the next four elements are elements of third level of tree and so on. +
+
+For a given level, the position in array from left to right is the position of elements in tree from left to right. +
+
+For example, a max-heap implemented using array can be represented as tree as shown +
+
+Heap-as-array.svg +
+
+In C, we can create a heap struct for easier implementation of algorithms +

+
+
struct heap_type{
+  int array[];
+  size_t capacity;
+  size_t len;
+};
+
+
+
+
+
+

6.4. Operations on heaps

+
+

+Both insertion and deletion in heap must be done in a way which conform to the heap property as well as shape property of heap. Before we can look at insertion and deletion, we need a way to find parent and child for a given index. We will also first see up-heapify and down-heapfiy funtions. +

+
+
+

6.4.1. Parent and child indices

+
+

+In a binary heap, we can find parent and children for any given index using simple formulas. +

+
    +
  • If array is zero indexed, for element at index i +
      +
    • children at indices \((2i + 1)\) and \((2i + 2)\)
    • +
    • parent at index \(floor\left( (i - 1)/2 \right)\)
    • +
  • +
  • If array is one indexed, for element at index i +
      +
    • children at indices \((2i)\) and \((2i + 1)\)
    • +
    • parent at index \(floor\left( i/2 \right)\)
    • +
  • +
+
+
+ +
+

6.4.2. Down-heapify

+
+

+The down-heapify is a function which can re-heapify an array if no element of heap violates the heap property other than index and it's two children. +
+This function runs in \(\theta (log_2n)\) time. The algorithm for this works as follows +

+
    +
  1. Compare the index element with its children and stop if in correct order in relation to both children.
  2. +
  3. If not in correct order, swap the index element with the children which is not in correct order. Repeat till in correct order or at the lowest level.
  4. +
+ +
+
void down_heapify(struct heap_type heap, size_t index){
+  size_t left = 2 * index  + 1;
+  size_t right = 2 * index + 2;
+  size_t largest = index;
+
+  if(left < heap.len && heap.array[left] > heap.array[largest])
+    largest = left;
+
+  if(right < heap.len && heap.array[right] > heap.array[largest])
+    largest = right;
+
+  if(largest != index){
+    swap(heap.array[index], heap.array[largest]);
+    down_heapify(heap, largest);
+  }
+}
+
+
+ +

+Since we shift element downwards, this operation is often called down-heap operation. It is also known as trickle-down, swim-down, heapify-down, or cascade-down +

+
+
+ +
+

6.4.3. Up-heapify

+
+

+The up-heapify is a function which can re-heapify an array if no element of heap violates the heap property other than index and it's parent. +
+This function runs in \(\theta (log_2n)\) time. The algorithm for this works as follows +

+
    +
  1. Compare the index element to its parent and stop algorithm if it is in correct order.
  2. +
  3. If not in correct order, swap element with its parent. Repeat till element in correct position or at root position.
  4. +
+ +
+
void up_heapify(struct heap_type heap, size_t index){
+  size_t parent = (index - 1) / 2;
+  size_t smallest = index;
+
+  if(parent >= 0 && heap.array[smallest] > heap.array[parent])
+    smallest = parent;
+
+  if(smallest != index){
+    swap(heap.array[index], heap.array[smallest]);
+    up_heapify(heap, smallest);
+  }
+}
+
+
+ +

+Since we shift element upwards, this operation is often called up-heap operation. It is also known as trickle-up, swim-up, heapify-up, or cascade-up +
+
+TODO : Maybe up-heapfiy funtion should be made cleaner rather than trying to mirror down-heapify funtion. +

+
+
+ +
+

6.4.4. Insertion

+
+

+Insertion takes \(\theta (log_2n)\) time in a binary heap. To insert and element in heap, we will add it to the end of the heap and then apply up-heapify operation of the elment +
+The code shows example of insertion in a max-heap. +

+ +
+
void insert_element(struct heap_type heap, int element){
+  // add element
+  size_t element_index = heap.len;
+  if(element_index == heap.capacity){
+    printf("Heap reached full capacity");
+    return;
+  }
+
+  heap.array[heap.len++] = element;
+  up_heapify(heap, heap.len - 1);
+}
+
+
+
+
+ +
+

6.4.5. Deletion or Extraction

+
+

+Like insertion, extraction also takes \(\theta (log_2n)\) time. Extraction from heap will extract the root element of the heap. We can use the down-heapify function in order to re-heapify after extracting the root node. +
+
+The code shows example of extraction in max-heap. +

+ +
+
int extract_element(struct heap_type heap){
+  if(heap.len < 1){
+    printf("No elements in the heap");
+    return -1;
+  }
+
+  int r = heap.array[0];
+  heap.array[0] = heap.array[heap.len - 1];
+  heap.len -= 1;
+
+  down_heapify(heap, 0);
+
+  return r;
+}
+
+
+
+
+ +
+

6.4.6. Insert then extract

+
+

+Inserting an element and then extracting from the heap can be done more efficiently than simply calling these functions seperately as defined previously. If we call both funtions we define above, we have to do an up-heap operation followed by a down-heap. Instead, there is a way to do just a single down-heap. +
+
+The algorithm for this will work as follows in a max-heap. +

+
    +
  1. Compare whether the item we are trying to push is greater than root of heap.
  2. +
  3. If item we are pushing is greater, return it.
  4. +
  5. Else, +
      +
    1. Replace root element with new item
    2. +
    3. Apply down-heapify on the root of heap
    4. +
    5. Return the orignal root heap which we replaced.
    6. +
  6. +
+ +

+In python, this is implemented by the name of heap replace. +

+
+
int heap_replace(struct heap_type heap, int element){
+  if(element > heap.array[0])
+    return element;
+
+  int r = heap.array[0];
+  swap(heap.array[0], element);
+  down_heapify(heap, 0);
+  return r;
+}
+
+
+
+
+ +
+

6.4.7. Searching

+
+

+Searching for a arbitrary element takes linear time in a heap. We use linear search to search for element in array. +

+
+
+
+

6.4.8. Deleting arbitray element

+
+

+For a max-heap, deleting an arbitrary element is done as follows +

+
    +
  1. Find the element to delete and get its index \(i\).
  2. +
  3. swap last element and the element at index \(i\), and decrease the size of heap.
  4. +
  5. apply down-heapify on index \(i\) if any of it's children violate the heap property else apply up-heapify if the parent element violates the heapify property.
  6. +
+
+
+
+

6.4.9. Decrease and increase keys

+
+

+TODO : I don't know if it is neccessary to do this operation. It looks simple to implement. +

+
+
+
+
+

6.5. Building a heap from array

+
+

+We can convert a normal array into a heap using the down-heapify operation in linear time \(\left( \theta (n) \right)\) +

+ +
+
// array.array[..] contains an array which is not a heap yet
+// this funtion will turn it into a correct heap
+void build_heap(int array[], size_t len){
+  for(int i = (len/2) - 1; i >= 0; i--)
+    down_heapify(array, i);
+}
+
+
+

+As we see, for zero indexed language, the range of for loop is [(len(array)/2) - 1, 0] +
+If we are using a one indexed language, then range of for loop is [len(array)/2, 1] +

+
+
+
+ +
+

7. Graphs

+
+

+A graph is a data structure which consists of nodes/vertices, and edges. We sometimes write it as \(G=(V,E)\), where \(V\) is the set of vertices and \(E\) is the set of edges. When we are working on runtime of algorithms related to graphs, we represent runtime in two input sizes. \(|V|\) which we simply write as \(V\) is the number of vertices and similarly \(E\) is the number of edges. +

+
+
+

7.1. Representing graphs

+
+

+We need a way to represent graphs in computers and to search a graph. Searching a graph means to systematically follow edges of graphs in order to reach vertices. +
+
+The two common ways of representing graphs are either using adjacency lists and adjacency matrix. Either can represent both directed and undirected graphs. +

+
+ +
+

7.1.1. Adjacency List

+
+

+Every node in the graph is represented by a linked list. The list contains the nodes to which the list node is connected by an edge. +
+Example, if list-0 contains node-3, then node-0 is connected to node-3 by an edge. +

+
    +
  • For undirected graphs this will simply work by storing all nodes in list who have a shared edge with list node.
  • +
  • For directed graphs we will only add node to list, if edge goes from list node to the stored node.
  • +
+

+So in our previous example, if list-0 contains node-3, then the edge goes from 0 to 3 in the directed graph. +
+
+The space taken by adjacency list representation is \(\theta (V + E)\). +
+Since each node represents an edge, it is easy to convert an adjacency representation graph to a weighted graph. A weighted graph is a graph where each edge has an associated weight. So the weight of (u, v) edge can be stored in the node-v of u's list. +
+The adjacency list representation is very robust and can represent various types of graph variants. +

+
+
+ +
+

7.1.2. Adjacency Matrix

+
+

+We use a single matrix to represent the graph. The size of the matrix is \(\left( |V| \times |V| \right)\). When we make the matrix, all it's elements are zero, i.e the matrix is zero initialized. +
+
+If there is an edge between vertices (x , y), we show it by setting +
+matrix[x][y] = true or matrix[x][y] = 1 +
+If there is not an edge between vertices (x , y), we set +
+matrix[x][y] = false or matrix [x][y] = 0 +

+
    +
  • For undirected graphs, to show edge (u , v) we have to set both matrix[u][v] and matrix[v][u] to 1.
  • +
  • For directed graphs, to show edge (u , v) which goes from u to v, we only set matrix[u][v] to 1.
  • +
+ +

+The space taken by adjacency matrix is \(\theta (V^2)\). +
+For undirected graphs, the matrix will be symmetrical along the diagonal, because matrix will be equal to it's own transpose. So we can save space by only storing half the matrix in memory. +
+
+When comparing asymptotic results, the adjacency list seems more efficient, but matrix has advantage of only storing 1 bit for each cell. So in denser graphs, the matrix may use less space. +
+
+We can store weighted graphs in adjacency matrix by storing the weights along with the edge information in matrix cells. +

+
+
+
+ +
+

7.2. Vertex and edge attributes

+
+

+Many times we have to store attributes with either vertices or edges or sometimes both. How this is differs by language. In notation, we will write it using a dot (.) +
+
+For example, the attribute x of v will be denoted as v.x +
+Similarly, the attribute x of edge (u , v) will be denoted as (u , v).x +

+
+
+
+

7.3. Density of graph

+
+

+Knowing the density of a graph can help us choose the way in which we represent our graph. +
+The formula for density of graph is +\[ \text{density} = \frac{\text{number of edges}}{\text{maximum possible edges}} \] +Maximum possible number of edges for a simple undirected graph is +\[ \frac{|V| \left( |V| - 1 \right)}{2} \] +Maximum possible number of edges for a simple directed graph is +\[ |V| \left( |V| - 1 \right) \] +Therefore, the density of a simple undirected graph will be +\[ \text{density (simple undirected)} = \frac{2|E|}{|V| \left( |V| - 1 \right)} \] +And density of simple directed directed graph will be +\[ \text{density (simple directed)} = \frac{|E|}{|V| \left( |V| - 1 \right)} \] +

+ +

+Therefore, maximum density for a graph is 1. The minimum density for a graph is 0. +
+Knowing this, we can say graph with low density is a sparse graph and graph with high density is a dense graph. +

+
+
+

7.3.1. Which representation to use

+
+

+For a quick approximation, when undirected graph and \(2|E|\) is close to \(|V|^2\), we say that graph is dense, else we say it is sparse. +
+Similarly, for directed graph when \(|E|\) is close to \(|V|^2\), we can say graph is dense, else it is sparse. +
+
+The list representation provides a more compact way to represent graph when the graph is sparse. Whereas matrix representation is better for dense graphs. +
+Another criteria is how algorithm will use the graph. If we want to traverse to neighbouring nodes, then list representation works well. If we want to quickly tell if there is an edge between two nodes, then matrix representation is better. +

+
+
+
+ +
+

7.4. Searching Graphs

+
+

+Graph search (or graph traversal) algorithms are used to explore a graph to find nodes and edges. Vertices not connected by edges are not explored by such algorithms. These algorithms start at a source vertex and traverse as much of the connected graph as possible. +
+
+Searching graphs algorithm can also be used on trees, because trees are also graphs. +

+
+
+

7.4.1. Breadth first search

+
+

+BFS is one of the simplest algorithms for searching a graph and is used as an archetype for many other graph algorithms. This algorithm works well with the adjacency list representation. +
+
+In BFS, the nodes are explored based on their distance from the starting node. What we mean by distance between nodes is how many edges are in between the two nodes. +
+
+So in BFS, all nodes at distance 1 are explored first, then nodes at distance 2 are explored, then nodes at distance 3 and so on. That is, all nodes at distance \(k\) are explored before exploring nodes at distance \((k+1)\). +

+
+
BFS(graph_type graph, node_type start){
+  queue_type queue;
+  start.explored = true;
+  queue.add(start);
+
+  while(queue.len != 0){
+    node_type v = queue.dequeue();
+    node_list adjacency_list = grap.adj_list(v);
+
+    while(adjacency_list != NULL){
+      node_type u = adjacency_list.node;
+      if(u.explored == false){
+        u.explored = true;
+        queue.add(u);
+      }
+      adjacency_list = adjacency_list.next;
+    }
+  }
+}
+
+
+ +
    +
  • Analysis
  • +
+

+For an input graph \(G=(V,E)\), every node is enqued only once and hence, dequeued only once. The time taken to enqueue and dequeue a single node is \(\theta (1)\), then the time for \(|V|\) nodes is, \(\theta (V)\). Each node in adjacency list represents an edge, therefore the time taken to explore each node in adjacency lists is \(\theta (E)\). Therefore, the total time complexity is +\[ \text{Time complexity of BFS : } \theta(V + E) \] +

+
+
+
+

7.4.2. Breadth-first trees for shortest path

+
+

+For a simple graph, we may want to get the shortest path between two nodes. This can be done by making a Breadth-first tree. +
+
+When we are traversing nodes using BFS, we can create a breadth-first tree. To make this tree, we simply need to set parent of u in the inner while loop in the BFS algorithm to v. So our algorithm from earlier will become. +

+
+
BFS_shortest_path(graph_type graph, node_type start, node_type end){
+  queue_type queue;
+  start.explored = true;
+  start.parent = NULL; // the start node is root node of tree
+  queue.add(start);
+
+  while(queue.len != 0){
+    node_type v = queue.dequeue();
+    node_list adjacency_list = grap.adj_list(v);
+    while(adjacency_list != NULL){
+      node_type u = adjacency_list.node;
+      if(u.explored == false){
+        u.explored = true;
+        u.parent = v; // the parent of u is v
+        queue.add(u);
+
+        if(u == end) return; // if we found the end node,
+                             // we have the path to it.
+      }
+
+      adjacency_list = adjacency_list.next;
+    }
+  }
+
+  printf("end node not in graph");
+}
+
+
+

+In this tree, the path upwards from any given node to start node will be the shortest path to the start node. +
+Therefore, we can get the shortest path now as follows +

+
+
print_shortest_path(graph_type graph, node_type start, node_type end){
+  BFS_shortest_path(graph, start, end);
+  while(end != NULL){
+    print_node(end);
+    end = end.parent;
+  }
+}
+
+
+

+This will print shortest path from end node to start node. +

+
+
+
+

7.4.3. Depth first search

+
+

+Unlike BFS, depth first search is more biased towards the farthest nodes of a graph. It follows a single path till it reaches the end of a path. After that, it back tracks to the last open path and follows that one. This process is repeated till all nodes are covered. +
+
+Implementation of DFS is very similar to BFS with two differences. Rather than using a queue, we use a stack. In BFS, the explored nodes are added to the queue, but in DFS we will add unexplored nodes to the stack. +

+ +
+
DFS(graph_type graph, node_type start){
+  stack_type stack;
+  stack.push(start);
+  while(stack.len != 0){
+    node_type v = stack.pop();
+    if(v.explored == false){
+      v.explored = true;
+
+      node_list adjacency_list = graph.adj_list(start);
+      while(adjacency_list != NULL){
+        stack.push(adjacency_list.node);
+        adjacency_list = adjacency_list.next;
+      }
+    }
+  }
+}
+
+
+ +

+Another way to implement DFS is recursively. +

+ +
+
DFS(graph_type graph, node_type node){
+  node.discovered = true;
+  node_list adjacency_list = graph.adj_list(node);
+  while(adjacency_list != NULL){
+    node_type u = adjacency_list.node;
+    if(u.discovered == false)
+      DFS(graph, u);
+    adjacency_list = adjacency_list.next;
+  }
+}
+
+
+ +

+The difference between recursive and iterative version of DFS is that, recursive will choose the path of first neighbour in the adjacency list, whereas the iterative will choose the path of last neighbour in the adjacency list. +

+ +
    +
  • Analysis
  • +
+

+For an input graph \(G=(V,E)\), the time complexity for Depth first search is \(\theta (V + E)\), i.e, it is the same of breadth first search. The reasoning for this is the same as before, all nodes are pushed and popped from stack only once, giving use time complexity of \(\theta (V)\). We go through all the adjacency lists only once giving time complexity \(\theta (E)\). Thus adding the two will give us +\[ \text{Time complexity of DFS : } \theta (V + E) \] +

+
+
+ +
+

7.4.4. Properties of DFS

+
+

+DFS is very useful to understand the structure of a graph. To understand the +

+
+
+
+

7.4.5. Topological sort using DFS

+
+
+
+
+
+

Author: Anmol Nawani

+

Created: 2023-07-30 Sun 18:20

+

Validate

+
+ + diff --git a/main.org b/main.org new file mode 100644 index 0000000..0403aa7 --- /dev/null +++ b/main.org @@ -0,0 +1,1161 @@ +#+TITLE: Data Structures +#+html_head: + +* Stack +A stack is a data structure which only allows insertion and deletion from one end of the array. The insertion is always on the extreme end of the array. The deletion can only be done on the element which was most recently added. +\\ +*It is similar to stacking plates.* The plate can only be added at the *top* of the stack and also only the last added plate to the stack can be removed (which will be on top). +\\ +Due to this property, Last In elements are removed First from a stack. Therefore, it is called a *Last In First Out (LIFO)* data structure or a *First In Last Out (FILO)* data structure. +\\ +To create a stack, we will keep track of the index which is the *top* of the array. This top index will *increment when we insert element* and *decrement when we remove element.* + +** Operation on stack +A stack has two operations + +* Direct Address Table +Direct Address Tables are useful when we know that key is within a small range. Then, we can allocate an array such that each possible key gets an index and just add the values according to the keys. +\\ +This also assumes that keys are integers + ++ Table creation + +#+BEGIN_SRC c +struct table{ + int * values; + size_t min_key; + size_t max_key; +}; + +struct table create_table(size_t min_key, size_t max_key){ + struct table r; + r.values = (int * ) malloc(sizeof(int) * (max_key - min_key + 1) ); + r.min_key = min_key; + r.max_key = max_key; + return r; +} +#+END_SRC + ++ Table insert + +#+BEGIN_SRC c +void table_insert(struct table t, size_t key, int value){ + if(key > t.max_key || key < t.min_key) + assert(false && "Key value out of boundry"); + + t.values[key - t.min_key] = value; +} +#+END_SRC + ++ Table delete + +#+BEGIN_SRC c +void table_delete(struct table t, size_t key){ + if(key > t.max_key || key < t.min_key) + assert(false && "Key value out of boundry"); + + t.values[key - t.min_key] = 0x00; +} +#+END_SRC + ++ Table Search / Table Get + +#+BEGIN_SRC c +int table_get(struct table t, size_t key){ + if(key > t.max_key || key < t.min_key) + assert(false && "Key value out of boundry"); + + return t.values[key - t.min_key]; +} +#+END_SRC + +*Using direct address tables is very useful when keys are enum values.* + +* Hash Table +When the set of possible keys is large, it is impractical to allocate a table big enough for all keys. In order to fit all possible keys into a small table, rather than directly using keys as the index for our array, we wil first calculate a /*hash*/ for it using a /*hash function*/. Since we are relying on hashes for this addressing in the table, we call it a hash table. +\\ +\\ +For a given key $k_i$ in */direct address table/*, we store value in $table[k_i]$. +\\ +\\ +For a given key $k_i$ in */hash table/*, we store value in $table[h(k_i)]$, where $h()$ is the hash function. +\\ +\\ +So the main purpose of the hash function is to reduce the range of array indices. + +** Collision + +Because we are reducing the range of indices, the hash function may /*hash two keys to the same slot*/. This is called a collision. +\\ +\\ +We should try to find a hash funtion which will minimise the number of collisions. +\\ +\\ +The number of keys is going to be greater than number of slots in table. Therefore avoiding all collisions is not possible. +\\ +There are two ways we will look at to resolve collision. +1. Chaining +2. Open addressing + +*** Chaining +In chaining, rather than storing values in table slots. We will have /*linked lists at each slot*/ which will store (key, value) pairs. +\\ +\\ +When the hash gives us a slot, we will add the value to linked list at that slot. + ++ Linked List structure + +#+BEGIN_SRC c + struct linked_list{ + size_t key; + int value; + struct linked_list * next; + }; +#+END_SRC + ++ Table structure + +#+BEGIN_SRC c + struct table{ + struct linked_list * table[]; + size_t table_size; + }; +#+END_SRC + ++ Insertion + +Insertion can be done in $\theta (1)$ time if we assume that key being inserted is not already in the linked list. But we can add a check to see if the key was already inserted and modify that value. + +#+BEGIN_SRC c + // linked_list_add(struct linked_list * ll, size_t key, int value) + // adds the given key,value to the start of the list + void chained_hash_insert(struct table t, size_t key, int value){ + linked_list_add(t.table[ h(key) ], key ,value); + } +#+END_SRC + ++ Get / Search + +#+BEGIN_SRC c + // linked_list_search(struct linked_list * ll, size_t key) + // gets the value stored with the given key + void chained_hash_get(struct table t, size_t key){ + return linked_list_search(t.table[ h(key) ], key); + } +#+END_SRC + ++ Delete + +#+BEGIN_SRC c + // linked_list_delete(struct linked_list * ll, size_t key) + // delete the node with the given key + void chained_hash_delete(struct table t, size_t key){ + linked_list_delete(t.table[ h(key) ], key); + } +#+END_SRC + +*** Performance of chaining hash table +The *load factor* is defined as number of elements per slot and is calculated as +\[ \alpha \text{(Load factor)} = \frac{\text{number of elements in hash table}}{\text{number of slots in hash table}} \] +The worst case for chaining is when all keys are assigned to a single slot. In this case searching for an element takes $\theta (n)$ time. +\\ +\\ +If we assume that any given element is equally likely to be hashed into any of the slots, this assumption is called */simple uniform hashing/*. +\\ +\\ +If we also assume that hash funtion takes constant time, then in the average case, the time complexity for searching key in the chaining hash table is +\[ \text{Average Case Searching} : \theta (1 + \alpha) \] +*** Open Addressing +In open addressing, all the key and value pair of entries are stored in the table itself. Because of this, the load factor $\left( \alpha \right)$ can never exceed 1. +\\ +\\ +When we get a key whose slot is already taken, we will look for another empty slot. This is done by what is called */probing/*. To get which slot to check next, we have various methods. +\\ +\\ +The sequence in which empty slots are looked for is fixed for given key, this sequence is called *probe sequence*. \\ +It is necessary to keep probe sequence fixed for any given key, so that we can search for it later. + +**** *Linear probing* +For a given *ordinary hash function* $h(k)$, the linear probing uses the hash function +\[ linear\_h(k, i) = (h(k) + 1)\ mod\ m \] +We refer to $h(k)$ as the */auxiliary hash function/*. +\\ +\\ +In linear probing, we first check the slot [h(k)], if it is not empty, we check [h(k) + 1] then [h(k) + 2] .... upto slot [m - 1] after which we wrap around to [1], [2] ... till we have checked all the slots. +\\ +\\ +Linear probing is easy to implement, but it suffers from */primary clustering/*. In long runs of linear probing, keys tend to cluster together. This causes the performance of operations on hash table to degrade. The time to query a random element from table degrades to $\theta (n)$. + +**** *Quadratic probing* +For given auxiliary hash function $h(k)$, the quadratic probing uses +\[ quadratic\_h(k, i) = \left( h(k) + c_1i + c_2i^2 \right) \ mod\ m \] +Where, $c_1$ and $c_2$ are positive auxiliary constants. ++ If m is not considered, we just assume $c_1 = 0, c_2 = 1$, this is the simplest form of quadratic probing. ++ For $m = 2^n$, a good choice for auxiliary constants is $c_1=c_2=1/2$. ++ For $m = n^p$ where m, n and p are positive integers greater or equal to 2, constants $c_1 = 1, c_2 = n$ are a good choice. + +Quadratic probing works much better than linear probing. +\\ +\\ +If $quadratic\_h(k_1, 0) = quadratic\_h(k_2,0)$, then that implies that all $quadratic\_h(k_1, i) = quadratic\_h(k_2,i)$, i.e, they will have the same *probe sequence*. This leads to a probe sequence getting clustered. This is called /*secondary clustering*/. This also effects performance but not as drastically as primary clustering. +**** *Double Hashing* +Double hashing is one of the best available method for open addressing. \\ +*Double hashing uses /two auxiliary hashing functions/.* +\[ double\_h(k, i) = \left( h_1(k) + i \times h_2(k) \right) \ mod\ m \] +The value of $h_2(k)$ must be *relatively prime (i.e, coprime) to number of slots (m)*. \\ ++ A convenient way to ensure this is let *m be a power of 2* and $h_2(k)$ be a *hash function that always produces an odd number*. ++ Another way is to let *m be a prime* and make $h_2(k)$ such that is *always produces a positive integer less than m.* +If we use one of the above two methods (either m is a power of 2 or a prime), then double hashing improves over linear and quadratic probing since keys will have distinct probe sequences. +\\ +\\ +When using the above values of m, performance of double hashing is very close to the performance of "ideal" scheme of uniform hashing. +**n* Performace of open addressing +In open addressing *load factor* $\left( \alpha \right) \le 1$. We will assume *uniform hashing* i.e, any element is equally likely to be hashed in any slot. We will also assume that for any key, each possible probe sequence is equally likely. +\\ +\\ +Under these assumptions, for load factor $\alpha$. The number of probes in an unsuccessful search is at most $1/(1 - \alpha )$ +\\ +This means that for a constant load factor, an unsuccessful search will run in $\theta (1)$ time. +\\ +\\ +The number of probes on average for inserting an element under these assumptions is $1/(1- \alpha )$ +\\ +The number of probes on averge in a successful search is at most $\frac{1}{\alpha} ln\left( \frac{1}{1-\alpha} \right)$ +** Hash Functions +A good hash funtion will approximately satisfy the *simple uniform hashing*, which means that any element is equally likely to be hashed to any slot. + +\[ m : \text{Number of slots in hash table} \] +\[ n : \text{Number of elements in hash table} \] + +Suppose we knew that our keys are from a set of real numbers and the keys are picked uniformly. In this case, we could simply use the hash function $h(k) = floor(mk)$. +\\ +\\ +Similarly, in many cases we can make a reasonably good hash funtion if we know the distribution of keys. +\\ +\\ +We will look at a few ways to make a hash function. + +*** The division method +In division method, we map a key $k$ into one of the $m$ slots by taking the remainder of k divided by m. +\[ h(k) = k\ mod\ m = k\ \%\ m \] +In most cases, +\[ m : \text{Number of slots in hash table} \] +But there are some cases where $m$ is chosen to be something else. ++ If $m$ is a *power of 2*, then $k\ mod\ m$ will give us the least significant $log_2m$ bits of $k$. When making a hash function, we want a function that depends on all bits of the key. So, */we should not use this method if m is a power of 2/*. ++ A *prime number* not close to a power of 2 is a good choice for $m$ in many cases. So when deciding the number of slots for the hash table, we can /*try to make $m$ a prime*/ which will accomodate our elements with less load factor. + +*** The multiplication method +In multiplication method, we first multiply the key $k$ with a constant $A$ which is in range $0 < A < 1$. Then we get the *fractional part* of $kA$. Then we multiply the fractional part by $m$ and floor it to get the hash. +\[ h(k) = floor(m \times decimal\_part(kA) ) \] +The advantage of multiplication method is that we can choose any value of $m$. We can even choose $m$ to be a power of 2. +\\ +We can choose any value of $A$. The value depends on characteristics of data, +\[ A \approx \frac{\sqrt{5} - 1}{2} \] +will work reasonably well. +\\ +\\ +Example, Suppose + +\[ key\ (k) = 1234 \] +\[ m = 128 \] +And our value of $A$ is, +\[ A = 0.618 \] +Then to get our $h(k)$, +\[ kA = 762.612 \] +\[ decimal\ part(kA) = 0.612 \] +\[ floor(m \times decimal\_part(kA) ) = h(k) = 78 \] + +In C language, +#+BEGIN_SRC c + size_t hash(size_t key, size_t m){ + double kA = key * 0.618; + // get decimal part only + double kA = kA - ((int) kA); + // floor the product of decimal part and m + size_t h = floor(m * kA); + return h; + } +#+END_SRC + +*** Mid square method +In this method, we square the keys and then we choose some digits from the middle. +Example, +\[ h(10) = middle\ digit \left( 10 \times 10 \right) = midlle\ digit (100) = 0 \] +\[ h(11) = middle\ digit \left( 11 \times 11 \right) = midlle\ digit (121) = 2 \] +\[ h(12) = middle\ digit \left( 12 \times 12 \right) = midlle\ digit (144) = 4 \] +With huge numbers, we need to take care of overflow conditions in this method. + +*** Folding method + +While this method can be used on integers, this method is usually used where the key is segmented. For example in arrays or when key is a string. +\\ +\\ +In this method, we add all of the segments and then we mod it with the number of slots. +\[ h(k) = \left( \text{Sum of all the segments} \right) mod\ m \] +Example, for string "hello" +\\ +sum = 'h' + 'e' + 'l' + 'l' + 'o' +\\ +sum = 104 + 101 + 108 + 108 + 111 = 532 +\\ +\\ +If m = 100, then +\\ +h(k) = 532 mod 100 +\\ +h(k) = 32 + +** Universal Hashing +TODO: Basics of universal hashing. +** Perfect Hashing +*NOTE*: This doesn't seem to be in B.Tech syllabus, but it seems cool. +\\ + +* Representing rooted trees using nodes +We can represent trees using nodes. A node only stores a single element of the tree. What is a node will depend on the language being used. +\\ +In C, we make a struct which will store the element and pointers to other node structs. + +#+BEGIN_SRC c + struct tree_node{ + int element; + struct tree_node * left_child; + struct tree_node * right_child; + }; +#+END_SRC +\\ +In languages with oop, we create node class which will store refrences to other node objects. +#+BEGIN_SRC java + class Node { + int value; + Node left; + Node right; + + Node(int value) { + this.value = value; + right = null; + left = null; + } + } +#+END_SRC + +** Fixed number of children +When we know how many children any given node can have, i.e, the number of children is bounded. We can just use refrences or pointers to the nodes directly. +\\ +For example, if we know we are making a binary tree, then we can just store refrence to left children and right childern. + +#+BEGIN_SRC c + struct tree_node{ + int element; + struct tree_node * left_child; + struct tree_node * right_child; + }; +#+END_SRC + +** Unbounded number of children +When we don't know how many children any given node will have. Thus any node can have any number of children, we can't just use refrences. We could create an array of refrences to nodes, but some nodes will only have one or two childs and some may have no childs. This will lead to a lot of wasted memory. +\\ +There is a way to represent such trees without wasting any memory. This is done by using *sibling refrences or pointers*. +\\ +#+BEGIN_SRC c + struct tree_node{ + int element; + struct tree_node * left_child; + struct tree_node * right_sibling; + }; +#+END_SRC + +The right sibling pointer will point to the right sibling of the node. This allows us to chain siblings and have unbounded number of siblings to the given node, therefore having unbounded number of children to any given parent. To make this approach easier to use, we can also add a pointer back to the parent node, though it is not compulsary. + +#+BEGIN_SRC c + struct tree_node{ + struct tree_node * parent; + + int element; + + struct tree_node * left_child; + struct tree_node * right_sibling; + }; +#+END_SRC + +So a tree which is like : +\\ +[[./imgs/tree_actual.jpg]] +\\ +\\ +can be represented using refrences and pointers as : +\\ +[[./imgs/tree_representation.jpg]] +\\ + +* Binary Search Trees +A tree where any node can have only two child nodes is called a */binary tree/*. +\\ +A binary search tree is a tree where for any give node *the nodes stored in left sub-tree are less than the parent node* and the *nodes stored in right sub-tree are greater than the parent node* (or vice versa). So the left-subtree always have smaller elements and right sub-tree always have greater elements. +\\ +\\ +This property allows us easily search for elements from the data structure. We start our search at the root node. If the element we want is less than the current node, we will go to the left node ,else we will go to the right node. The concept is similar to the binary search on arrays. + +In C, we can make a binary tree as +#+BEGIN_SRC c + struct binary_tree{ + int value; + struct binary_tree * left_child; + struct binary_tree * right_child; + }; +#+END_SRC + +** Quering a BST +Some common ways in which we usually query a BST are searching for a node, minimum & maximum node and successor & predecessor nodes. We will also look at how we can get the parent node for a given node, if we already store a parent pointer then that algorithm will be unnecessary. +*** Searching for node +We can search for a node very effectively with the help of binary search tree property. The search will return the node if it is found, else it will return NULL. +#+BEGIN_SRC c + struct binary_tree * + search_recursively(struct binary_tree * root, int value){ + // If we reach a null, then value is not in tree + if(root == NULL) + return NULL; + // if we found the value, return the current node + if(root->value == value) + return root; + // compare value we are looking for + // and go to either left or right sub-tree + if(value < root->value) + return search_recursively(root->left, value); + else + return search_recursively(root->right, value); + } +#+END_SRC +We can also search iteratively rather than recursively. +#+BEGIN_SRC c + struct binary_tree * + search_iterative(struct binary_tree * root, int value){ + while(root != NULL){ + // if we found the value, return the current node + if(root->value == value) return root; + // compare value and go to left or right sub-tree + root = (value < root->value) ? root->left : root->right; + } + // if not found then return NULL + return NULL; + } +#+END_SRC +*** Minimum and maximum +Finding the minimum and maximum is simple in a Binary Search Tree. The minimum element will be the leftmost node and maximum will be the rightmost node. We can get the minimum and maximum nodes by using these algorithms. ++ For minimum node +#+BEGIN_SRC c + struct binary_tree * minimum(struct binary_tree * root){ + if(root == NULL) return NULL; + while(root->left != NULL) + root = root->left; + return root; + } +#+END_SRC ++ For maximum node +#+BEGIN_SRC c + struct binary_tree * maximum(struct binary_tree * root){ + if(root == NULL) return NULL; + while(root->right != NULL) + root = root->right; + return root; + } +#+END_SRC + +*** Find Parent Node +This algorithm will return the parent node. It uses a trailing node to get the parent. If the root node is given, then it will return NULL. *This algorithm makes the assumption that the node is in the tree*. +#+BEGIN_SRC c + struct binary_tree * + find_parent(struct binary_tree * tree, struct binary_tree * node){ + if(tree == node) return NULL; + + struct binary_tree * current_node = tree; + struct binary_tree * trailing_node = tree; + + while(current_node != node){ + trailing_node = current_node; + current_node = (node->value < current_node->value) ? + current_node->left : + current_node->right; + } + + return trailing_node; + } +#+END_SRC +*** Is ancestor +This algorithm will take two nodes, ancestor and descendant. Then it will check if ancestor node is really the ancestor of descendant node. +#+BEGIN_SRC c + bool + is_ancestor(struct binary_tree *ancestor, + struct binary_tree *descendant){ + // both ancestor and descendant + // should not be NULL + if(ancestor == NULL || descendant == NULL) + return false; + + while(ancestor != NULL){ + if(ancestor == descendant) return true; + ancestor = (descendant->value < ancestor->value) ? + ancestor->left : + ancestor->right; + } + return false; + } +#+END_SRC +*** Successor and predecessor +We often need to find the successor or predecessor of an element in a Binary Search Tree. The search for predecessor and succesor is divided in to two cases. + +**** *For Successor* +#+BEGIN_SRC c + // get successor of x + struct binary_tree * + successor(struct binary_tree * tree, struct binary_tree * x){ + // case 1 : right subtree is non-empty + if(x->right != NULL){ + return minimum(x->right); + } + // case 2 : right subtree is empty + struct binary_tree * y = find_parent(tree, x); + while(y != NULL){ + if(is_ancestor(y, x) && is_ancestor(y->left, x)) return y; + y = find_parent(tree, y); + } + return NULL; + } +#+END_SRC +*Case 1* : If the node x has a right subtree, then the minimum of right subtree of x is the succesor. +\\ +*Case 2* : If the node x has no right subtree, then successor may or may not exist. If it exists, the successor node will be the ancestor of x whose own left node is also the ancestor of x. +**** *For Predecessor* +#+BEGIN_SRC c + struct binary_tree * + predecessor(struct binary_tree * tree, struct binary_tree * x){ + // case 1 : left subtree is non-empty + if(x->left != NULL){ + return maximum(x->left); + } + // case 2 : left subtree is empty + struct binary_tree * y = find_parent(tree, x); + while(y != NULL){ + if(is_ancestor(y, x) && is_ancestor(y->right, x)) return y; + y = find_parent(tree, y); + } + return NULL; + } +#+END_SRC +*Case 1* : If the node x has a left subtree, then the maximum of left subtree of x is the predecessor. +\\ +*Case 2* : If the node x has no left subtree, then predecessor may or may not exist. If it exists, the predecessor node will be the ancestor of x whose own right node is also the ancestor of x. +** Inserting and Deleting nodes +When inserting and deleting nodes in BST, we need to make sure that the Binary Search Tree property continues to hold. Inserting node is easier in a binary search tree than deleting a node. +*** Insertion +Insertion is simple in a binary search tree. We search for the node we want to insert in the tree and insert it where we find first NULL spot. +#+BEGIN_SRC c + void + insert_node(struct binary_tree ** tree, struct binary_tree * node){ + // if found a null spot, insert the node + if(*tree == NULL){ + *tree = node; + return; + } + if(node->value < (*tree)->value){ + // the node is to be inserted into left subtree + struct binary_tree ** left_tree = &((*tree)->left); + insert_node(left_tree, node); + }else{ + // the node is to be inserted into right subtree + struct binary_tree ** right_tree = &((*tree)->right); + insert_node(right_tree, node); + } + } +#+END_SRC +The recursive algorithm for inserting into a Binary search tree is simpler than the iterative algorithm. +\\ +\\ +The algorithm for iterative insertion is +#+BEGIN_SRC c + void + insert_node(struct binary_tree **tree, struct binary_tree * node){ + // if no nodes in tree, then just node and return + if((*tree) == NULL){ + ,*tree = node; + return; + } + + struct binary_tree ** current_node = tree; + struct binary_tree ** trailing_node = tree; + + // look for an empty place using current_node + while(*current_node != NULL){ + trailing_node = current_node; + current_node = (node->value < (*current_node)->value) ? + &((*current_node)->left) : &((*current_node)->right); + } + + // we need to insert node on the trailing node + if(node->value < (*trailing_node)->value) + (*trailing_node)->left = node; + else + (*trailing_node)->right = node; + } +#+END_SRC +*** Deletion +Deletion in Binary Search Trees is tricky because we need to delete nodes in a way that the property of the Binary Search Tree holds after the deletion of the node. So we first have to remove the node from the tree before we can free it. +\\ +\\ +TODO : Write four cases of node deletion here +**** *Implementation in code* +We also use a helper function called Replace Child for deletion of node. This function will simply take parent node, old child node and new child node and replace old child with new child. + +#+BEGIN_SRC c + void + replace_child(struct binary_tree *parent, + struct binary_tree *old_child, + struct binary_tree *new_child){ + if(parent->left == old_child) parent->left = new_child; + else parent->right = new_child; + } +#+END_SRC + +We will create a funtion that will remove the root node from a given subtree and then return the root node of the result subtree. +This will allow us to apply remove root node funtion on any node and then reattach the new subtree. +\\ +\\ +Making remove root node a different funtion will also allow us to not worry about attaching the the subtree immediately in the same funtion. + +#+BEGIN_SRC c + struct binary_tree * + remove_root_node(struct binary_tree *root){ + // case 1 : no child + // this case can be skipped in real implementation + // as it is covered by the case 2 + if(root->left == NULL && root->right == NULL){ + return NULL; + } + + // case 2 : one child + if(root->left == NULL){ + return root->right; + }else if(root->right == NULL){ + return root->left; + } + + struct binary_tree *successor = minimum(root->right); + // case 3 : two child and successor is right node of root node + if(successor == root->right){ + successor->left = root->left; + return successor; + } + + // case 4 : two child and successor is not the right node of root node + struct binary_tree *successor_parent = find_parent(root, successor); + replace_child(successor_parent, successor, successor->right); + successor->left = root->left; + successor->right = root->right; + return successor; + } +#+END_SRC + +Now we can make a delete node function which will remove the node, reattach the subtree and also free or delete the node. + +#+BEGIN_SRC c + void + delete_node(struct binary_tre **tree, struct binary_tree *node){ + struct binary_tree *new_root = remove_root_node(node); + + // if deleting root node of tree + if(node == (*tree)){ + (*tree) = new_root; + free(node); + return; + } + + // when not deleting root node of tree + replace_child(find_parent(*tree, node) + ,node ,new_root); + free(node); + } +#+END_SRC + +** Performance of BST +The performance of the search operation depends on the height of the tree. If the tree has $n$ elements, the height of a binary tree can be between $n$ and $floor\left( 1+ log_2(n) \right)$. +\\ +\\ +To perform an operation on BST, we need to find the node where we have perform the operation. Since even in worst case *we only need to traverse the height of the search tree to search for any node*, the time taken to perform any operation on a Binary Search Tree is $\theta (h)$ where, $h$ is the height of the tree. +\\ +\\ +A binary tree with height of $floor(1 + log_2(n))$ is called a *balanced binary tree*, otherwise it is an unbalanced tree. A balanced binary tree is the shortest height a binary tree with that number of nodes can have. +\\ +\\ +The worst case is when tree has a single branch, making the height of tree n. In this case, the worst case for any operation takes $\theta (n)$ time. +\\ +A balanced binary search tree in worst case for any operation will take $\theta (log_2n)$ time. + +** Traversing a Binary Tree +There are three ways to traverse a binary tree, inorder tree walk, preorder tree walk and postorder tree walk. All three algorithm will take $\theta (n)$ time to traverse the $n$ nodes. + +*** Inorder tree walk +This algorithm is named so because it first traverses the left sub-tree recursively, then the node value and then traverses right sub-tree recursively. + +#+BEGIN_SRC c + void inorder_print(struct binary_tree * node){ + if(node == NULL) + return; + // recursively print left sub-tree + inorder_print(node->left_child); + // print the node value + printf("%d\t", node->value); + // recursively print right sub-tree + inorder_print(node->right_child); + } +#+END_SRC + ++ *Inorder algorithm will traverse the binary search tree in a sorted order.* Thus, it can be used to get nodes in a sorted order. ++ This algorithm is not suitable to delete or free the nodes of the tree. It should not be used to delete a binary tree. ++ This algorithm cannot we used to make a copy of a binay search tree. +*** Preorder tree walk +This algorithm is called preorder algorithm because it will first traverse the current node, then recursively traverses the left sub-tree and then recursively traverse the right sub-tree. +#+BEGIN_SRC c + void preorder_print(struct binary_tree * node){ + if(node == NULL) + return; + // print the node + printf("%d\t", node->value); + // recursively print left sub-tree + preorder_print(node->left_child); + // recursively print right sub-tree + preorder_print(node->right_child); + } +#+END_SRC ++ *This algorithm is used to create a copy of the Binary Search Tree*. If we store nodes in an array using this algorithm and then later insert the nodes linearly in a simple binary search tree, we will have an exact copy of the tree. ++ This algorithm traverses the tree in a *topologically sorted* order. ++ This algorithm cannot be used to delete or free the nodes of the tree. +*** Postorder tree walk +In this algorithm, we first traverse the left sub-tree recursively, then the right-sub tree recursively and finally the node. +#+BEGIN_SRC c + void postorder_print(struct binary_tree * node){ + if(node == NULL) + return; + // recursively print left sub-tree + postorder_print(node->left_child); + // recursively print right sub-tree + postorder_print(node->right_child); + // print the node + printf("%d\t", node->value); + } +#+END_SRC ++ *This algorithm can be used to delete or free all the nodes of a binary tree*. ++ This algorithm cannot be used to create a copy of the tree + +* Binary Heap +Heap is a data structure represented as a complete tree which follows the heap property. All levels in a heap tree are completely filled except possible the last one, which is filled from left to right. +\\ +\\ +The most common implementation of the heap is a *binary heap*. The binary heap is represented as a binary tree. We can use an array to implement binary heaps. +\\ +\\ +The heap data structure is used to implement *priority queues*. In many cases we even refer to heaps as priority queues and vice versa. + +** Heap Property +Heaps are of two types ++ *min-heap* : the smallest element is at the root of the tree. ++ *max-heap* : the largest element is at the root of the tree. +The heap property is different for min-heaps and max-heaps. ++ *for min-heap* : the key stored in parent node is always less than or equal $(\le)$ to the key of child node. ++ *for max-heap* : the key stored in parent node is always greter than or equal $(\ge)$ to the key of child node. + +** Shape of Heap +Also reffered to as *shape property* of heap. +\\ +A heap is represented as a complete tree. A complete tree is one where all the levels are completely filled except possible the last. The last level if not completely filled is filled from left to right. +** Array implementation +We can implement binary heap using arrays. The root of tree is the first element of the array. The next two elements are elements of second level of tree and children of the root node. Similary, the next four elements are elements of third level of tree and so on. +\\ +\\ +/*For a given level, the position in array from left to right is the position of elements in tree from left to right.*/ +\\ +\\ +For example, a max-heap implemented using array can be represented as tree as shown +\\ +\\ +[[./imgs/Heap-as-array.svg]] +\\ +\\ +In C, we can create a heap struct for easier implementation of algorithms +#+BEGIN_SRC c + struct heap_type{ + int array[]; + size_t capacity; + size_t len; + }; +#+END_SRC +** Operations on heaps +Both insertion and deletion in heap must be done in a way which conform to the heap property as well as shape property of heap. Before we can look at insertion and deletion, we need a way to find parent and child for a given index. We will also first see up-heapify and down-heapfiy funtions. +*** Parent and child indices +In a binary heap, we can find parent and children for any given index using simple formulas. ++ If array is zero indexed, for element at index i + + children at indices $(2i + 1)$ and $(2i + 2)$ + + parent at index $floor\left( (i - 1)/2 \right)$ ++ If array is one indexed, for element at index i + + children at indices $(2i)$ and $(2i + 1)$ + + parent at index $floor\left( i/2 \right)$ + +*** Down-heapify +The down-heapify is a function which can re-heapify an array if no element of heap violates the heap property other than index and it's two children. +\\ +This function runs in $\theta (log_2n)$ time. The algorithm for this works as follows +1. Compare the index element with its children and stop if in correct order in relation to both children. +2. If not in correct order, swap the index element with the children which is not in correct order. Repeat till in correct order or at the lowest level. + +#+BEGIN_SRC c + void down_heapify(struct heap_type heap, size_t index){ + size_t left = 2 * index + 1; + size_t right = 2 * index + 2; + size_t largest = index; + + if(left < heap.len && heap.array[left] > heap.array[largest]) + largest = left; + + if(right < heap.len && heap.array[right] > heap.array[largest]) + largest = right; + + if(largest != index){ + swap(heap.array[index], heap.array[largest]); + down_heapify(heap, largest); + } + } +#+END_SRC + +Since we shift element downwards, this operation is often called /down-heap/ operation. It is also known as /trickle-down, swim-down, heapify-down, or cascade-down/ + +*** Up-heapify +The up-heapify is a function which can re-heapify an array if no element of heap violates the heap property other than index and it's parent. +\\ +This function runs in $\theta (log_2n)$ time. The algorithm for this works as follows +1. Compare the index element to its parent and stop algorithm if it is in correct order. +2. If not in correct order, swap element with its parent. Repeat till element in correct position or at root position. + +#+BEGIN_SRC c + void up_heapify(struct heap_type heap, size_t index){ + size_t parent = (index - 1) / 2; + size_t smallest = index; + + if(parent >= 0 && heap.array[smallest] > heap.array[parent]) + smallest = parent; + + if(smallest != index){ + swap(heap.array[index], heap.array[smallest]); + up_heapify(heap, smallest); + } + } +#+END_SRC + +Since we shift element upwards, this operation is often called /up-heap/ operation. It is also known as /trickle-up, swim-up, heapify-up, or cascade-up/ +\\ +\\ +*TODO* : Maybe up-heapfiy funtion should be made cleaner rather than trying to mirror down-heapify funtion. + +*** Insertion +Insertion takes $\theta (log_2n)$ time in a binary heap. To insert and element in heap, we will add it to the end of the heap and then apply up-heapify operation of the elment +\\ +The code shows example of insertion in a max-heap. + +#+BEGIN_SRC c + void insert_element(struct heap_type heap, int element){ + // add element + size_t element_index = heap.len; + if(element_index == heap.capacity){ + printf("Heap reached full capacity"); + return; + } + + heap.array[heap.len++] = element; + up_heapify(heap, heap.len - 1); + } +#+END_SRC + +*** Deletion or Extraction +Like insertion, extraction also takes $\theta (log_2n)$ time. Extraction from heap will extract the root element of the heap. We can use the down-heapify function in order to re-heapify after extracting the root node. +\\ +\\ +The code shows example of extraction in max-heap. + +#+BEGIN_SRC c + int extract_element(struct heap_type heap){ + if(heap.len < 1){ + printf("No elements in the heap"); + return -1; + } + + int r = heap.array[0]; + heap.array[0] = heap.array[heap.len - 1]; + heap.len -= 1; + + down_heapify(heap, 0); + + return r; + } +#+END_SRC + +*** Insert then extract +Inserting an element and then extracting from the heap can be done more efficiently than simply calling these functions seperately as defined previously. If we call both funtions we define above, we have to do an up-heap operation followed by a down-heap. Instead, there is a way to do just a single down-heap. +\\ +\\ +The algorithm for this will work as follows in a max-heap. +1. Compare whether the item we are trying to push is greater than root of heap. +2. If item we are pushing is greater, return it. +3. Else, + 1. Replace root element with new item + 2. Apply down-heapify on the root of heap + 3. Return the orignal root heap which we replaced. + +In python, this is implemented by the name of */heap replace/*. +#+BEGIN_SRC c + int heap_replace(struct heap_type heap, int element){ + if(element > heap.array[0]) + return element; + + int r = heap.array[0]; + swap(heap.array[0], element); + down_heapify(heap, 0); + return r; + } +#+END_SRC + +*** Searching +Searching for a arbitrary element takes linear time in a heap. We use linear search to search for element in array. +*** Deleting arbitray element +For a max-heap, deleting an arbitrary element is done as follows +1. Find the element to delete and get its index $i$. +2. swap last element and the element at index $i$, and decrease the size of heap. +3. apply down-heapify on index $i$ if any of it's children violate the heap property else apply up-heapify if the parent element violates the heapify property. +*** Decrease and increase keys +TODO : I don't know if it is neccessary to do this operation. It looks simple to implement. +** Building a heap from array +We can convert a normal array into a heap using the down-heapify operation in linear time $\left( \theta (n) \right)$ + +#+BEGIN_SRC c + // array.array[..] contains an array which is not a heap yet + // this funtion will turn it into a correct heap + void build_heap(int array[], size_t len){ + for(int i = (len/2) - 1; i >= 0; i--) + down_heapify(array, i); + } +#+END_SRC +As we see, for */zero indexed language/*, the range of for loop is [(len(array)/2) - 1, 0] +\\ +If we are using a */one indexed language/*, then range of for loop is [len(array)/2, 1] + +* Graphs +A graph is a data structure which consists of nodes/vertices, and edges. We sometimes write it as $G=(V,E)$, where $V$ is the set of vertices and $E$ is the set of edges. When we are working on runtime of algorithms related to graphs, we represent runtime in two input sizes. $|V|$ which we simply write as $V$ is the number of vertices and similarly $E$ is the number of edges. +** Representing graphs +We need a way to represent graphs in computers and to search a graph. Searching a graph means to systematically follow edges of graphs in order to reach vertices. +\\ +\\ +The two common ways of representing graphs are either using adjacency lists and adjacency matrix. Either can represent both directed and undirected graphs. + +*** Adjacency List +Every node in the graph is represented by a linked list. The list contains the nodes to which the list node is connected by an edge. +\\ +Example, if list-0 contains node-3, then node-0 is connected to node-3 by an edge. ++ For *undirected graphs* this will simply work by storing all nodes in list who have a shared edge with list node. ++ For *directed graphs* we will only add node to list, if edge goes from list node to the stored node. +So in our previous example, if list-0 contains node-3, then the edge goes from 0 to 3 in the directed graph. +\\ +\\ +The space taken by adjacency list representation is $\theta (V + E)$. +\\ +Since each node represents an edge, it is easy to convert an adjacency representation graph to a *weighted graph*. A weighted graph is a graph where each edge has an associated weight. So the weight of (u, v) edge can be stored in the node-v of u's list. +\\ +The adjacency list representation is very robust and can represent various types of graph variants. + +*** Adjacency Matrix +We use a single matrix to represent the graph. The size of the matrix is $\left( |V| \times |V| \right)$. When we make the matrix, all it's elements are zero, i.e the matrix is zero initialized. +\\ +\\ +If there is an edge between vertices (x , y), we show it by setting +\\ +matrix[x][y] = true */or/* matrix[x][y] = 1 +\\ +If there is not an edge between vertices (x , y), we set +\\ +matrix[x][y] = false */or/* matrix [x][y] = 0 ++ For undirected graphs, to show edge (u , v) we have to set both matrix[u][v] and matrix[v][u] to 1. ++ For directed graphs, to show edge (u , v) which goes from u to v, we only set matrix[u][v] to 1. + +The space taken by adjacency matrix is $\theta (V^2)$. +\\ +For undirected graphs, the matrix will be symmetrical along the diagonal, because matrix will be equal to it's own *transpose*. So we can save space by only storing half the matrix in memory. +\\ +\\ +When comparing asymptotic results, the adjacency list seems more efficient, but matrix has advantage of only storing 1 bit for each cell. So in denser graphs, the matrix may use less space. +\\ +\\ +We can store weighted graphs in adjacency matrix by storing the weights along with the edge information in matrix cells. + +** Vertex and edge attributes +Many times we have to store attributes with either vertices or edges or sometimes both. How this is differs by language. In notation, we will write it using a dot (.) +\\ +\\ +For example, the attribute x of v will be denoted as v.x +\\ +Similarly, the attribute x of edge (u , v) will be denoted as (u , v).x +** Density of graph +Knowing the density of a graph can help us choose the way in which we represent our graph. +\\ +The formula for density of graph is +\[ \text{density} = \frac{\text{number of edges}}{\text{maximum possible edges}} \] +Maximum possible number of edges for a simple undirected graph is +\[ \frac{|V| \left( |V| - 1 \right)}{2} \] +Maximum possible number of edges for a simple directed graph is +\[ |V| \left( |V| - 1 \right) \] +Therefore, the density of a simple undirected graph will be +\[ \text{density (simple undirected)} = \frac{2|E|}{|V| \left( |V| - 1 \right)} \] +And density of simple directed directed graph will be +\[ \text{density (simple directed)} = \frac{|E|}{|V| \left( |V| - 1 \right)} \] + +Therefore, maximum density for a graph is 1. The minimum density for a graph is 0. +\\ +Knowing this, we can say graph with low density is a sparse graph and graph with high density is a dense graph. +*** Which representation to use +For a quick approximation, when undirected graph and $2|E|$ is close to $|V|^2$, we say that graph is dense, else we say it is sparse. +\\ +Similarly, for directed graph when $|E|$ is close to $|V|^2$, we can say graph is dense, else it is sparse. +\\ +\\ +The list representation provides a more compact way to represent graph when the graph is *sparse*. Whereas matrix representation is better for *dense* graphs. +\\ +Another criteria is how algorithm will use the graph. If we want to traverse to neighbouring nodes, then list representation works well. If we want to quickly tell if there is an edge between two nodes, then matrix representation is better. + +** Searching Graphs +Graph search (or graph traversal) algorithms are used to explore a graph to find nodes and edges. Vertices not connected by edges are not explored by such algorithms. These algorithms start at a source vertex and traverse as much of the connected graph as possible. +\\ +\\ +Searching graphs algorithm can also be used on trees, because trees are also graphs. +*** Breadth first search +BFS is one of the simplest algorithms for searching a graph and is used as an archetype for many other graph algorithms. This algorithm works well with the adjacency list representation. +\\ +\\ +In BFS, the nodes are explored based on their distance from the starting node. What we mean by distance between nodes is how many edges are in between the two nodes. +\\ +\\ +So in BFS, all nodes at distance 1 are explored first, then nodes at distance 2 are explored, then nodes at distance 3 and so on. That is, all nodes at distance $k$ are explored before exploring nodes at distance $(k+1)$. +#+BEGIN_SRC c + BFS(graph_type graph, node_type start){ + queue_type queue; + start.explored = true; + queue.add(start); + + while(queue.len != 0){ + node_type v = queue.dequeue(); + node_list adjacency_list = grap.adj_list(v); + + while(adjacency_list != NULL){ + node_type u = adjacency_list.node; + if(u.explored == false){ + u.explored = true; + queue.add(u); + } + adjacency_list = adjacency_list.next; + } + } + } +#+END_SRC + ++ *Analysis* +For an input graph $G=(V,E)$, every node is enqued only once and hence, dequeued only once. The time taken to enqueue and dequeue a single node is $\theta (1)$, then the time for $|V|$ nodes is, $\theta (V)$. Each node in adjacency list represents an edge, therefore the time taken to explore each node in adjacency lists is $\theta (E)$. Therefore, the total time complexity is +\[ \text{Time complexity of BFS : } \theta(V + E) \] +*** Breadth-first trees for shortest path +For a simple graph, we may want to get the shortest path between two nodes. This can be done by making a Breadth-first tree. +\\ +\\ +When we are traversing nodes using BFS, we can create a breadth-first tree. To make this tree, we simply need to set parent of u in the inner while loop in the BFS algorithm to v. So our algorithm from earlier will become. +#+BEGIN_SRC c + BFS_shortest_path(graph_type graph, node_type start, node_type end){ + queue_type queue; + start.explored = true; + start.parent = NULL; // the start node is root node of tree + queue.add(start); + + while(queue.len != 0){ + node_type v = queue.dequeue(); + node_list adjacency_list = grap.adj_list(v); + while(adjacency_list != NULL){ + node_type u = adjacency_list.node; + if(u.explored == false){ + u.explored = true; + u.parent = v; // the parent of u is v + queue.add(u); + + if(u == end) return; // if we found the end node, + // we have the path to it. + } + + adjacency_list = adjacency_list.next; + } + } + + printf("end node not in graph"); + } +#+END_SRC +In this tree, the path upwards from any given node to start node will be the shortest path to the start node. +\\ +Therefore, we can get the shortest path now as follows +#+BEGIN_SRC c + print_shortest_path(graph_type graph, node_type start, node_type end){ + BFS_shortest_path(graph, start, end); + while(end != NULL){ + print_node(end); + end = end.parent; + } + } +#+END_SRC +This will print shortest path from end node to start node. +*** Depth first search +Unlike BFS, depth first search is more biased towards the farthest nodes of a graph. It follows a single path till it reaches the end of a path. After that, it back tracks to the last open path and follows that one. This process is repeated till all nodes are covered. +\\ +\\ +Implementation of DFS is very similar to BFS with two differences. Rather than using a queue, we use a *stack*. In BFS, the explored nodes are added to the queue, but in DFS we will add unexplored nodes to the stack. + +#+BEGIN_SRC c + DFS(graph_type graph, node_type start){ + stack_type stack; + stack.push(start); + while(stack.len != 0){ + node_type v = stack.pop(); + if(v.explored == false){ + v.explored = true; + + node_list adjacency_list = graph.adj_list(start); + while(adjacency_list != NULL){ + stack.push(adjacency_list.node); + adjacency_list = adjacency_list.next; + } + } + } + } +#+END_SRC + +Another way to implement DFS is recursively. + +#+BEGIN_SRC c + DFS(graph_type graph, node_type node){ + node.discovered = true; + node_list adjacency_list = graph.adj_list(node); + while(adjacency_list != NULL){ + node_type u = adjacency_list.node; + if(u.discovered == false) + DFS(graph, u); + adjacency_list = adjacency_list.next; + } + } +#+END_SRC + +The difference between recursive and iterative version of DFS is that, recursive will choose the path of first neighbour in the adjacency list, whereas the iterative will choose the path of last neighbour in the adjacency list. + ++ *Analysis* +For an input graph $G=(V,E)$, the time complexity for Depth first search is $\theta (V + E)$, i.e, it is the same of breadth first search. The reasoning for this is the same as before, all nodes are pushed and popped from stack only once, giving use time complexity of $\theta (V)$. We go through all the adjacency lists only once giving time complexity $\theta (E)$. Thus adding the two will give us +\[ \text{Time complexity of DFS : } \theta (V + E) \] + +*** Properties of DFS +DFS is very useful to understand the structure of a graph. To understand the +*** Topological sort using DFS diff --git a/main.tsk b/main.tsk new file mode 100644 index 0000000..d48896f --- /dev/null +++ b/main.tsk @@ -0,0 +1,7 @@ +*Export to HTML +#do +emacs --script src/export.el + +*Remove intermediate +#do +rm main.html~ diff --git a/src/export.el b/src/export.el new file mode 100644 index 0000000..65d5dfd --- /dev/null +++ b/src/export.el @@ -0,0 +1,9 @@ +;; In elisp, default-directory is the current directory +(add-to-list 'load-path "src") +;; If htmlize is outdated, just replace htmlize.el with the newer version lmao. +(require 'htmlize) + +(load-theme 'tsdh-light) + +(find-file "main.org") +(org-html-export-to-html) diff --git a/src/htmlize.el b/src/htmlize.el new file mode 100644 index 0000000..b158a65 --- /dev/null +++ b/src/htmlize.el @@ -0,0 +1,1864 @@ +;;; htmlize.el --- Convert buffer text and decorations to HTML. -*- lexical-binding: t -*- + +;; Copyright (C) 1997-2003,2005,2006,2009,2011,2012,2014,2017,2018,2020 Hrvoje Niksic + +;; Author: Hrvoje Niksic +;; Homepage: https://github.com/hniksic/emacs-htmlize +;; Keywords: hypermedia, extensions +;; Version: 1.57 + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This package converts the buffer text and the associated +;; decorations to HTML. Mail to to discuss +;; features and additions. All suggestions are more than welcome. + +;; To use it, just switch to the buffer you want HTML-ized and type +;; `M-x htmlize-buffer'. You will be switched to a new buffer that +;; contains the resulting HTML code. You can edit and inspect this +;; buffer, or you can just save it with C-x C-w. `M-x htmlize-file' +;; will find a file, fontify it, and save the HTML version in +;; FILE.html, without any additional intervention. `M-x +;; htmlize-many-files' allows you to htmlize any number of files in +;; the same manner. `M-x htmlize-many-files-dired' does the same for +;; files marked in a dired buffer. + +;; htmlize supports three types of HTML output, selected by setting +;; `htmlize-output-type': `css', `inline-css', and `font'. In `css' +;; mode, htmlize uses cascading style sheets to specify colors; it +;; generates classes that correspond to Emacs faces and uses ... to color parts of text. In this mode, the +;; produced HTML is valid under the 4.01 strict DTD, as confirmed by +;; the W3C validator. `inline-css' is like `css', except the CSS is +;; put directly in the STYLE attribute of the SPAN element, making it +;; possible to paste the generated HTML into existing HTML documents. +;; In `font' mode, htmlize uses ... to +;; colorize HTML, which is not standard-compliant, but works better in +;; older browsers. `css' mode is the default. + +;; You can also use htmlize from your Emacs Lisp code. When called +;; non-interactively, `htmlize-buffer' and `htmlize-region' will +;; return the resulting HTML buffer, but will not change current +;; buffer or move the point. htmlize will do its best to work on +;; non-windowing Emacs sessions but the result will be limited to +;; colors supported by the terminal. + +;; htmlize aims for compatibility with older Emacs versions. Please +;; let me know if it doesn't work on the version of GNU Emacs that you +;; are using. The package relies on the presence of CL extensions; +;; please don't try to remove that dependency. I see no practical +;; problems with using the full power of the CL extensions, except +;; that one might learn to like them too much. + +;; The latest version is available at: +;; +;; +;; +;; + +;; Thanks go to the many people who have sent reports and contributed +;; comments, suggestions, and fixes. They include Ron Gut, Bob +;; Weiner, Toni Drabik, Peter Breton, Ville Skytta, Thomas Vogels, +;; Juri Linkov, Maciek Pasternacki, and many others. + +;; User quotes: "You sir, are a sick, sick, _sick_ person. :)" +;; -- Bill Perry, author of Emacs/W3 + + +;;; Code: + +(require 'cl-lib) +(eval-when-compile + (defvar font-lock-auto-fontify) + (defvar font-lock-support-mode) + (defvar global-font-lock-mode)) + +(defconst htmlize-version "1.57") + +(defgroup htmlize nil + "Convert buffer text and faces to HTML." + :group 'hypermedia) + +(defcustom htmlize-head-tags "" + "Additional tags to insert within HEAD of the generated document." + :type 'string + :group 'htmlize) + +(defcustom htmlize-output-type 'css + "Output type of generated HTML, one of `css', `inline-css', or `font'. +When set to `css' (the default), htmlize will generate a style sheet +with description of faces, and use it in the HTML document, specifying +the faces in the actual text with . + +When set to `inline-css', the style will be generated as above, but +placed directly in the STYLE attribute of the span ELEMENT: . This makes it easier to paste the resulting HTML to +other documents. + +When set to `font', the properties will be set using layout tags +, , , , and . + +`css' output is normally preferred, but `font' is still useful for +supporting old, pre-CSS browsers, and both `inline-css' and `font' for +easier embedding of colorized text in foreign HTML documents (no style +sheet to carry around)." + :type '(choice (const css) (const inline-css) (const font)) + :group 'htmlize) + +(defcustom htmlize-use-images t + "Whether htmlize generates `img' for images attached to buffer contents." + :type 'boolean + :group 'htmlize) + +(defcustom htmlize-force-inline-images nil + "Non-nil means generate all images inline using data URLs. +Normally htmlize converts image descriptors with :file properties to +relative URIs, and those with :data properties to data URIs. With this +flag set, the images specified as a file name are loaded into memory and +embedded in the HTML as data URIs." + :type 'boolean + :group 'htmlize) + +(defcustom htmlize-max-alt-text 100 + "Maximum size of text to use as ALT text in images. + +Normally when htmlize encounters text covered by the `display' property +that specifies an image, it generates an `alt' attribute containing the +original text. If the text is larger than `htmlize-max-alt-text' characters, +this will not be done." + :type 'integer + :group 'htmlize) + +(defcustom htmlize-transform-image 'htmlize-default-transform-image + "Function called to modify the image descriptor. + +The function is called with the image descriptor found in the buffer and +the text the image is supposed to replace. It should return a (possibly +different) image descriptor property list or a replacement string to use +instead of of the original buffer text. + +Returning nil is the same as returning the original text." + :type 'boolean + :group 'htmlize) + +(defcustom htmlize-generate-hyperlinks t + "Non-nil means auto-generate the links from URLs and mail addresses in buffer. + +This is on by default; set it to nil if you don't want htmlize to +autogenerate such links. Note that this option only turns off automatic +search for contents that looks like URLs and converting them to links. +It has no effect on whether htmlize respects the `htmlize-link' property." + :type 'boolean + :group 'htmlize) + +(defcustom htmlize-hyperlink-style " + a { + color: inherit; + background-color: inherit; + font: inherit; + text-decoration: inherit; + } + a:hover { + text-decoration: underline; + } +" + "The CSS style used for hyperlinks when in CSS mode." + :type 'string + :group 'htmlize) + +(defcustom htmlize-replace-form-feeds t + "Non-nil means replace form feeds in source code with HTML separators. +Form feeds are the ^L characters at line beginnings that are sometimes +used to separate sections of source code. If this variable is set to +`t', form feed characters are replaced with the
separator. If this +is a string, it specifies the replacement to use. Note that
 is
+temporarily closed before the separator is inserted, so the default
+replacement is effectively \"

\".  If you specify
+another replacement, don't forget to close and reopen the 
 if you
+want the output to remain valid HTML.
+
+If you need more elaborate processing, set this to nil and use
+htmlize-after-hook."
+  :type 'boolean
+  :group 'htmlize)
+
+(defcustom htmlize-html-charset nil
+  "The charset declared by the resulting HTML documents.
+When non-nil, causes htmlize to insert the following in the HEAD section
+of the generated HTML:
+
+  
+
+where CHARSET is the value you've set for htmlize-html-charset.  Valid
+charsets are defined by MIME and include strings like \"iso-8859-1\",
+\"iso-8859-15\", \"utf-8\", etc.
+
+If you are using non-Latin-1 charsets, you might need to set this for
+your documents to render correctly.  Also, the W3C validator requires
+submitted HTML documents to declare a charset.  So if you care about
+validation, you can use this to prevent the validator from bitching.
+
+Needless to say, if you set this, you should actually make sure that
+the buffer is in the encoding you're claiming it is in.  (This is
+normally achieved by using the correct file coding system for the
+buffer.)  If you don't understand what that means, you should probably
+leave this option in its default setting."
+  :type '(choice (const :tag "Unset" nil)
+		 string)
+  :group 'htmlize)
+
+(defcustom htmlize-convert-nonascii-to-entities t
+  "Whether non-ASCII characters should be converted to HTML entities.
+
+When this is non-nil, characters with codes in the 128-255 range will be
+considered Latin 1 and rewritten as \"&#CODE;\".  Characters with codes
+above 255 will be converted to \"&#UCS;\", where UCS denotes the Unicode
+code point of the character.  If the code point cannot be determined,
+the character will be copied unchanged, as would be the case if the
+option were nil.
+
+When the option is nil, the non-ASCII characters are copied to HTML
+without modification.  In that case, the web server and/or the browser
+must be set to understand the encoding that was used when saving the
+buffer.  (You might also want to specify it by setting
+`htmlize-html-charset'.)
+
+Note that in an HTML entity \"&#CODE;\", CODE is always a UCS code point,
+which has nothing to do with the charset the page is in.  For example,
+\"©\" *always* refers to the copyright symbol, regardless of charset
+specified by the META tag or the charset sent by the HTTP server.  In
+other words, \"©\" is exactly equivalent to \"©\".
+
+For most people htmlize will work fine with this option left at the
+default setting; don't change it unless you know what you're doing."
+  :type 'sexp
+  :group 'htmlize)
+
+(defcustom htmlize-ignore-face-size 'absolute
+  "Whether face size should be ignored when generating HTML.
+If this is nil, face sizes are used.  If set to t, sizes are ignored
+If set to `absolute', only absolute size specifications are ignored.
+Please note that font sizes only work with CSS-based output types."
+  :type '(choice (const :tag "Don't ignore" nil)
+		 (const :tag "Ignore all" t)
+		 (const :tag "Ignore absolute" absolute))
+  :group 'htmlize)
+
+(defcustom htmlize-css-name-prefix ""
+  "The prefix used for CSS names.
+The CSS names that htmlize generates from face names are often too
+generic for CSS files; for example, `font-lock-type-face' is transformed
+to `type'.  Use this variable to add a prefix to the generated names.
+The string \"htmlize-\" is an example of a reasonable prefix."
+  :type 'string
+  :group 'htmlize)
+
+(defcustom htmlize-use-rgb-txt t
+  "Whether `rgb.txt' should be used to convert color names to RGB.
+
+This conversion means determining, for instance, that the color
+\"IndianRed\" corresponds to the (205, 92, 92) RGB triple.  `rgb.txt'
+is the X color database that maps hundreds of color names to such RGB
+triples.  When this variable is non-nil, `htmlize' uses `rgb.txt' to
+look up color names.
+
+If this variable is nil, htmlize queries Emacs for RGB components of
+colors using `color-instance-rgb-components' and `color-values'.
+This can yield incorrect results on non-true-color displays.
+
+If the `rgb.txt' file is not found (which will be the case if you're
+running Emacs on non-X11 systems), this option is ignored."
+  :type 'boolean
+  :group 'htmlize)
+
+(defvar htmlize-face-overrides nil
+  "Overrides for face definitions.
+
+Normally face definitions are taken from Emacs settings for fonts
+in the current frame.  For faces present in this plist, the
+definitions will be used instead.  Keys in the plist are symbols
+naming the face and values are the overriding definitions.  For
+example:
+
+  (setq htmlize-face-overrides
+        '(font-lock-warning-face \"black\"
+          font-lock-function-name-face \"red\"
+          font-lock-comment-face \"blue\"
+          default (:foreground \"dark-green\" :background \"yellow\")))
+
+This variable can be also be `let' bound when running `htmlize-buffer'.")
+
+(defcustom htmlize-untabify t
+  "Non-nil means untabify buffer contents during htmlization."
+  :type 'boolean
+  :group 'htmlize)
+
+(defcustom htmlize-html-major-mode nil
+  "The mode the newly created HTML buffer will be put in.
+Set this to nil if you prefer the default (fundamental) mode."
+  :type '(radio (const :tag "No mode (fundamental)" nil)
+		 (function-item html-mode)
+		 (function :tag "User-defined major mode"))
+  :group 'htmlize)
+
+(defcustom htmlize-pre-style nil
+  "When non-nil, `
' tags will be decorated with style
+information in `font' and `inline-css' modes. This allows a
+consistent background for captures of regions."
+  :type 'boolean
+  :group 'htmlize)
+
+(defvar htmlize-before-hook nil
+  "Hook run before htmlizing a buffer.
+The hook functions are run in the source buffer (not the resulting HTML
+buffer).")
+
+(defvar htmlize-after-hook nil
+  "Hook run after htmlizing a buffer.
+Unlike `htmlize-before-hook', these functions are run in the generated
+HTML buffer.  You may use them to modify the outlook of the final HTML
+output.")
+
+(defvar htmlize-file-hook nil
+  "Hook run by `htmlize-file' after htmlizing a file, but before saving it.")
+
+(defvar htmlize-buffer-places)
+
+;;; Some cross-Emacs compatibility.
+
+;; We need a function that efficiently finds the next change of a
+;; property regardless of whether the change occurred because of a
+;; text property or an extent/overlay.
+(defun htmlize-next-change (pos prop &optional limit)
+  (if prop
+      (next-single-char-property-change pos prop nil limit)
+    (next-char-property-change pos limit)))
+
+(defun htmlize-overlay-faces-at (pos)
+  (delq nil (mapcar (lambda (o) (overlay-get o 'face)) (overlays-at pos))))
+
+(defun htmlize-next-face-change (pos &optional limit)
+  ;; (htmlize-next-change pos 'face limit) would skip over entire
+  ;; overlays that specify the `face' property, even when they
+  ;; contain smaller text properties that also specify `face'.
+  ;; Emacs display engine merges those faces, and so must we.
+  (or limit
+      (setq limit (point-max)))
+  (let ((next-prop (next-single-property-change pos 'face nil limit))
+        (overlay-faces (htmlize-overlay-faces-at pos)))
+    (while (progn
+             (setq pos (next-overlay-change pos))
+             (and (< pos next-prop)
+                  (equal overlay-faces (htmlize-overlay-faces-at pos)))))
+    (setq pos (min pos next-prop))
+    ;; Additionally, we include the entire region that specifies the
+    ;; `display' property.
+    (when (get-char-property pos 'display)
+      (setq pos (next-single-char-property-change pos 'display nil limit)))
+    pos))
+
+(defmacro htmlize-lexlet (&rest letforms)
+  (declare (indent 1) (debug let))
+  (if (and (boundp 'lexical-binding)
+           lexical-binding)
+      `(let ,@letforms)
+    ;; cl extensions have a macro implementing lexical let
+    `(lexical-let ,@letforms)))
+
+
+;;; Transformation of buffer text: HTML escapes, untabification, etc.
+
+(defvar htmlize-basic-character-table
+  ;; Map characters in the 0-127 range to either one-character strings
+  ;; or to numeric entities.
+  (let ((table (make-vector 128 ?\0)))
+    ;; Map characters in the 32-126 range to themselves, others to
+    ;; &#CODE entities;
+    (dotimes (i 128)
+      (setf (aref table i) (if (and (>= i 32) (<= i 126))
+			       (char-to-string i)
+			     (format "&#%d;" i))))
+    ;; Set exceptions manually.
+    (setf
+     ;; Don't escape newline, carriage return, and TAB.
+     (aref table ?\n) "\n"
+     (aref table ?\r) "\r"
+     (aref table ?\t) "\t"
+     ;; Escape &, <, and >.
+     (aref table ?&) "&"
+     (aref table ?<) "<"
+     (aref table ?>) ">"
+     ;; Not escaping '"' buys us a measurable speedup.  It's only
+     ;; necessary to quote it for strings used in attribute values,
+     ;; which htmlize doesn't typically do.
+     ;(aref table ?\") """
+     )
+    table))
+
+;; A cache of HTML representation of non-ASCII characters.  Depending
+;; on the setting of `htmlize-convert-nonascii-to-entities', this maps
+;; non-ASCII characters to either "&#;" or "" (mapconcat's
+;; mapper must always return strings).  It's only filled as characters
+;; are encountered, so that in a buffer with e.g. French text, it will
+;; only ever contain French accented characters as keys.  It's cleared
+;; on each entry to htmlize-buffer-1 to allow modifications of
+;; `htmlize-convert-nonascii-to-entities' to take effect.
+(defvar htmlize-extended-character-cache (make-hash-table :test 'eq))
+
+(defun htmlize-protect-string (string)
+  "HTML-protect string, escaping HTML metacharacters and I18N chars."
+  ;; Only protecting strings that actually contain unsafe or non-ASCII
+  ;; chars removes a lot of unnecessary funcalls and consing.
+  (if (not (string-match "[^\r\n\t -%'-;=?-~]" string))
+      string
+    (mapconcat (lambda (char)
+		 (cond
+		  ((< char 128)
+		   ;; ASCII: use htmlize-basic-character-table.
+		   (aref htmlize-basic-character-table char))
+		  ((gethash char htmlize-extended-character-cache)
+		   ;; We've already seen this char; return the cached
+		   ;; string.
+		   )
+		  ((not htmlize-convert-nonascii-to-entities)
+		   ;; If conversion to entities is not desired, always
+		   ;; copy the char literally.
+		   (setf (gethash char htmlize-extended-character-cache)
+			 (char-to-string char)))
+		  ((< char 256)
+		   ;; Latin 1: no need to call encode-char.
+		   (setf (gethash char htmlize-extended-character-cache)
+			 (format "&#%d;" char)))
+		  ((encode-char char 'ucs)
+                   ;; Must check if encode-char works for CHAR;
+                   ;; it fails for Arabic and possibly elsewhere.
+		   (setf (gethash char htmlize-extended-character-cache)
+			 (format "&#%d;" (encode-char char 'ucs))))
+		  (t
+		   ;; encode-char doesn't work for this char.  Copy it
+		   ;; unchanged and hope for the best.
+		   (setf (gethash char htmlize-extended-character-cache)
+			 (char-to-string char)))))
+	       string "")))
+
+(defun htmlize-attr-escape (string)
+  ;; Like htmlize-protect-string, but also escapes double-quoted
+  ;; strings to make it usable in attribute values.
+  (setq string (htmlize-protect-string string))
+  (if (not (string-match "\"" string))
+      string
+    (mapconcat (lambda (char)
+                 (if (eql char ?\")
+                     """
+                   (char-to-string char)))
+               string "")))
+
+(defsubst htmlize-concat (list)
+  (if (and (consp list) (null (cdr list)))
+      ;; Don't create a new string in the common case where the list only
+      ;; consists of one element.
+      (car list)
+    (apply #'concat list)))
+
+(defun htmlize-format-link (linkprops text)
+  (let ((uri (if (stringp linkprops)
+                 linkprops
+               (plist-get linkprops :uri)))
+        (escaped-text (htmlize-protect-string text)))
+    (if uri
+        (format "%s" (htmlize-attr-escape uri) escaped-text)
+      escaped-text)))
+
+(defun htmlize-escape-or-link (string)
+  ;; Escape STRING and/or add hyperlinks.  STRING comes from a
+  ;; `display' property.
+  (let ((pos 0) (end (length string)) outlist)
+    (while (< pos end)
+      (let* ((link (get-char-property pos 'htmlize-link string))
+             (next-link-change (next-single-property-change
+                                pos 'htmlize-link string end))
+             (chunk (substring string pos next-link-change)))
+        (push
+         (cond (link
+                (htmlize-format-link link chunk))
+               ((get-char-property 0 'htmlize-literal chunk)
+                chunk)
+               (t
+                (htmlize-protect-string chunk)))
+         outlist)
+        (setq pos next-link-change)))
+    (htmlize-concat (nreverse outlist))))
+
+(defun htmlize-display-prop-to-html (display text)
+  (let (desc)
+    (cond ((stringp display)
+           ;; Emacs ignores recursive display properties.
+           (htmlize-escape-or-link display))
+          ((not (eq (car-safe display) 'image))
+           (htmlize-protect-string text))
+          ((null (setq desc (funcall htmlize-transform-image
+                                     (cdr display) text)))
+           (htmlize-escape-or-link text))
+          ((stringp desc)
+           (htmlize-escape-or-link desc))
+          (t
+           (htmlize-generate-image desc text)))))
+
+(defun htmlize-string-to-html (string)
+  ;; Convert the string to HTML, including images attached as
+  ;; `display' property and links as `htmlize-link' property.  In a
+  ;; string without images or links, this is equivalent to
+  ;; `htmlize-protect-string'.
+  (let ((pos 0) (end (length string)) outlist)
+    (while (< pos end)
+      (let* ((display (get-char-property pos 'display string))
+             (next-display-change (next-single-property-change
+                                   pos 'display string end))
+             (chunk (substring string pos next-display-change)))
+        (push
+         (if display
+             (htmlize-display-prop-to-html display chunk)
+           (htmlize-escape-or-link chunk))
+         outlist)
+        (setq pos next-display-change)))
+    (htmlize-concat (nreverse outlist))))
+
+(defun htmlize-default-transform-image (imgprops _text)
+  "Default transformation of image descriptor to something usable in HTML.
+
+If `htmlize-use-images' is nil, the function always returns nil, meaning
+use original text.  Otherwise, it tries to find the image for images that
+specify a file name.  If `htmlize-force-inline-images' is non-nil, it also
+converts the :file attribute to :data and returns the modified property
+list."
+  (when htmlize-use-images
+    (when (plist-get imgprops :file)
+      (let ((location (plist-get (cdr (find-image (list imgprops))) :file)))
+        (when location
+          (setq imgprops (plist-put (cl-copy-list imgprops) :file location)))))
+    (if htmlize-force-inline-images
+        (let ((location (plist-get imgprops :file))
+              data)
+          (when location
+            (with-temp-buffer
+              (condition-case nil
+                  (progn
+                    (insert-file-contents-literally location)
+                    (setq data (buffer-string)))
+                (error nil))))
+          ;; if successful, return the new plist, otherwise return
+          ;; nil, which will use the original text
+          (and data
+               (plist-put (plist-put imgprops :file nil)
+                          :data data)))
+      imgprops)))
+
+(defun htmlize-alt-text (_imgprops origtext)
+  (and (/= (length origtext) 0)
+       (<= (length origtext) htmlize-max-alt-text)
+       (not (string-match "[\0-\x1f]" origtext))
+       origtext))
+
+(defun htmlize-generate-image (imgprops origtext)
+  (let* ((alt-text (htmlize-alt-text imgprops origtext))
+         (alt-attr (if alt-text
+                       (format " alt=\"%s\"" (htmlize-attr-escape alt-text))
+                     "")))
+    (cond ((plist-get imgprops :file)
+           ;; Try to find the image in image-load-path
+           (let* ((found-props (cdr (find-image (list imgprops))))
+                  (file (or (plist-get found-props :file)
+                            (plist-get imgprops :file))))
+             (format ""
+                     (htmlize-attr-escape (file-relative-name file))
+                     alt-attr)))
+          ((plist-get imgprops :data)
+           (format ""
+                   (or (plist-get imgprops :type) "")
+                   (base64-encode-string (plist-get imgprops :data))
+                   alt-attr)))))
+
+(defconst htmlize-ellipsis "...")
+(put-text-property 0 (length htmlize-ellipsis) 'htmlize-ellipsis t htmlize-ellipsis)
+
+(defun htmlize-match-inv-spec (inv)
+  (cl-member inv buffer-invisibility-spec
+             :key (lambda (i)
+                    (if (symbolp i) i (car i)))))
+
+(defun htmlize-decode-invisibility-spec (invisible)
+  ;; Return t, nil, or `ellipsis', depending on how invisible text should be inserted.
+
+  (if (not (listp buffer-invisibility-spec))
+      ;; If buffer-invisibility-spec is not a list, then all
+      ;; characters with non-nil `invisible' property are visible.
+      (not invisible)
+
+    ;; Otherwise, the value of a non-nil `invisible' property can be:
+    ;; 1. a symbol -- make the text invisible if it matches
+    ;;    buffer-invisibility-spec.
+    ;; 2. a list of symbols -- make the text invisible if
+    ;;    any symbol in the list matches
+    ;;    buffer-invisibility-spec.
+    ;; If the match of buffer-invisibility-spec has a non-nil
+    ;; CDR, replace the invisible text with an ellipsis.
+    (let ((match (if (symbolp invisible)
+                     (htmlize-match-inv-spec invisible)
+                   (cl-some #'htmlize-match-inv-spec invisible))))
+      (cond ((null match) t)
+            ((cdr-safe (car match)) 'ellipsis)
+            (t nil)))))
+
+(defun htmlize-add-before-after-strings (beg end text)
+  ;; Find overlays specifying before-string and after-string in [beg,
+  ;; pos).  If any are found, splice them into TEXT and return the new
+  ;; text.
+  (let (additions)
+    (dolist (overlay (overlays-in beg end))
+      (let ((before (overlay-get overlay 'before-string))
+            (after (overlay-get overlay 'after-string)))
+        (when after
+          (push (cons (- (overlay-end overlay) beg)
+                      after)
+                additions))
+        (when before
+          (push (cons (- (overlay-start overlay) beg)
+                      before)
+                additions))))
+    (if additions
+        (let ((textlist nil)
+              (strpos 0))
+          (dolist (add (cl-stable-sort additions #'< :key #'car))
+            (let ((addpos (car add))
+                  (addtext (cdr add)))
+              (push (substring text strpos addpos) textlist)
+              (push addtext textlist)
+              (setq strpos addpos)))
+          (push (substring text strpos) textlist)
+          (apply #'concat (nreverse textlist)))
+      text)))
+
+(defun htmlize-copy-prop (prop beg end string)
+  ;; Copy the specified property from the specified region of the
+  ;; buffer to the target string.  We cannot rely on Emacs to copy the
+  ;; property because we want to handle properties coming from both
+  ;; text properties and overlays.
+  (let ((pos beg))
+    (while (< pos end)
+      (let ((value (get-char-property pos prop))
+            (next-change (htmlize-next-change pos prop end)))
+        (when value
+          (put-text-property (- pos beg) (- next-change beg)
+                             prop value string))
+        (setq pos next-change)))))
+
+(defun htmlize-get-text-with-display (beg end)
+  ;; Like buffer-substring-no-properties, except it copies the
+  ;; `display' property from the buffer, if found.
+  (let ((text (buffer-substring-no-properties beg end)))
+    (htmlize-copy-prop 'display beg end text)
+    (htmlize-copy-prop 'htmlize-link beg end text)
+    (setq text (htmlize-add-before-after-strings beg end text))
+    text))
+
+(defun htmlize-buffer-substring-no-invisible (beg end)
+  ;; Like buffer-substring-no-properties, but don't copy invisible
+  ;; parts of the region.  Where buffer-substring-no-properties
+  ;; mandates an ellipsis to be shown, htmlize-ellipsis is inserted.
+  (let ((pos beg)
+	visible-list invisible show last-show next-change)
+    ;; Iterate over the changes in the `invisible' property and filter
+    ;; out the portions where it's non-nil, i.e. where the text is
+    ;; invisible.
+    (while (< pos end)
+      (setq invisible (get-char-property pos 'invisible)
+	    next-change (htmlize-next-change pos 'invisible end)
+            show (htmlize-decode-invisibility-spec invisible))
+      (cond ((eq show t)
+	     (push (htmlize-get-text-with-display pos next-change)
+                   visible-list))
+            ((and (eq show 'ellipsis)
+                  (not (eq last-show 'ellipsis))
+                  ;; Conflate successive ellipses.
+                  (push htmlize-ellipsis visible-list))))
+      (setq pos next-change last-show show))
+    (htmlize-concat (nreverse visible-list))))
+
+(defun htmlize-trim-ellipsis (text)
+  ;; Remove htmlize-ellipses ("...") from the beginning of TEXT if it
+  ;; starts with it.  It checks for the special property of the
+  ;; ellipsis so it doesn't work on ordinary text that begins with
+  ;; "...".
+  (if (get-text-property 0 'htmlize-ellipsis text)
+      (substring text (length htmlize-ellipsis))
+    text))
+
+(defconst htmlize-tab-spaces
+  ;; A table of strings with spaces.  (aref htmlize-tab-spaces 5) is
+  ;; like (make-string 5 ?\ ), except it doesn't cons.
+  (let ((v (make-vector 32 nil)))
+    (dotimes (i (length v))
+      (setf (aref v i) (make-string i ?\ )))
+    v))
+
+(defun htmlize-untabify-string (text start-column)
+  "Untabify TEXT, assuming it starts at START-COLUMN."
+  (let ((column start-column)
+	(last-match 0)
+	(chunk-start 0)
+	chunks match-pos tab-size)
+    (while (string-match "[\t\n]" text last-match)
+      (setq match-pos (match-beginning 0))
+      (cond ((eq (aref text match-pos) ?\t)
+	     ;; Encountered a tab: create a chunk of text followed by
+	     ;; the expanded tab.
+	     (push (substring text chunk-start match-pos) chunks)
+	     ;; Increase COLUMN by the length of the text we've
+	     ;; skipped since last tab or newline.  (Encountering
+	     ;; newline resets it.)
+	     (cl-incf column (- match-pos last-match))
+	     ;; Calculate tab size based on tab-width and COLUMN.
+	     (setq tab-size (- tab-width (% column tab-width)))
+	     ;; Expand the tab, carefully recreating the `display'
+	     ;; property if one was on the TAB.
+             (let ((display (get-text-property match-pos 'display text))
+                   (expanded-tab (aref htmlize-tab-spaces tab-size)))
+               (when display
+                 (put-text-property 0 tab-size 'display display expanded-tab))
+               (push expanded-tab chunks))
+	     (cl-incf column tab-size)
+	     (setq chunk-start (1+ match-pos)))
+	    (t
+	     ;; Reset COLUMN at beginning of line.
+	     (setq column 0)))
+      (setq last-match (1+ match-pos)))
+    ;; If no chunks have been allocated, it means there have been no
+    ;; tabs to expand.  Return TEXT unmodified.
+    (if (null chunks)
+	text
+      (when (< chunk-start (length text))
+	;; Push the remaining chunk.
+	(push (substring text chunk-start) chunks))
+      ;; Generate the output from the available chunks.
+      (htmlize-concat (nreverse chunks)))))
+
+(defun htmlize-extract-text (beg end trailing-ellipsis)
+  ;; Extract buffer text, sans the invisible parts.  Then
+  ;; untabify it and escape the HTML metacharacters.
+  (let ((text (htmlize-buffer-substring-no-invisible beg end)))
+    (when trailing-ellipsis
+      (setq text (htmlize-trim-ellipsis text)))
+    ;; If TEXT ends up empty, don't change trailing-ellipsis.
+    (when (> (length text) 0)
+      (setq trailing-ellipsis
+            (get-text-property (1- (length text))
+                               'htmlize-ellipsis text)))
+    (when htmlize-untabify
+      (setq text (htmlize-untabify-string text (current-column))))
+    (setq text (htmlize-string-to-html text))
+    (cl-values text trailing-ellipsis)))
+
+(defun htmlize-despam-address (string)
+  "Replace every occurrence of '@' in STRING with %40.
+This is used to protect mailto links without modifying their meaning."
+  ;; Suggested by Ville Skytta.
+  (while (string-match "@" string)
+    (setq string (replace-match "%40" nil t string)))
+  string)
+
+(defun htmlize-make-tmp-overlay (beg end props)
+  (let ((overlay (make-overlay beg end)))
+    (overlay-put overlay 'htmlize-tmp-overlay t)
+    (while props
+      (overlay-put overlay (pop props) (pop props)))
+    overlay))
+
+(defun htmlize-delete-tmp-overlays ()
+  (dolist (overlay (overlays-in (point-min) (point-max)))
+    (when (overlay-get overlay 'htmlize-tmp-overlay)
+      (delete-overlay overlay))))
+
+(defun htmlize-make-link-overlay (beg end uri)
+  (htmlize-make-tmp-overlay beg end `(htmlize-link (:uri ,uri))))
+
+(defun htmlize-create-auto-links ()
+  "Add `htmlize-link' property to all mailto links in the buffer."
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward
+            "<\\(\\(mailto:\\)?\\([-=+_.a-zA-Z0-9]+@[-_.a-zA-Z0-9]+\\)\\)>"
+            nil t)
+      (let* ((address (match-string 3))
+             (beg (match-beginning 0)) (end (match-end 0))
+             (uri (concat "mailto:" (htmlize-despam-address address))))
+        (htmlize-make-link-overlay beg end uri)))
+    (goto-char (point-min))
+    (while (re-search-forward "<\\(\\(URL:\\)?\\([a-zA-Z]+://[^;]+\\)\\)>"
+                              nil t)
+      (htmlize-make-link-overlay
+       (match-beginning 0) (match-end 0) (match-string 3)))))
+
+;; Tests for htmlize-create-auto-links:
+
+;; 
+;; 
+;; 
+;; 
+;; 
+;; 
+
+(defun htmlize-shadow-form-feeds ()
+  (let ((s "\n
")) + (put-text-property 0 (length s) 'htmlize-literal t s) + (let ((disp `(display ,s))) + (while (re-search-forward "\n\^L" nil t) + (let* ((beg (match-beginning 0)) + (end (match-end 0)) + (form-feed-pos (1+ beg)) + ;; don't process ^L if invisible or covered by `display' + (show (and (htmlize-decode-invisibility-spec + (get-char-property form-feed-pos 'invisible)) + (not (get-char-property form-feed-pos 'display))))) + (when show + (htmlize-make-tmp-overlay beg end disp))))))) + +(defun htmlize-defang-local-variables () + ;; Juri Linkov reports that an HTML-ized "Local variables" can lead + ;; visiting the HTML to fail with "Local variables list is not + ;; properly terminated". He suggested changing the phrase to + ;; syntactically equivalent HTML that Emacs doesn't recognize. + (goto-char (point-min)) + (while (search-forward "Local Variables:" nil t) + (replace-match "Local Variables:" nil t))) + + +;;; Color handling. + +(defvar htmlize-x-library-search-path + `(,data-directory + "/etc/X11/rgb.txt" + "/usr/share/X11/rgb.txt" + ;; the remainder of this list really belongs in a museum + "/usr/X11R6/lib/X11/" + "/usr/X11R5/lib/X11/" + "/usr/lib/X11R6/X11/" + "/usr/lib/X11R5/X11/" + "/usr/local/X11R6/lib/X11/" + "/usr/local/X11R5/lib/X11/" + "/usr/local/lib/X11R6/X11/" + "/usr/local/lib/X11R5/X11/" + "/usr/X11/lib/X11/" + "/usr/lib/X11/" + "/usr/local/lib/X11/" + "/usr/X386/lib/X11/" + "/usr/x386/lib/X11/" + "/usr/XFree86/lib/X11/" + "/usr/unsupported/lib/X11/" + "/usr/athena/lib/X11/" + "/usr/local/x11r5/lib/X11/" + "/usr/lpp/Xamples/lib/X11/" + "/usr/openwin/lib/X11/" + "/usr/openwin/share/lib/X11/")) + +(defun htmlize-get-color-rgb-hash (&optional rgb-file) + "Return a hash table mapping X color names to RGB values. +The keys in the hash table are X11 color names, and the values are the +#rrggbb RGB specifications, extracted from `rgb.txt'. + +If RGB-FILE is nil, the function will try hard to find a suitable file +in the system directories. + +If no rgb.txt file is found, return nil." + (let ((rgb-file (or rgb-file (locate-file + "rgb.txt" + htmlize-x-library-search-path))) + (hash nil)) + (when rgb-file + (with-temp-buffer + (insert-file-contents rgb-file) + (setq hash (make-hash-table :test 'equal)) + (while (not (eobp)) + (cond ((looking-at "^\\s-*\\([!#]\\|$\\)") + ;; Skip comments and empty lines. + ) + ((looking-at + "[ \t]*\\([0-9]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\(.*\\)") + (setf (gethash (downcase (match-string 4)) hash) + (format "#%02x%02x%02x" + (string-to-number (match-string 1)) + (string-to-number (match-string 2)) + (string-to-number (match-string 3))))) + (t + (error + "Unrecognized line in %s: %s" + rgb-file + (buffer-substring (point) (progn (end-of-line) (point)))))) + (forward-line 1)))) + hash)) + +;; Compile the RGB map when loaded. On systems where rgb.txt is +;; missing, the value of the variable will be nil, and rgb.txt will +;; not be used. +(defvar htmlize-color-rgb-hash (htmlize-get-color-rgb-hash)) + +;;; Face handling. + +(defun htmlize-face-color-internal (face fg) + ;; Used only under GNU Emacs. Return the color of FACE, but don't + ;; return "unspecified-fg" or "unspecified-bg". If the face is + ;; `default' and the color is unspecified, look up the color in + ;; frame parameters. + (let* ((function (if fg #'face-foreground #'face-background)) + (color (funcall function face nil t))) + (when (and (eq face 'default) (null color)) + (setq color (cdr (assq (if fg 'foreground-color 'background-color) + (frame-parameters))))) + (when (or (eq color 'unspecified) + (equal color "unspecified-fg") + (equal color "unspecified-bg")) + (setq color nil)) + (when (and (eq face 'default) + (null color)) + ;; Assuming black on white doesn't seem right, but I can't think + ;; of anything better to do. + (setq color (if fg "black" "white"))) + color)) + +(defun htmlize-face-foreground (face) + ;; Return the name of the foreground color of FACE. If FACE does + ;; not specify a foreground color, return nil. + (htmlize-face-color-internal face t)) + +(defun htmlize-face-background (face) + ;; Return the name of the background color of FACE. If FACE does + ;; not specify a background color, return nil. + ;; GNU Emacs. + (htmlize-face-color-internal face nil)) + +;; Convert COLOR to the #RRGGBB string. If COLOR is already in that +;; format, it's left unchanged. + +(defun htmlize-color-to-rgb (color) + (let ((rgb-string nil)) + (cond ((null color) + ;; Ignore nil COLOR because it means that the face is not + ;; specifying any color. Hence (htmlize-color-to-rgb nil) + ;; returns nil. + ) + ((string-match "\\`#" color) + ;; The color is already in #rrggbb format. + (setq rgb-string color)) + ((and htmlize-use-rgb-txt + htmlize-color-rgb-hash) + ;; Use of rgb.txt is requested, and it's available on the + ;; system. Use it. + (setq rgb-string (gethash (downcase color) htmlize-color-rgb-hash))) + (t + ;; We're getting the RGB components from Emacs. + (let ((rgb (mapcar (lambda (arg) + (/ arg 256)) + (color-values color)))) + (when rgb + (setq rgb-string (apply #'format "#%02x%02x%02x" rgb)))))) + ;; If RGB-STRING is still nil, it means the color cannot be found, + ;; for whatever reason. In that case just punt and return COLOR. + ;; Most browsers support a decent set of color names anyway. + (or rgb-string color))) + +;; We store the face properties we care about into an +;; `htmlize-fstruct' type. That way we only have to analyze face +;; properties, which can be time consuming, once per each face. The +;; mapping between Emacs faces and htmlize-fstructs is established by +;; htmlize-make-face-map. The name "fstruct" refers to variables of +;; type `htmlize-fstruct', while the term "face" is reserved for Emacs +;; faces. + +(cl-defstruct htmlize-fstruct + foreground ; foreground color, #rrggbb + background ; background color, #rrggbb + size ; size + boldp ; whether face is bold + italicp ; whether face is italic + underlinep ; whether face is underlined + overlinep ; whether face is overlined + strikep ; whether face is struck through + css-name ; CSS name of face + ) + +(defun htmlize-face-set-from-keyword-attr (fstruct attr value) + ;; For ATTR and VALUE, set the equivalent value in FSTRUCT. + (cl-case attr + (:foreground + (setf (htmlize-fstruct-foreground fstruct) (htmlize-color-to-rgb value))) + (:background + (setf (htmlize-fstruct-background fstruct) (htmlize-color-to-rgb value))) + (:height + (setf (htmlize-fstruct-size fstruct) value)) + (:weight + (when (string-match (symbol-name value) "bold") + (setf (htmlize-fstruct-boldp fstruct) t))) + (:slant + (setf (htmlize-fstruct-italicp fstruct) (or (eq value 'italic) + (eq value 'oblique)))) + (:bold + (setf (htmlize-fstruct-boldp fstruct) value)) + (:italic + (setf (htmlize-fstruct-italicp fstruct) value)) + (:underline + (setf (htmlize-fstruct-underlinep fstruct) value)) + (:overline + (setf (htmlize-fstruct-overlinep fstruct) value)) + (:strike-through + (setf (htmlize-fstruct-strikep fstruct) value)))) + +(defun htmlize-face-size (face) + ;; The size (height) of FACE, taking inheritance into account. + ;; Only works in Emacs 21 and later. + (let* ((face-list (list face)) + (head face-list) + (tail face-list)) + (while head + (let ((inherit (face-attribute (car head) :inherit))) + (cond ((listp inherit) + (setcdr tail (cl-copy-list inherit)) + (setq tail (last tail))) + ((eq inherit 'unspecified)) + (t + (setcdr tail (list inherit)) + (setq tail (cdr tail))))) + (pop head)) + (let ((size-list + (cl-loop + for f in face-list + for h = (and (facep f) (face-attribute f :height)) + collect (if (eq h 'unspecified) nil h)))) + (cl-reduce 'htmlize-merge-size (cons nil size-list))))) + +(defun htmlize-face-css-name (face) + ;; Generate the css-name property for the given face. Emacs places + ;; no restrictions on the names of symbols that represent faces -- + ;; any characters may be in the name, even control chars. We try + ;; hard to beat the face name into shape, both esthetically and + ;; according to CSS1 specs. + (let ((name (downcase (symbol-name face)))) + (when (string-match "\\`font-lock-" name) + ;; font-lock-FOO-face -> FOO. + (setq name (replace-match "" t t name))) + (when (string-match "-face\\'" name) + ;; Drop the redundant "-face" suffix. + (setq name (replace-match "" t t name))) + (while (string-match "[^-a-zA-Z0-9]" name) + ;; Drop the non-alphanumerics. + (setq name (replace-match "X" t t name))) + (when (string-match "\\`[-0-9]" name) + ;; CSS identifiers may not start with a digit. + (setq name (concat "X" name))) + ;; After these transformations, the face could come out empty. + (when (equal name "") + (setq name "face")) + ;; Apply the prefix. + (concat htmlize-css-name-prefix name))) + +(defun htmlize-face-to-fstruct-1 (face) + "Convert Emacs face FACE to fstruct, internal." + (let ((fstruct (make-htmlize-fstruct + :foreground (htmlize-color-to-rgb + (htmlize-face-foreground face)) + :background (htmlize-color-to-rgb + (htmlize-face-background face))))) + ;; GNU Emacs + (dolist (attr '(:weight :slant :underline :overline :strike-through)) + (let ((value (face-attribute face attr nil t))) + (when (and value (not (eq value 'unspecified))) + (htmlize-face-set-from-keyword-attr fstruct attr value)))) + (let ((size (htmlize-face-size face))) + (unless (eql size 1.0) ; ignore non-spec + (setf (htmlize-fstruct-size fstruct) size))) + (setf (htmlize-fstruct-css-name fstruct) (htmlize-face-css-name face)) + fstruct)) + +(defun htmlize-face-to-fstruct (face) + (let* ((face-list (or (and (symbolp face) + (cdr (assq face face-remapping-alist))) + (list face))) + (fstruct (htmlize-merge-faces + (mapcar (lambda (face) + (if (symbolp face) + (or (htmlize-get-override-fstruct face) + (htmlize-face-to-fstruct-1 face)) + (htmlize-attrlist-to-fstruct face))) + (nreverse face-list))))) + (when (symbolp face) + (setf (htmlize-fstruct-css-name fstruct) (htmlize-face-css-name face))) + fstruct)) + +(defmacro htmlize-copy-attr-if-set (attr-list dest source) + ;; Generate code with the following pattern: + ;; (progn + ;; (when (htmlize-fstruct-ATTR source) + ;; (setf (htmlize-fstruct-ATTR dest) (htmlize-fstruct-ATTR source))) + ;; ...) + ;; for the given list of boolean attributes. + (cons 'progn + (cl-loop for attr in attr-list + for attr-sym = (intern (format "htmlize-fstruct-%s" attr)) + collect `(when (,attr-sym ,source) + (setf (,attr-sym ,dest) (,attr-sym ,source)))))) + +(defun htmlize-merge-size (merged next) + ;; Calculate the size of the merge of MERGED and NEXT. + (cond ((null merged) next) + ((integerp next) next) + ((null next) merged) + ((floatp merged) (* merged next)) + ((integerp merged) (round (* merged next))))) + +(defun htmlize-merge-two-faces (merged next) + (htmlize-copy-attr-if-set + (foreground background boldp italicp underlinep overlinep strikep) + merged next) + (setf (htmlize-fstruct-size merged) + (htmlize-merge-size (htmlize-fstruct-size merged) + (htmlize-fstruct-size next))) + merged) + +(defun htmlize-merge-faces (fstruct-list) + (cond ((null fstruct-list) + ;; Nothing to do, return a dummy face. + (make-htmlize-fstruct)) + ((null (cdr fstruct-list)) + ;; Optimize for the common case of a single face, simply + ;; return it. + (car fstruct-list)) + (t + (cl-reduce #'htmlize-merge-two-faces + (cons (make-htmlize-fstruct) fstruct-list))))) + +;; GNU Emacs 20+ supports attribute lists in `face' properties. For +;; example, you can use `(:foreground "red" :weight bold)' as an +;; overlay's "face", or you can even use a list of such lists, etc. +;; We call those "attrlists". +;; +;; htmlize supports attrlist by converting them to fstructs, the same +;; as with regular faces. + +(defun htmlize-attrlist-to-fstruct (attrlist &optional name) + ;; Like htmlize-face-to-fstruct, but accepts an ATTRLIST as input. + (let ((fstruct (make-htmlize-fstruct))) + (cond ((eq (car attrlist) 'foreground-color) + ;; ATTRLIST is (foreground-color . COLOR) + (setf (htmlize-fstruct-foreground fstruct) + (htmlize-color-to-rgb (cdr attrlist)))) + ((eq (car attrlist) 'background-color) + ;; ATTRLIST is (background-color . COLOR) + (setf (htmlize-fstruct-background fstruct) + (htmlize-color-to-rgb (cdr attrlist)))) + (t + ;; ATTRLIST is a plist. + (while attrlist + (let ((attr (pop attrlist)) + (value (pop attrlist))) + (when (and value (not (eq value 'unspecified))) + (htmlize-face-set-from-keyword-attr fstruct attr value)))))) + (setf (htmlize-fstruct-css-name fstruct) (or name "custom")) + fstruct)) + +(defun htmlize-decode-face-prop (prop) + "Turn face property PROP into a list of face-like objects." + ;; PROP can be a symbol naming a face, a string naming such a + ;; symbol, a cons (foreground-color . COLOR) or (background-color + ;; COLOR), a property list (:attr1 val1 :attr2 val2 ...), or a list + ;; of any of those. + ;; + ;; (htmlize-decode-face-prop 'face) -> (face) + ;; (htmlize-decode-face-prop '(face1 face2)) -> (face1 face2) + ;; (htmlize-decode-face-prop '(:attr "val")) -> ((:attr "val")) + ;; (htmlize-decode-face-prop '((:attr "val") face (foreground-color "red"))) + ;; -> ((:attr "val") face (foreground-color "red")) + ;; + ;; Unrecognized atoms or non-face symbols/strings are silently + ;; stripped away. + (cond ((null prop) + nil) + ((symbolp prop) + (and (facep prop) + (list prop))) + ((stringp prop) + (and (facep (intern-soft prop)) + (list prop))) + ((atom prop) + nil) + ((and (symbolp (car prop)) + (eq ?: (aref (symbol-name (car prop)) 0))) + (list prop)) + ((or (eq (car prop) 'foreground-color) + (eq (car prop) 'background-color)) + (list prop)) + (t + (apply #'nconc (mapcar #'htmlize-decode-face-prop prop))))) + +(defun htmlize-get-override-fstruct (face) + (let* ((raw-def (plist-get htmlize-face-overrides face)) + (def (cond ((stringp raw-def) (list :foreground raw-def)) + ((listp raw-def) raw-def) + (t + (error (format (concat "face override must be an " + "attribute list or string, got %s") + raw-def)))))) + (and def + (htmlize-attrlist-to-fstruct def (symbol-name face))))) + +(defun htmlize-make-face-map (faces) + ;; Return a hash table mapping Emacs faces to htmlize's fstructs. + ;; The keys are either face symbols or attrlists, so the test + ;; function must be `equal'. + (let ((face-map (make-hash-table :test 'equal)) + css-names) + (dolist (face faces) + (unless (gethash face face-map) + ;; Haven't seen FACE yet; convert it to an fstruct and cache + ;; it. + (let ((fstruct (htmlize-face-to-fstruct face))) + (setf (gethash face face-map) fstruct) + (let* ((css-name (htmlize-fstruct-css-name fstruct)) + (new-name css-name) + (i 0)) + ;; Uniquify the face's css-name by using NAME-1, NAME-2, + ;; etc. + (while (member new-name css-names) + (setq new-name (format "%s-%s" css-name (cl-incf i)))) + (unless (equal new-name css-name) + (setf (htmlize-fstruct-css-name fstruct) new-name)) + (push new-name css-names))))) + face-map)) + +(defun htmlize-unstringify-face (face) + "If FACE is a string, return it interned, otherwise return it unchanged." + (if (stringp face) + (intern face) + face)) + +(defun htmlize-faces-in-buffer () + "Return a list of faces used in the current buffer. +This is the set of faces specified by the `face' text property and by buffer +overlays that specify `face'." + (let (faces) + ;; Faces used by text properties. + (let ((pos (point-min)) face-prop next) + (while (< pos (point-max)) + (setq face-prop (get-text-property pos 'face) + next (or (next-single-property-change pos 'face) (point-max))) + (setq faces (cl-nunion (htmlize-decode-face-prop face-prop) + faces :test 'equal)) + (setq pos next))) + ;; Faces used by overlays. + (dolist (overlay (overlays-in (point-min) (point-max))) + (let ((face-prop (overlay-get overlay 'face))) + (setq faces (cl-nunion (htmlize-decode-face-prop face-prop) + faces :test 'equal)))) + faces)) + +;; htmlize-faces-at-point returns the faces in use at point. The +;; faces are sorted by increasing priority, i.e. the last face takes +;; precedence. +;; +;; This returns all the faces in the `face' property and all the faces +;; in the overlays at point. + +(defun htmlize-faces-at-point () + (let (all-faces) + ;; Faces from text properties. + (let ((face-prop (get-text-property (point) 'face))) + ;; we need to reverse the `face' prop because we want + ;; more specific faces to come later + (setq all-faces (nreverse (htmlize-decode-face-prop face-prop)))) + ;; Faces from overlays. + (let ((overlays + ;; Collect overlays at point that specify `face'. + (cl-delete-if-not (lambda (o) + (overlay-get o 'face)) + (nreverse (overlays-at (point) t)))) + list face-prop) + (dolist (overlay overlays) + (setq face-prop (overlay-get overlay 'face) + list (nconc (htmlize-decode-face-prop face-prop) list))) + ;; Under "Merging Faces" the manual explicitly states + ;; that faces specified by overlays take precedence over + ;; faces specified by text properties. + (setq all-faces (nconc all-faces list))) + all-faces)) + +;; htmlize supports generating HTML in several flavors, some of which +;; use CSS, and others the element. We take an OO approach and +;; define "methods" that indirect to the functions that depend on +;; `htmlize-output-type'. The currently used methods are `doctype', +;; `insert-head', `body-tag', `pre-tag', and `text-markup'. Not all +;; output types define all methods. +;; +;; Methods are called either with (htmlize-method METHOD ARGS...) +;; special form, or by accessing the function with +;; (htmlize-method-function 'METHOD) and calling (funcall FUNCTION). +;; The latter form is useful in tight loops because `htmlize-method' +;; conses. + +(defmacro htmlize-method (method &rest args) + ;; Expand to (htmlize-TYPE-METHOD ...ARGS...). TYPE is the value of + ;; `htmlize-output-type' at run time. + `(funcall (htmlize-method-function ',method) ,@args)) + +(defun htmlize-method-function (method) + ;; Return METHOD's function definition for the current output type. + ;; The returned object can be safely funcalled. + (let ((sym (intern (format "htmlize-%s-%s" htmlize-output-type method)))) + (indirect-function (if (fboundp sym) + sym + (let ((default (intern (concat "htmlize-default-" + (symbol-name method))))) + (if (fboundp default) + default + 'ignore)))))) + +(defvar htmlize-memoization-table (make-hash-table :test 'equal)) + +(defmacro htmlize-memoize (key generator) + "Return the value of GENERATOR, memoized as KEY. +That means that GENERATOR will be evaluated and returned the first time +it's called with the same value of KEY. All other times, the cached +\(memoized) value will be returned." + (let ((value (cl-gensym))) + `(let ((,value (gethash ,key htmlize-memoization-table))) + (unless ,value + (setq ,value ,generator) + (setf (gethash ,key htmlize-memoization-table) ,value)) + ,value))) + +;;; Default methods. + +(defun htmlize-default-doctype () + nil ; no doc-string + ;; Note that the `font' output is technically invalid under this DTD + ;; because the DTD doesn't allow embedding in
.
+  ""
+  )
+
+(defun htmlize-default-body-tag (face-map)
+  nil					; no doc-string
+  face-map ; shut up the byte-compiler
+  "")
+
+(defun htmlize-default-pre-tag (face-map)
+  nil					; no doc-string
+  face-map ; shut up the byte-compiler
+  "
")
+
+
+;;; CSS based output support.
+
+;; Internal function; not a method.
+(defun htmlize-css-specs (fstruct)
+  (let (result)
+    (when (htmlize-fstruct-foreground fstruct)
+      (push (format "color: %s;" (htmlize-fstruct-foreground fstruct))
+	    result))
+    (when (htmlize-fstruct-background fstruct)
+      (push (format "background-color: %s;"
+		    (htmlize-fstruct-background fstruct))
+	    result))
+    (let ((size (htmlize-fstruct-size fstruct)))
+      (when (and size (not (eq htmlize-ignore-face-size t)))
+	(cond ((floatp size)
+	       (push (format "font-size: %d%%;" (* 100 size)) result))
+	      ((not (eq htmlize-ignore-face-size 'absolute))
+	       (push (format "font-size: %spt;" (/ size 10.0)) result)))))
+    (when (htmlize-fstruct-boldp fstruct)
+      (push "font-weight: bold;" result))
+    (when (htmlize-fstruct-italicp fstruct)
+      (push "font-style: italic;" result))
+    (when (htmlize-fstruct-underlinep fstruct)
+      (push "text-decoration: underline;" result))
+    (when (htmlize-fstruct-overlinep fstruct)
+      (push "text-decoration: overline;" result))
+    (when (htmlize-fstruct-strikep fstruct)
+      (push "text-decoration: line-through;" result))
+    (nreverse result)))
+
+(defun htmlize-css-insert-head (buffer-faces face-map)
+  (insert "    \n"))
+
+(defun htmlize-css-text-markup (fstruct-list buffer)
+  ;; Open the markup needed to insert text colored with FACES into
+  ;; BUFFER.  Return the function that closes the markup.
+
+  ;; In CSS mode, this is easy: just nest the text in one  tag for each face in FSTRUCT-LIST.
+  (dolist (fstruct fstruct-list)
+    (princ "" buffer))
+  (htmlize-lexlet ((fstruct-list fstruct-list) (buffer buffer))
+    (lambda ()
+      (dolist (fstruct fstruct-list)
+        (ignore fstruct)                ; shut up the byte-compiler
+        (princ "" buffer)))))
+
+;; `inline-css' output support.
+
+(defun htmlize-inline-css-body-tag (face-map)
+  (format ""
+	  (mapconcat #'identity (htmlize-css-specs (gethash 'default face-map))
+		     " ")))
+
+(defun htmlize-inline-css-pre-tag (face-map)
+  (if htmlize-pre-style
+      (format "
"
+              (mapconcat #'identity (htmlize-css-specs (gethash 'default face-map))
+                         " "))
+    (format "
")))
+
+(defun htmlize-inline-css-text-markup (fstruct-list buffer)
+  (let* ((merged (htmlize-merge-faces fstruct-list))
+	 (style (htmlize-memoize
+		 merged
+		 (let ((specs (htmlize-css-specs merged)))
+		   (and specs
+			(mapconcat #'identity (htmlize-css-specs merged) " "))))))
+    (when style
+      (princ "" buffer))
+    (htmlize-lexlet ((style style) (buffer buffer))
+      (lambda ()
+        (when style
+          (princ "" buffer))))))
+
+;;; `font' tag based output support.
+
+(defun htmlize-font-body-tag (face-map)
+  (let ((fstruct (gethash 'default face-map)))
+    (format ""
+	    (htmlize-fstruct-foreground fstruct)
+	    (htmlize-fstruct-background fstruct))))
+
+(defun htmlize-font-pre-tag (face-map)
+  (if htmlize-pre-style
+      (let ((fstruct (gethash 'default face-map)))
+        (format "
"
+                (htmlize-fstruct-foreground fstruct)
+                (htmlize-fstruct-background fstruct)))
+    (format "
")))
+       
+(defun htmlize-font-text-markup (fstruct-list buffer)
+  ;; In `font' mode, we use the traditional HTML means of altering
+  ;; presentation:  tag for colors,  for bold,  for
+  ;; underline, and  for strike-through.
+  (let* ((merged (htmlize-merge-faces fstruct-list))
+	 (markup (htmlize-memoize
+		  merged
+		  (cons (concat
+			 (and (htmlize-fstruct-foreground merged)
+			      (format "" (htmlize-fstruct-foreground merged)))
+			 (and (htmlize-fstruct-boldp merged)      "")
+			 (and (htmlize-fstruct-italicp merged)    "")
+			 (and (htmlize-fstruct-underlinep merged) "")
+			 (and (htmlize-fstruct-strikep merged)    ""))
+			(concat
+			 (and (htmlize-fstruct-strikep merged)    "")
+			 (and (htmlize-fstruct-underlinep merged) "")
+			 (and (htmlize-fstruct-italicp merged)    "")
+			 (and (htmlize-fstruct-boldp merged)      "")
+			 (and (htmlize-fstruct-foreground merged) ""))))))
+    (princ (car markup) buffer)
+    (htmlize-lexlet ((markup markup) (buffer buffer))
+      (lambda ()
+        (princ (cdr markup) buffer)))))
+
+(defun htmlize-buffer-1 ()
+  ;; Internal function; don't call it from outside this file.  Htmlize
+  ;; current buffer, writing the resulting HTML to a new buffer, and
+  ;; return it.  Unlike htmlize-buffer, this doesn't change current
+  ;; buffer or use switch-to-buffer.
+  (save-excursion
+    ;; Protect against the hook changing the current buffer.
+    (save-excursion
+      (run-hooks 'htmlize-before-hook))
+    ;; Convince font-lock support modes to fontify the entire buffer
+    ;; in advance.
+    (htmlize-ensure-fontified)
+    (clrhash htmlize-extended-character-cache)
+    (clrhash htmlize-memoization-table)
+    ;; It's important that the new buffer inherits default-directory
+    ;; from the current buffer.
+    (let ((htmlbuf (generate-new-buffer (if (buffer-file-name)
+                                            (htmlize-make-file-name
+                                             (file-name-nondirectory
+                                              (buffer-file-name)))
+                                          "*html*")))
+          (completed nil))
+      (unwind-protect
+          (let* ((buffer-faces (htmlize-faces-in-buffer))
+                 (face-map (htmlize-make-face-map (cl-adjoin 'default buffer-faces)))
+                 (places (cl-gensym))
+                 (title (if (buffer-file-name)
+                            (file-name-nondirectory (buffer-file-name))
+                          (buffer-name))))
+            (when htmlize-generate-hyperlinks
+              (htmlize-create-auto-links))
+            (when htmlize-replace-form-feeds
+              (htmlize-shadow-form-feeds))
+
+            ;; Initialize HTMLBUF and insert the HTML prolog.
+            (with-current-buffer htmlbuf
+              (buffer-disable-undo)
+              (insert (htmlize-method doctype) ?\n
+                      (format "\n"
+                              htmlize-version htmlize-output-type)
+                      "\n  ")
+              (put places 'head-start (point-marker))
+              (insert "\n"
+                      "    " (htmlize-protect-string title) "\n"
+                      (if htmlize-html-charset
+                          (format (concat "    \n")
+                                  htmlize-html-charset)
+                        "")
+                      htmlize-head-tags)
+              (htmlize-method insert-head buffer-faces face-map)
+              (insert "  ")
+              (put places 'head-end (point-marker))
+              (insert "\n  ")
+              (put places 'body-start (point-marker))
+              (insert (htmlize-method body-tag face-map)
+                      "\n    ")
+              (put places 'content-start (point-marker))
+              (insert (htmlize-method pre-tag face-map) "\n"))
+            (let ((text-markup
+                   ;; Get the inserter method, so we can funcall it inside
+                   ;; the loop.  Not calling `htmlize-method' in the loop
+                   ;; body yields a measurable speed increase.
+                   (htmlize-method-function 'text-markup))
+                  ;; Declare variables used in loop body outside the loop
+                  ;; because it's faster to establish `let' bindings only
+                  ;; once.
+                  next-change text face-list trailing-ellipsis
+                  fstruct-list last-fstruct-list
+                  (close-markup (lambda ())))
+              ;; This loop traverses and reads the source buffer, appending
+              ;; the resulting HTML to HTMLBUF.  This method is fast
+              ;; because: 1) it doesn't require examining the text
+              ;; properties char by char (htmlize-next-face-change is used
+              ;; to move between runs with the same face), and 2) it doesn't
+              ;; require frequent buffer switches, which are slow because
+              ;; they rebind all buffer-local vars.
+              (goto-char (point-min))
+              (while (not (eobp))
+                (setq next-change (htmlize-next-face-change (point)))
+                ;; Get faces in use between (point) and NEXT-CHANGE, and
+                ;; convert them to fstructs.
+                (setq face-list (htmlize-faces-at-point)
+                      fstruct-list (delq nil (mapcar (lambda (f)
+                                                       (gethash f face-map))
+                                                     face-list)))
+                (cl-multiple-value-setq (text trailing-ellipsis)
+                  (htmlize-extract-text (point) next-change trailing-ellipsis))
+                ;; Don't bother writing anything if there's no text (this
+                ;; happens in invisible regions).
+                (when (> (length text) 0)
+                  ;; Open the new markup if necessary and insert the text.
+                  (when (not (cl-equalp fstruct-list last-fstruct-list))
+                    (funcall close-markup)
+                    (setq last-fstruct-list fstruct-list
+                          close-markup (funcall text-markup fstruct-list htmlbuf)))
+                  (princ text htmlbuf))
+                (goto-char next-change))
+
+              ;; We've gone through the buffer; close the markup from
+              ;; the last run, if any.
+              (funcall close-markup))
+
+            ;; Insert the epilog and post-process the buffer.
+            (with-current-buffer htmlbuf
+              (insert "
") + (put places 'content-end (point-marker)) + (insert "\n ") + (put places 'body-end (point-marker)) + (insert "\n\n") + (htmlize-defang-local-variables) + (goto-char (point-min)) + (when htmlize-html-major-mode + ;; What sucks about this is that the minor modes, most notably + ;; font-lock-mode, won't be initialized. Oh well. + (funcall htmlize-html-major-mode)) + (set (make-local-variable 'htmlize-buffer-places) + (symbol-plist places)) + (run-hooks 'htmlize-after-hook) + (buffer-enable-undo)) + (setq completed t) + htmlbuf) + + (when (not completed) + (kill-buffer htmlbuf)) + (htmlize-delete-tmp-overlays))))) + +;; Utility functions. + +(defmacro htmlize-with-fontify-message (&rest body) + ;; When forcing fontification of large buffers in + ;; htmlize-ensure-fontified, inform the user that he is waiting for + ;; font-lock, not for htmlize to finish. + `(progn + (if (> (buffer-size) 65536) + (message "Forcing fontification of %s..." + (buffer-name (current-buffer)))) + ,@body + (if (> (buffer-size) 65536) + (message "Forcing fontification of %s...done" + (buffer-name (current-buffer)))))) + +(defun htmlize-ensure-fontified () + ;; If font-lock is being used, ensure that the "support" modes + ;; actually fontify the buffer. If font-lock is not in use, we + ;; don't care because, except in htmlize-file, we don't force + ;; font-lock on the user. + (when font-lock-mode + ;; In part taken from ps-print-ensure-fontified in GNU Emacs 21. + (when (and (boundp 'jit-lock-mode) + (symbol-value 'jit-lock-mode)) + (htmlize-with-fontify-message + (jit-lock-fontify-now (point-min) (point-max)))) + + (if (fboundp 'font-lock-ensure) + (font-lock-ensure) + ;; Emacs prior to 25.1 + (with-no-warnings + (font-lock-mode 1) + (font-lock-fontify-buffer))))) + + +;;;###autoload +(defun htmlize-buffer (&optional buffer) + "Convert BUFFER to HTML, preserving colors and decorations. + +The generated HTML is available in a new buffer, which is returned. +When invoked interactively, the new buffer is selected in the current +window. The title of the generated document will be set to the buffer's +file name or, if that's not available, to the buffer's name. + +Note that htmlize doesn't fontify your buffers, it only uses the +decorations that are already present. If you don't set up font-lock or +something else to fontify your buffers, the resulting HTML will be +plain. Likewise, if you don't like the choice of colors, fix the mode +that created them, or simply alter the faces it uses." + (interactive) + (let ((htmlbuf (with-current-buffer (or buffer (current-buffer)) + (htmlize-buffer-1)))) + (when (interactive-p) + (switch-to-buffer htmlbuf)) + htmlbuf)) + +;;;###autoload +(defun htmlize-region (beg end) + "Convert the region to HTML, preserving colors and decorations. +See `htmlize-buffer' for details." + (interactive "r") + ;; Don't let zmacs region highlighting end up in HTML. + (when (fboundp 'zmacs-deactivate-region) + (zmacs-deactivate-region)) + (let ((htmlbuf (save-restriction + (narrow-to-region beg end) + (htmlize-buffer-1)))) + (when (interactive-p) + (switch-to-buffer htmlbuf)) + htmlbuf)) + +(defun htmlize-region-for-paste (beg end) + "Htmlize the region and return just the HTML as a string. +This forces the `inline-css' style and only returns the HTML body, +but without the BODY tag. This should make it useful for inserting +the text to another HTML buffer." + (let* ((htmlize-output-type 'inline-css) + (htmlbuf (htmlize-region beg end))) + (unwind-protect + (with-current-buffer htmlbuf + (buffer-substring (plist-get htmlize-buffer-places 'content-start) + (plist-get htmlize-buffer-places 'content-end))) + (kill-buffer htmlbuf)))) + +(defun htmlize-region-save-screenshot (beg end) + "Save the htmlized (see `htmlize-region-for-paste') region in +the kill ring. Uses `inline-css', with style information in +`
' tags, so that the rendering of the marked up text
+approximates the buffer as closely as possible."
+  (interactive "r")
+  (let ((htmlize-pre-style t))
+    (kill-new (htmlize-region-for-paste beg end)))
+  (deactivate-mark))
+
+(defun htmlize-make-file-name (file)
+  "Make an HTML file name from FILE.
+
+In its default implementation, this simply appends `.html' to FILE.
+This function is called by htmlize to create the buffer file name, and
+by `htmlize-file' to create the target file name.
+
+More elaborate transformations are conceivable, such as changing FILE's
+extension to `.html' (\"file.c\" -> \"file.html\").  If you want them,
+overload this function to do it and htmlize will comply."
+  (concat file ".html"))
+
+;; Older implementation of htmlize-make-file-name that changes FILE's
+;; extension to ".html".
+;(defun htmlize-make-file-name (file)
+;  (let ((extension (file-name-extension file))
+;	(sans-extension (file-name-sans-extension file)))
+;    (if (or (equal extension "html")
+;	    (equal extension "htm")
+;	    (equal sans-extension ""))
+;	(concat file ".html")
+;      (concat sans-extension ".html"))))
+
+;;;###autoload
+(defun htmlize-file (file &optional target)
+  "Load FILE, fontify it, convert it to HTML, and save the result.
+
+Contents of FILE are inserted into a temporary buffer, whose major mode
+is set with `normal-mode' as appropriate for the file type.  The buffer
+is subsequently fontified with `font-lock' and converted to HTML.  Note
+that, unlike `htmlize-buffer', this function explicitly turns on
+font-lock.  If a form of highlighting other than font-lock is desired,
+please use `htmlize-buffer' directly on buffers so highlighted.
+
+Buffers currently visiting FILE are unaffected by this function.  The
+function does not change current buffer or move the point.
+
+If TARGET is specified and names a directory, the resulting file will be
+saved there instead of to FILE's directory.  If TARGET is specified and
+does not name a directory, it will be used as output file name."
+  (interactive (list (read-file-name
+		      "HTML-ize file: "
+		      nil nil nil (and (buffer-file-name)
+				       (file-name-nondirectory
+					(buffer-file-name))))))
+  (let ((output-file (if (and target (not (file-directory-p target)))
+			 target
+		       (expand-file-name
+			(htmlize-make-file-name (file-name-nondirectory file))
+			(or target (file-name-directory file)))))
+	;; Try to prevent `find-file-noselect' from triggering
+	;; font-lock because we'll fontify explicitly below.
+	(font-lock-mode nil)
+	(font-lock-auto-fontify nil)
+	(global-font-lock-mode nil)
+	;; Ignore the size limit for the purposes of htmlization.
+	(font-lock-maximum-size nil))
+    (with-temp-buffer
+      ;; Insert FILE into the temporary buffer.
+      (insert-file-contents file)
+      ;; Set the file name so normal-mode and htmlize-buffer-1 pick it
+      ;; up.  Restore it afterwards so with-temp-buffer's kill-buffer
+      ;; doesn't complain about killing a modified buffer.
+      (let ((buffer-file-name file))
+	;; Set the major mode for the sake of font-lock.
+	(normal-mode)
+	;; htmlize the buffer and save the HTML.
+	(with-current-buffer (htmlize-buffer-1)
+	  (unwind-protect
+	      (progn
+		(run-hooks 'htmlize-file-hook)
+		(write-region (point-min) (point-max) output-file))
+	    (kill-buffer (current-buffer)))))))
+  ;; I haven't decided on a useful return value yet, so just return
+  ;; nil.
+  nil)
+
+;;;###autoload
+(defun htmlize-many-files (files &optional target-directory)
+  "Convert FILES to HTML and save the corresponding HTML versions.
+
+FILES should be a list of file names to convert.  This function calls
+`htmlize-file' on each file; see that function for details.  When
+invoked interactively, you are prompted for a list of files to convert,
+terminated with RET.
+
+If TARGET-DIRECTORY is specified, the HTML files will be saved to that
+directory.  Normally, each HTML file is saved to the directory of the
+corresponding source file."
+  (interactive
+   (list
+    (let (list file)
+      ;; Use empty string as DEFAULT because setting DEFAULT to nil
+      ;; defaults to the directory name, which is not what we want.
+      (while (not (equal (setq file (read-file-name
+				     "HTML-ize file (RET to finish): "
+				     (and list (file-name-directory
+						(car list)))
+				     "" t))
+			 ""))
+	(push file list))
+      (nreverse list))))
+  ;; Verify that TARGET-DIRECTORY is indeed a directory.  If it's a
+  ;; file, htmlize-file will use it as target, and that doesn't make
+  ;; sense.
+  (and target-directory
+       (not (file-directory-p target-directory))
+       (error "target-directory must name a directory: %s" target-directory))
+  (dolist (file files)
+    (htmlize-file file target-directory)))
+
+;;;###autoload
+(defun htmlize-many-files-dired (arg &optional target-directory)
+  "HTMLize dired-marked files."
+  (interactive "P")
+  (htmlize-many-files (dired-get-marked-files nil arg) target-directory))
+
+(provide 'htmlize)
+
+;; Local Variables:
+;; byte-compile-warnings: (not unresolved obsolete)
+;; End:
+
+;;; htmlize.el ends here
diff --git a/src/org.css b/src/org.css
new file mode 100644
index 0000000..18ebe3f
--- /dev/null
+++ b/src/org.css
@@ -0,0 +1,137 @@
+@import url("https://fonts.googleapis.com/css2?family=Lora:wght@500&display=swap");
+@import url("https://fonts.googleapis.com/css2?family=Inconsolata&display=swap");
+
+body {
+        margin: 40px auto;
+        width: 700px;
+        max-width: 100%;
+        line-height: 1.6;
+        font-size: 16px;
+        background: #fffff4;
+        color: #3a1616;
+        padding: 0 10px;
+        font-size: 18px;
+        line-height: 28px;
+        font-family: "Lora";
+        font-weight: 500;
+        /* Smooth the font a little bit, it's a
+         bit too bold on retina screens */
+        -webkit-font-smoothing: antialiased;
+}
+
+/* --------------------------------------------------- */
+/* Make a nice input form with rounded corners and hover
+ animations*/
+/* --------------------------------------------------- */
+input {
+        padding: 10px 16px;
+        margin: 2px 0;
+        box-sizing: border-box;
+        border: 2px solid #dabebe;
+        border-radius: 6px;
+        background: #fffff4;
+        color: #3a1616;
+        font-size: 16px;
+        -webkit-transition: 0.5s;
+        transition: 0.5s;
+        outline: none;
+}
+input:focus {
+        border: 2px solid #3a1616;
+}
+
+/* --------------------------------------- */
+/* The button is very similar to the input */
+/* --------------------------------------- */
+.button {
+        background-color: #fffff4;
+        border: none;
+        color: black;
+        padding: 6px 14px;
+        text-align: center;
+        text-decoration: none;
+        display: inline-block;
+        font-size: 16px;
+        margin: 4px 2px;
+        transition-duration: 0.4s;
+        cursor: pointer;
+        border: 2px solid #3a1616;
+        border-radius: 6px;
+}
+.button:hover {
+        background-color: #3a1616;
+        color: white;
+}
+
+/* ----------------------------------------------- */
+/* Various classes for messages of different kinds */
+/* ----------------------------------------------- */
+.isa_info,
+.isa_success,
+.isa_warning,
+.isa_error {
+        width: 90%;
+        margin: 10px 0px;
+        padding: 12px;
+}
+.isa_info {
+        color: #00529b;
+        background-color: #bde5f8;
+}
+.isa_success {
+        color: #4f8a10;
+        background-color: #dff2bf;
+}
+.isa_warning {
+        color: #9f6000;
+        background-color: #feefb3;
+}
+.isa_error {
+        color: #d8000c;
+        background-color: #ffd2d2;
+}
+
+h1,
+h2,
+h3 {
+        line-height: 1.2;
+        font-family: "Lora";
+}
+
+img {
+        width: 500px;
+        max-width: 100%;
+        border-radius: 10px;
+        text-align: center;
+}
+
+/* --------------------------------------------- */
+/* Bold hover animations on links and clickables */
+/* --------------------------------------------- */
+a {
+        cursor: pointer;
+        color: #217ab7;
+        line-height: inherit;
+        transition: .14s;
+}
+a:hover {
+        color: white;
+        background-color: #3297d3;
+}
+a:visited {
+        color: #43458b;
+        border-color: #43458b;
+}
+a:visited:hover {
+        color: white;
+        background-color: #9251ac;
+}
+
+pre {
+        font-family: "Inconsolata", monospace;
+}
+
+::selection {
+        color: white;
+        background: #ff4081;
+}