You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2066 lines
104 KiB
HTML

1 year ago
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2023-07-30 Sun 18:20 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Data Structures</title>
<meta name="author" content="Anmol Nawani" />
<meta name="generator" content="Org Mode" />
<style>
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<link rel="stylesheet" href="src/org.css">
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
displayAlign: "center",
displayIndent: "0em",
"HTML-CSS": { scale: 100,
linebreaks: { automatic: "false" },
webFont: "TeX"
},
SVG: {scale: 100,
linebreaks: { automatic: "false" },
font: "TeX"},
NativeMML: {scale: 100},
TeX: { equationNumbers: {autoNumber: "AMS"},
MultLineWidth: "85%",
TagSide: "right",
TagIndent: ".8em"
}
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML"></script>
</head>
<body>
<div id="content" class="content">
<h1 class="title">Data Structures</h1>
<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org81ab3fa">1. Stack</a>
<ul>
<li><a href="#org476cd3f">1.1. Operation on stack</a></li>
</ul>
</li>
<li><a href="#org6466b75">2. Direct Address Table</a></li>
<li><a href="#orgb6526cf">3. Hash Table</a>
<ul>
<li><a href="#org64d5283">3.1. Collision</a>
<ul>
<li><a href="#org23a9fe2">3.1.1. Chaining</a></li>
<li><a href="#org732d622">3.1.2. Performance of chaining hash table</a></li>
<li><a href="#orga12689d">3.1.3. Open Addressing</a></li>
</ul>
</li>
<li><a href="#orgb32fcc8">3.2. Hash Functions</a>
<ul>
<li><a href="#org64ed2dc">3.2.1. The division method</a></li>
<li><a href="#org7d82f3d">3.2.2. The multiplication method</a></li>
<li><a href="#orgcf8d990">3.2.3. Mid square method</a></li>
<li><a href="#org719601b">3.2.4. Folding method</a></li>
</ul>
</li>
<li><a href="#org000a70c">3.3. Universal Hashing</a></li>
<li><a href="#org0b7a2f3">3.4. Perfect Hashing</a></li>
</ul>
</li>
<li><a href="#orga2c39cb">4. Representing rooted trees using nodes</a>
<ul>
<li><a href="#orgd36b71b">4.1. Fixed number of children</a></li>
<li><a href="#orgfbf415c">4.2. Unbounded number of children</a></li>
</ul>
</li>
<li><a href="#orgda50fd0">5. Binary Search Trees</a>
<ul>
<li><a href="#orgf95dd3b">5.1. Quering a BST</a>
<ul>
<li><a href="#org97d681f">5.1.1. Searching for node</a></li>
<li><a href="#org286a6d6">5.1.2. Minimum and maximum</a></li>
<li><a href="#org9af08d0">5.1.3. Find Parent Node</a></li>
<li><a href="#orgeacb6ef">5.1.4. Is ancestor</a></li>
<li><a href="#orgce7c596">5.1.5. Successor and predecessor</a></li>
</ul>
</li>
<li><a href="#orgee97ab6">5.2. Inserting and Deleting nodes</a>
<ul>
<li><a href="#org5fbdca0">5.2.1. Insertion</a></li>
<li><a href="#org3d65276">5.2.2. Deletion</a></li>
</ul>
</li>
<li><a href="#org438ffbb">5.3. Performance of BST</a></li>
<li><a href="#orgb60c267">5.4. Traversing a Binary Tree</a>
<ul>
<li><a href="#orgb03b5c9">5.4.1. Inorder tree walk</a></li>
<li><a href="#org32eaac9">5.4.2. Preorder tree walk</a></li>
<li><a href="#orgdb18f9b">5.4.3. Postorder tree walk</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#org2128999">6. Binary Heap</a>
<ul>
<li><a href="#org0ad3ed1">6.1. Heap Property</a></li>
<li><a href="#org2ddce59">6.2. Shape of Heap</a></li>
<li><a href="#orgc2ae7dd">6.3. Array implementation</a></li>
<li><a href="#org7251356">6.4. Operations on heaps</a>
<ul>
<li><a href="#orgb8e21e1">6.4.1. Parent and child indices</a></li>
<li><a href="#orgd61130f">6.4.2. Down-heapify</a></li>
<li><a href="#orgfa9b550">6.4.3. Up-heapify</a></li>
<li><a href="#orga289df9">6.4.4. Insertion</a></li>
<li><a href="#org30cb28f">6.4.5. Deletion or Extraction</a></li>
<li><a href="#orgf14f6ac">6.4.6. Insert then extract</a></li>
<li><a href="#org86b6aec">6.4.7. Searching</a></li>
<li><a href="#org7e92748">6.4.8. Deleting arbitray element</a></li>
<li><a href="#org88a5120">6.4.9. Decrease and increase keys</a></li>
</ul>
</li>
<li><a href="#org7fa13c0">6.5. Building a heap from array</a></li>
</ul>
</li>
<li><a href="#orga31eb53">7. Graphs</a>
<ul>
<li><a href="#orgfc9e0fa">7.1. Representing graphs</a>
<ul>
<li><a href="#org29f60cc">7.1.1. Adjacency List</a></li>
<li><a href="#org7350965">7.1.2. Adjacency Matrix</a></li>
</ul>
</li>
<li><a href="#org2779c9b">7.2. Vertex and edge attributes</a></li>
<li><a href="#org149b890">7.3. Density of graph</a>
<ul>
<li><a href="#org68298dc">7.3.1. Which representation to use</a></li>
</ul>
</li>
<li><a href="#orgad83141">7.4. Searching Graphs</a>
<ul>
<li><a href="#org091c563">7.4.1. Breadth first search</a></li>
<li><a href="#orgab43fa4">7.4.2. Breadth-first trees for shortest path</a></li>
<li><a href="#orgcf9333d">7.4.3. Depth first search</a></li>
<li><a href="#org1d56cc6">7.4.4. Properties of DFS</a></li>
<li><a href="#orgf43e579">7.4.5. Topological sort using DFS</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-org81ab3fa" class="outline-2">
<h2 id="org81ab3fa"><span class="section-number-2">1.</span> Stack</h2>
<div class="outline-text-2" id="text-1">
<p>
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.
<br />
<b>It is similar to stacking plates.</b> The plate can only be added at the <b>top</b> of the stack and also only the last added plate to the stack can be removed (which will be on top).
<br />
Due to this property, Last In elements are removed First from a stack. Therefore, it is called a <b>Last In First Out (LIFO)</b> data structure or a <b>First In Last Out (FILO)</b> data structure.
<br />
To create a stack, we will keep track of the index which is the <b>top</b> of the array. This top index will <b>increment when we insert element</b> and <b>decrement when we remove element.</b>
</p>
</div>
<div id="outline-container-org476cd3f" class="outline-3">
<h3 id="org476cd3f"><span class="section-number-3">1.1.</span> Operation on stack</h3>
<div class="outline-text-3" id="text-1-1">
<p>
A stack has two operations
</p>
</div>
</div>
</div>
<div id="outline-container-org6466b75" class="outline-2">
<h2 id="org6466b75"><span class="section-number-2">2.</span> Direct Address Table</h2>
<div class="outline-text-2" id="text-2">
<p>
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.
<br />
This also assumes that keys are integers
</p>
<ul class="org-ul">
<li>Table creation</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span>{
<span style="color: #c18401;">int</span> * <span style="color: #8b4513;">values</span>;
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">min_key</span>;
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">max_key</span>;
};
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #0184bc;">create_table</span>(<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">min_key</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">max_key</span>){
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">r</span>;
r.values = (<span style="color: #c18401;">int</span> * ) malloc(<span style="color: #a626a4;">sizeof</span>(<span style="color: #c18401;">int</span>) * (max_key - min_key + 1) );
r.min_key = min_key;
r.max_key = max_key;
<span style="color: #a626a4;">return</span> r;
}
</pre>
</div>
<ul class="org-ul">
<li>Table insert</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">table_insert</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">t</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>, <span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>){
<span style="color: #a626a4;">if</span>(key &gt; t.max_key || key &lt; t.min_key)
assert(<span style="font-weight: bold; text-decoration: underline;">false</span> &amp;&amp; <span style="color: #50a14f;">"Key value out of boundry"</span>);
t.values[key - t.min_key] = value;
}
</pre>
</div>
<ul class="org-ul">
<li>Table delete</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">table_delete</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">t</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>){
<span style="color: #a626a4;">if</span>(key &gt; t.max_key || key &lt; t.min_key)
assert(<span style="font-weight: bold; text-decoration: underline;">false</span> &amp;&amp; <span style="color: #50a14f;">"Key value out of boundry"</span>);
t.values[key - t.min_key] = 0x00;
}
</pre>
</div>
<ul class="org-ul">
<li>Table Search / Table Get</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">int</span> <span style="color: #0184bc;">table_get</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">t</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>){
<span style="color: #a626a4;">if</span>(key &gt; t.max_key || key &lt; t.min_key)
assert(<span style="font-weight: bold; text-decoration: underline;">false</span> &amp;&amp; <span style="color: #50a14f;">"Key value out of boundry"</span>);
<span style="color: #a626a4;">return</span> t.values[key - t.min_key];
}
</pre>
</div>
<p>
<b>Using direct address tables is very useful when keys are enum values.</b>
</p>
</div>
</div>
<div id="outline-container-orgb6526cf" class="outline-2">
<h2 id="orgb6526cf"><span class="section-number-2">3.</span> Hash Table</h2>
<div class="outline-text-2" id="text-3">
<p>
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 <i><b>hash</b></i> for it using a <i><b>hash function</b></i>. Since we are relying on hashes for this addressing in the table, we call it a hash table.
<br />
<br />
For a given key \(k_i\) in <b><i>direct address table</i></b>, we store value in \(table[k_i]\).
<br />
<br />
For a given key \(k_i\) in <b><i>hash table</i></b>, we store value in \(table[h(k_i)]\), where \(h()\) is the hash function.
<br />
<br />
So the main purpose of the hash function is to reduce the range of array indices.
</p>
</div>
<div id="outline-container-org64d5283" class="outline-3">
<h3 id="org64d5283"><span class="section-number-3">3.1.</span> Collision</h3>
<div class="outline-text-3" id="text-3-1">
<p>
Because we are reducing the range of indices, the hash function may <i><b>hash two keys to the same slot</b></i>. This is called a collision.
<br />
<br />
We should try to find a hash funtion which will minimise the number of collisions.
<br />
<br />
The number of keys is going to be greater than number of slots in table. Therefore avoiding all collisions is not possible.
<br />
There are two ways we will look at to resolve collision.
</p>
<ol class="org-ol">
<li>Chaining</li>
<li>Open addressing</li>
</ol>
</div>
<div id="outline-container-org23a9fe2" class="outline-4">
<h4 id="org23a9fe2"><span class="section-number-4">3.1.1.</span> Chaining</h4>
<div class="outline-text-4" id="text-3-1-1">
<p>
In chaining, rather than storing values in table slots. We will have <i><b>linked lists at each slot</b></i> which will store (key, value) pairs.
<br />
<br />
When the hash gives us a slot, we will add the value to linked list at that slot.
</p>
<ul class="org-ul">
<li>Linked List structure</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">linked_list</span>{
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>;
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">linked_list</span> * <span style="color: #8b4513;">next</span>;
};
</pre>
</div>
<ul class="org-ul">
<li>Table structure</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span>{
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">linked_list</span> * <span style="color: #8b4513;">table</span>[];
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">table_size</span>;
};
</pre>
</div>
<ul class="org-ul">
<li>Insertion</li>
</ul>
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">linked_list_add(struct linked_list * ll, size_t key, int value)</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">adds the given key,value to the start of the list</span>
<span style="color: #c18401;">void</span> <span style="color: #0184bc;">chained_hash_insert</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">t</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>, <span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>){
linked_list_add(t.table[ h(key) ], key ,value);
}
</pre>
</div>
<ul class="org-ul">
<li>Get / Search</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">linked_list_search(struct linked_list * ll, size_t key)</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">gets the value stored with the given key</span>
<span style="color: #c18401;">void</span> <span style="color: #0184bc;">chained_hash_get</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">t</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>){
<span style="color: #a626a4;">return</span> linked_list_search(t.table[ h(key) ], key);
}
</pre>
</div>
<ul class="org-ul">
<li>Delete</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">linked_list_delete(struct linked_list * ll, size_t key)</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">delete the node with the given key</span>
<span style="color: #c18401;">void</span> <span style="color: #0184bc;">chained_hash_delete</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">table</span> <span style="color: #8b4513;">t</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>){
linked_list_delete(t.table[ h(key) ], key);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org732d622" class="outline-4">
<h4 id="org732d622"><span class="section-number-4">3.1.2.</span> Performance of chaining hash table</h4>
<div class="outline-text-4" id="text-3-1-2">
<p>
The <b>load factor</b> 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.
<br />
<br />
If we assume that any given element is equally likely to be hashed into any of the slots, this assumption is called <b><i>simple uniform hashing</i></b>.
<br />
<br />
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) \]
</p>
</div>
</div>
<div id="outline-container-orga12689d" class="outline-4">
<h4 id="orga12689d"><span class="section-number-4">3.1.3.</span> Open Addressing</h4>
<div class="outline-text-4" id="text-3-1-3">
<p>
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.
<br />
<br />
When we get a key whose slot is already taken, we will look for another empty slot. This is done by what is called <b><i>probing</i></b>. To get which slot to check next, we have various methods.
<br />
<br />
The sequence in which empty slots are looked for is fixed for given key, this sequence is called <b>probe sequence</b>. <br />
It is necessary to keep probe sequence fixed for any given key, so that we can search for it later.
</p>
</div>
<ol class="org-ol">
<li><a id="org513c43d"></a><b>Linear probing</b><br />
<div class="outline-text-5" id="text-3-1-3-1">
<p>
For a given <b>ordinary hash function</b> \(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 <b><i>auxiliary hash function</i></b>.
<br />
<br />
In linear probing, we first check the slot [h(k)], if it is not empty, we check [h(k) + 1] then [h(k) + 2] &#x2026;. upto slot [m - 1] after which we wrap around to [1], [2] &#x2026; till we have checked all the slots.
<br />
<br />
Linear probing is easy to implement, but it suffers from <b><i>primary clustering</i></b>. 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)\).
</p>
</div>
</li>
<li><a id="org4ad356d"></a><b>Quadratic probing</b><br />
<div class="outline-text-5" id="text-3-1-3-2">
<p>
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.
</p>
<ul class="org-ul">
<li>If m is not considered, we just assume \(c_1 = 0, c_2 = 1\), this is the simplest form of quadratic probing.</li>
<li>For \(m = 2^n\), a good choice for auxiliary constants is \(c_1=c_2=1/2\).</li>
<li>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.</li>
</ul>
<p>
Quadratic probing works much better than linear probing.
<br />
<br />
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 <b>probe sequence</b>. This leads to a probe sequence getting clustered. This is called <i><b>secondary clustering</b></i>. This also effects performance but not as drastically as primary clustering.
</p>
</div>
</li>
<li><a id="org317ecf5"></a><b>Double Hashing</b><br />
<div class="outline-text-5" id="text-3-1-3-3">
<p>
Double hashing is one of the best available method for open addressing. <br />
<b>Double hashing uses <i>two auxiliary hashing functions</i>.</b>
\[ double\_h(k, i) = \left( h_1(k) + i \times h_2(k) \right) \ mod\ m \]
The value of \(h_2(k)\) must be <b>relatively prime (i.e, coprime) to number of slots (m)</b>. <br />
</p>
<ul class="org-ul">
<li>A convenient way to ensure this is let <b>m be a power of 2</b> and \(h_2(k)\) be a <b>hash function that always produces an odd number</b>.</li>
<li>Another way is to let <b>m be a prime</b> and make \(h_2(k)\) such that is <b>always produces a positive integer less than m.</b></li>
</ul>
<p>
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.
<br />
<br />
When using the above values of m, performance of double hashing is very close to the performance of "ideal" scheme of uniform hashing.
<b>*n</b> Performace of open addressing
In open addressing <b>load factor</b> \(\left( \alpha \right) \le 1\). We will assume <b>uniform hashing</b> 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.
<br />
<br />
Under these assumptions, for load factor \(\alpha\). The number of probes in an unsuccessful search is at most \(1/(1 - \alpha )\)
<br />
This means that for a constant load factor, an unsuccessful search will run in \(\theta (1)\) time.
<br />
<br />
The number of probes on average for inserting an element under these assumptions is \(1/(1- \alpha )\)
<br />
The number of probes on averge in a successful search is at most \(\frac{1}{\alpha} ln\left( \frac{1}{1-\alpha} \right)\)
</p>
</div>
</li>
</ol>
</div>
</div>
<div id="outline-container-orgb32fcc8" class="outline-3">
<h3 id="orgb32fcc8"><span class="section-number-3">3.2.</span> Hash Functions</h3>
<div class="outline-text-3" id="text-3-2">
<p>
A good hash funtion will approximately satisfy the <b>simple uniform hashing</b>, which means that any element is equally likely to be hashed to any slot.
</p>
<p>
\[ m : \text{Number of slots in hash table} \]
\[ n : \text{Number of elements in hash table} \]
</p>
<p>
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)\).
<br />
<br />
Similarly, in many cases we can make a reasonably good hash funtion if we know the distribution of keys.
<br />
<br />
We will look at a few ways to make a hash function.
</p>
</div>
<div id="outline-container-org64ed2dc" class="outline-4">
<h4 id="org64ed2dc"><span class="section-number-4">3.2.1.</span> The division method</h4>
<div class="outline-text-4" id="text-3-2-1">
<p>
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.
</p>
<ul class="org-ul">
<li>If \(m\) is a <b>power of 2</b>, 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, <b><i>we should not use this method if m is a power of 2</i></b>.</li>
<li>A <b>prime number</b> 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 <i><b>try to make \(m\) a prime</b></i> which will accomodate our elements with less load factor.</li>
</ul>
</div>
</div>
<div id="outline-container-org7d82f3d" class="outline-4">
<h4 id="org7d82f3d"><span class="section-number-4">3.2.2.</span> The multiplication method</h4>
<div class="outline-text-4" id="text-3-2-2">
<p>
In multiplication method, we first multiply the key \(k\) with a constant \(A\) which is in range \(0 < A < 1\). Then we get the <b>fractional part</b> 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.
<br />
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.
<br />
<br />
Example, Suppose
</p>
<p>
\[ 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 \]
</p>
<p>
In C language,
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">size_t</span> <span style="color: #0184bc;">hash</span>(<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">key</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">m</span>){
<span style="color: #c18401;">double</span> <span style="color: #8b4513;">kA</span> = key * 0.618;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">get decimal part only</span>
<span style="color: #c18401;">double</span> <span style="color: #8b4513;">kA</span> = kA - ((<span style="color: #c18401;">int</span>) kA);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">floor the product of decimal part and m</span>
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">h</span> = floor(m * kA);
<span style="color: #a626a4;">return</span> h;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-orgcf8d990" class="outline-4">
<h4 id="orgcf8d990"><span class="section-number-4">3.2.3.</span> Mid square method</h4>
<div class="outline-text-4" id="text-3-2-3">
<p>
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.
</p>
</div>
</div>
<div id="outline-container-org719601b" class="outline-4">
<h4 id="org719601b"><span class="section-number-4">3.2.4.</span> Folding method</h4>
<div class="outline-text-4" id="text-3-2-4">
<p>
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.
<br />
<br />
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"
<br />
sum = 'h' + 'e' + 'l' + 'l' + 'o'
<br />
sum = 104 + 101 + 108 + 108 + 111 = 532
<br />
<br />
If m = 100, then
<br />
h(k) = 532 mod 100
<br />
h(k) = 32
</p>
</div>
</div>
</div>
<div id="outline-container-org000a70c" class="outline-3">
<h3 id="org000a70c"><span class="section-number-3">3.3.</span> Universal Hashing</h3>
<div class="outline-text-3" id="text-3-3">
<p>
TODO: Basics of universal hashing.
</p>
</div>
</div>
<div id="outline-container-org0b7a2f3" class="outline-3">
<h3 id="org0b7a2f3"><span class="section-number-3">3.4.</span> Perfect Hashing</h3>
<div class="outline-text-3" id="text-3-4">
<p>
<b>NOTE</b>: This doesn't seem to be in B.Tech syllabus, but it seems cool.
<br />
</p>
</div>
</div>
</div>
<div id="outline-container-orga2c39cb" class="outline-2">
<h2 id="orga2c39cb"><span class="section-number-2">4.</span> Representing rooted trees using nodes</h2>
<div class="outline-text-2" id="text-4">
<p>
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.
<br />
In C, we make a struct which will store the element and pointers to other node structs.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span>{
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">element</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">left_child</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">right_child</span>;
};
</pre>
</div>
<p>
<br />
In languages with oop, we create node class which will store refrences to other node objects.
</p>
<div class="org-src-container">
<pre class="src src-java"><span style="color: #a626a4;">class</span> <span style="color: #c18401;">Node</span> {
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>;
<span style="color: #c18401;">Node</span> <span style="color: #8b4513;">left</span>;
<span style="color: #c18401;">Node</span> <span style="color: #8b4513;">right</span>;
Node(<span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>) {
<span style="color: #a626a4;">this</span>.value = value;
right = <span style="font-weight: bold; text-decoration: underline;">null</span>;
left = <span style="font-weight: bold; text-decoration: underline;">null</span>;
}
}
</pre>
</div>
</div>
<div id="outline-container-orgd36b71b" class="outline-3">
<h3 id="orgd36b71b"><span class="section-number-3">4.1.</span> Fixed number of children</h3>
<div class="outline-text-3" id="text-4-1">
<p>
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.
<br />
For example, if we know we are making a binary tree, then we can just store refrence to left children and right childern.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span>{
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">element</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">left_child</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">right_child</span>;
};
</pre>
</div>
</div>
</div>
<div id="outline-container-orgfbf415c" class="outline-3">
<h3 id="orgfbf415c"><span class="section-number-3">4.2.</span> Unbounded number of children</h3>
<div class="outline-text-3" id="text-4-2">
<p>
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.
<br />
There is a way to represent such trees without wasting any memory. This is done by using <b>sibling refrences or pointers</b>.
<br />
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span>{
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">element</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">left_child</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">right_sibling</span>;
};
</pre>
</div>
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span>{
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">parent</span>;
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">element</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">left_child</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">tree_node</span> * <span style="color: #8b4513;">right_sibling</span>;
};
</pre>
</div>
<p>
So a tree which is like :
<br />
<img src="./imgs/tree_actual.jpg" alt="tree_actual.jpg" />
<br />
<br />
can be represented using refrences and pointers as :
<br />
<img src="./imgs/tree_representation.jpg" alt="tree_representation.jpg" />
<br />
</p>
</div>
</div>
</div>
<div id="outline-container-orgda50fd0" class="outline-2">
<h2 id="orgda50fd0"><span class="section-number-2">5.</span> Binary Search Trees</h2>
<div class="outline-text-2" id="text-5">
<p>
A tree where any node can have only two child nodes is called a <b><i>binary tree</i></b>.
<br />
A binary search tree is a tree where for any give node <b>the nodes stored in left sub-tree are less than the parent node</b> and the <b>nodes stored in right sub-tree are greater than the parent node</b> (or vice versa). So the left-subtree always have smaller elements and right sub-tree always have greater elements.
<br />
<br />
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.
</p>
<p>
In C, we can make a binary tree as
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span>{
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">left_child</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">right_child</span>;
};
</pre>
</div>
</div>
<div id="outline-container-orgf95dd3b" class="outline-3">
<h3 id="orgf95dd3b"><span class="section-number-3">5.1.</span> Quering a BST</h3>
<div class="outline-text-3" id="text-5-1">
<p>
Some common ways in which we usually query a BST are searching for a node, minimum &amp; maximum node and successor &amp; 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.
</p>
</div>
<div id="outline-container-org97d681f" class="outline-4">
<h4 id="org97d681f"><span class="section-number-4">5.1.1.</span> Searching for node</h4>
<div class="outline-text-4" id="text-5-1-1">
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *
<span style="color: #0184bc;">search_recursively</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">root</span>, <span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">If we reach a null, then value is not in tree</span>
<span style="color: #a626a4;">if</span>(root == <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if we found the value, return the current node</span>
<span style="color: #a626a4;">if</span>(root-&gt;value == value)
<span style="color: #a626a4;">return</span> root;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">compare value we are looking for</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">and go to either left or right sub-tree</span>
<span style="color: #a626a4;">if</span>(value &lt; root-&gt;value)
<span style="color: #a626a4;">return</span> search_recursively(root-&gt;left, value);
<span style="color: #a626a4;">else</span>
<span style="color: #a626a4;">return</span> search_recursively(root-&gt;right, value);
}
</pre>
</div>
<p>
We can also search iteratively rather than recursively.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *
<span style="color: #0184bc;">search_iterative</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">root</span>, <span style="color: #c18401;">int</span> <span style="color: #8b4513;">value</span>){
<span style="color: #a626a4;">while</span>(root != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if we found the value, return the current node</span>
<span style="color: #a626a4;">if</span>(root-&gt;value == value) <span style="color: #a626a4;">return</span> root;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">compare value and go to left or right sub-tree</span>
root = (value &lt; root-&gt;value) ? root-&gt;left : root-&gt;right;
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if not found then return NULL</span>
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org286a6d6" class="outline-4">
<h4 id="org286a6d6"><span class="section-number-4">5.1.2.</span> Minimum and maximum</h4>
<div class="outline-text-4" id="text-5-1-2">
<p>
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.
</p>
<ul class="org-ul">
<li>For minimum node</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #0184bc;">minimum</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">root</span>){
<span style="color: #a626a4;">if</span>(root == <span style="font-weight: bold; text-decoration: underline;">NULL</span>) <span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
<span style="color: #a626a4;">while</span>(root-&gt;left != <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
root = root-&gt;left;
<span style="color: #a626a4;">return</span> root;
}
</pre>
</div>
<ul class="org-ul">
<li>For maximum node</li>
</ul>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #0184bc;">maximum</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">root</span>){
<span style="color: #a626a4;">if</span>(root == <span style="font-weight: bold; text-decoration: underline;">NULL</span>) <span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
<span style="color: #a626a4;">while</span>(root-&gt;right != <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
root = root-&gt;right;
<span style="color: #a626a4;">return</span> root;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org9af08d0" class="outline-4">
<h4 id="org9af08d0"><span class="section-number-4">5.1.3.</span> Find Parent Node</h4>
<div class="outline-text-4" id="text-5-1-3">
<p>
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. <b>This algorithm makes the assumption that the node is in the tree</b>.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *
<span style="color: #0184bc;">find_parent</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">tree</span>, <span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">node</span>){
<span style="color: #a626a4;">if</span>(tree == node) <span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">current_node</span> = tree;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">trailing_node</span> = tree;
<span style="color: #a626a4;">while</span>(current_node != node){
trailing_node = current_node;
current_node = (node-&gt;value &lt; current_node-&gt;value) ?
current_node-&gt;left :
current_node-&gt;right;
}
<span style="color: #a626a4;">return</span> trailing_node;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-orgeacb6ef" class="outline-4">
<h4 id="orgeacb6ef"><span class="section-number-4">5.1.4.</span> Is ancestor</h4>
<div class="outline-text-4" id="text-5-1-4">
<p>
This algorithm will take two nodes, ancestor and descendant. Then it will check if ancestor node is really the ancestor of descendant node.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">bool</span>
<span style="color: #0184bc;">is_ancestor</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">ancestor</span>,
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">descendant</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">both ancestor and descendant</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">should not be NULL</span>
<span style="color: #a626a4;">if</span>(ancestor == <span style="font-weight: bold; text-decoration: underline;">NULL</span> || descendant == <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">false</span>;
<span style="color: #a626a4;">while</span>(ancestor != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">if</span>(ancestor == descendant) <span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">true</span>;
ancestor = (descendant-&gt;value &lt; ancestor-&gt;value) ?
ancestor-&gt;left :
ancestor-&gt;right;
}
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">false</span>;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-orgce7c596" class="outline-4">
<h4 id="orgce7c596"><span class="section-number-4">5.1.5.</span> Successor and predecessor</h4>
<div class="outline-text-4" id="text-5-1-5">
<p>
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.
</p>
</div>
<ol class="org-ol">
<li><a id="orge72e259"></a><b>For Successor</b><br />
<div class="outline-text-5" id="text-5-1-5-1">
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">get successor of x</span>
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *
<span style="color: #0184bc;">successor</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">tree</span>, <span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">x</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 1 : right subtree is non-empty</span>
<span style="color: #a626a4;">if</span>(x-&gt;right != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">return</span> minimum(x-&gt;right);
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 2 : right subtree is empty</span>
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">y</span> = find_parent(tree, x);
<span style="color: #a626a4;">while</span>(y != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">if</span>(is_ancestor(y, x) &amp;&amp; is_ancestor(y-&gt;left, x)) <span style="color: #a626a4;">return</span> y;
y = find_parent(tree, y);
}
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
}
</pre>
</div>
<p>
<b>Case 1</b> : If the node x has a right subtree, then the minimum of right subtree of x is the succesor.
<br />
<b>Case 2</b> : 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.
</p>
</div>
</li>
<li><a id="org3215bc6"></a><b>For Predecessor</b><br />
<div class="outline-text-5" id="text-5-1-5-2">
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *
<span style="color: #0184bc;">predecessor</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">tree</span>, <span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">x</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 1 : left subtree is non-empty</span>
<span style="color: #a626a4;">if</span>(x-&gt;left != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">return</span> maximum(x-&gt;left);
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 2 : left subtree is empty</span>
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">y</span> = find_parent(tree, x);
<span style="color: #a626a4;">while</span>(y != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">if</span>(is_ancestor(y, x) &amp;&amp; is_ancestor(y-&gt;right, x)) <span style="color: #a626a4;">return</span> y;
y = find_parent(tree, y);
}
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
}
</pre>
</div>
<p>
<b>Case 1</b> : If the node x has a left subtree, then the maximum of left subtree of x is the predecessor.
<br />
<b>Case 2</b> : 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.
</p>
</div>
</li>
</ol>
</div>
</div>
<div id="outline-container-orgee97ab6" class="outline-3">
<h3 id="orgee97ab6"><span class="section-number-3">5.2.</span> Inserting and Deleting nodes</h3>
<div class="outline-text-3" id="text-5-2">
<p>
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.
</p>
</div>
<div id="outline-container-org5fbdca0" class="outline-4">
<h4 id="org5fbdca0"><span class="section-number-4">5.2.1.</span> Insertion</h4>
<div class="outline-text-4" id="text-5-2-1">
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span>
<span style="color: #0184bc;">insert_node</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> ** <span style="color: #8b4513;">tree</span>, <span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">node</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if found a null spot, insert the node</span>
<span style="color: #a626a4;">if</span>(*tree == <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
*tree = node;
<span style="color: #a626a4;">return</span>;
}
<span style="color: #a626a4;">if</span>(node-&gt;value &lt; (*tree)-&gt;value){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">the node is to be inserted into left subtree</span>
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> ** <span style="color: #8b4513;">left_tree</span> = &amp;((*tree)-&gt;left);
insert_node(left_tree, node);
}<span style="color: #a626a4;">else</span>{
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">the node is to be inserted into right subtree</span>
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> ** <span style="color: #8b4513;">right_tree</span> = &amp;((*tree)-&gt;right);
insert_node(right_tree, node);
}
}
</pre>
</div>
<p>
The recursive algorithm for inserting into a Binary search tree is simpler than the iterative algorithm.
<br />
<br />
The algorithm for iterative insertion is
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span>
<span style="color: #0184bc;">insert_node</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> **<span style="color: #8b4513;">tree</span>, <span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">node</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if no nodes in tree, then just node and return</span>
<span style="color: #a626a4;">if</span>((*tree) == <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
*tree = node;
<span style="color: #a626a4;">return</span>;
}
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> ** <span style="color: #8b4513;">current_node</span> = tree;
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> ** <span style="color: #8b4513;">trailing_node</span> = tree;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">look for an empty place using current_node</span>
<span style="color: #a626a4;">while</span>(*current_node != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
trailing_node = current_node;
current_node = (node-&gt;value &lt; (*current_node)-&gt;value) ?
&amp;((*current_node)-&gt;left) : &amp;((*current_node)-&gt;right);
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">we need to insert node on the trailing node</span>
<span style="color: #a626a4;">if</span>(node-&gt;value &lt; (*trailing_node)-&gt;value)
(*trailing_node)-&gt;left = node;
<span style="color: #a626a4;">else</span>
(*trailing_node)-&gt;right = node;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org3d65276" class="outline-4">
<h4 id="org3d65276"><span class="section-number-4">5.2.2.</span> Deletion</h4>
<div class="outline-text-4" id="text-5-2-2">
<p>
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.
<br />
<br />
TODO : Write four cases of node deletion here
</p>
</div>
<ol class="org-ol">
<li><a id="org095bbad"></a><b>Implementation in code</b><br />
<div class="outline-text-5" id="text-5-2-2-1">
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span>
<span style="color: #0184bc;">replace_child</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">parent</span>,
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">old_child</span>,
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">new_child</span>){
<span style="color: #a626a4;">if</span>(parent-&gt;left == old_child) parent-&gt;left = new_child;
<span style="color: #a626a4;">else</span> parent-&gt;right = new_child;
}
</pre>
</div>
<p>
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.
<br />
<br />
Making remove root node a different funtion will also allow us to not worry about attaching the the subtree immediately in the same funtion.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *
<span style="color: #0184bc;">remove_root_node</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">root</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 1 : no child</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">this case can be skipped in real implementation</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">as it is covered by the case 2</span>
<span style="color: #a626a4;">if</span>(root-&gt;left == <span style="font-weight: bold; text-decoration: underline;">NULL</span> &amp;&amp; root-&gt;right == <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">return</span> <span style="font-weight: bold; text-decoration: underline;">NULL</span>;
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 2 : one child</span>
<span style="color: #a626a4;">if</span>(root-&gt;left == <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">return</span> root-&gt;right;
}<span style="color: #a626a4;">else</span> <span style="color: #a626a4;">if</span>(root-&gt;right == <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #a626a4;">return</span> root-&gt;left;
}
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">successor</span> = minimum(root-&gt;right);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 3 : two child and successor is right node of root node</span>
<span style="color: #a626a4;">if</span>(successor == root-&gt;right){
successor-&gt;left = root-&gt;left;
<span style="color: #a626a4;">return</span> successor;
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">case 4 : two child and successor is not the right node of root node</span>
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">successor_parent</span> = find_parent(root, successor);
replace_child(successor_parent, successor, successor-&gt;right);
successor-&gt;left = root-&gt;left;
successor-&gt;right = root-&gt;right;
<span style="color: #a626a4;">return</span> successor;
}
</pre>
</div>
<p>
Now we can make a delete node function which will remove the node, reattach the subtree and also free or delete the node.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span>
<span style="color: #0184bc;">delete_node</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tre</span> **<span style="color: #8b4513;">tree</span>, <span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">node</span>){
<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> *<span style="color: #8b4513;">new_root</span> = remove_root_node(node);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if deleting root node of tree</span>
<span style="color: #a626a4;">if</span>(node == (*tree)){
(*tree) = new_root;
free(node);
<span style="color: #a626a4;">return</span>;
}
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">when not deleting root node of tree</span>
replace_child(find_parent(*tree, node)
,node ,new_root);
free(node);
}
</pre>
</div>
</div>
</li>
</ol>
</div>
</div>
<div id="outline-container-org438ffbb" class="outline-3">
<h3 id="org438ffbb"><span class="section-number-3">5.3.</span> Performance of BST</h3>
<div class="outline-text-3" id="text-5-3">
<p>
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)\).
<br />
<br />
To perform an operation on BST, we need to find the node where we have perform the operation. Since even in worst case <b>we only need to traverse the height of the search tree to search for any node</b>, the time taken to perform any operation on a Binary Search Tree is \(\theta (h)\) where, \(h\) is the height of the tree.
<br />
<br />
A binary tree with height of \(floor(1 + log_2(n))\) is called a <b>balanced binary tree</b>, otherwise it is an unbalanced tree. A balanced binary tree is the shortest height a binary tree with that number of nodes can have.
<br />
<br />
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.
<br />
A balanced binary search tree in worst case for any operation will take \(\theta (log_2n)\) time.
</p>
</div>
</div>
<div id="outline-container-orgb60c267" class="outline-3">
<h3 id="orgb60c267"><span class="section-number-3">5.4.</span> Traversing a Binary Tree</h3>
<div class="outline-text-3" id="text-5-4">
<p>
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.
</p>
</div>
<div id="outline-container-orgb03b5c9" class="outline-4">
<h4 id="orgb03b5c9"><span class="section-number-4">5.4.1.</span> Inorder tree walk</h4>
<div class="outline-text-4" id="text-5-4-1">
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">inorder_print</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">node</span>){
<span style="color: #a626a4;">if</span>(node == <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
<span style="color: #a626a4;">return</span>;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">recursively print left sub-tree</span>
inorder_print(node-&gt;left_child);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">print the node value</span>
printf(<span style="color: #50a14f;">"%d\t"</span>, node-&gt;value);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">recursively print right sub-tree</span>
inorder_print(node-&gt;right_child);
}
</pre>
</div>
<ul class="org-ul">
<li><b>Inorder algorithm will traverse the binary search tree in a sorted order.</b> Thus, it can be used to get nodes in a sorted order.</li>
<li>This algorithm is not suitable to delete or free the nodes of the tree. It should not be used to delete a binary tree.</li>
<li>This algorithm cannot we used to make a copy of a binay search tree.</li>
</ul>
</div>
</div>
<div id="outline-container-org32eaac9" class="outline-4">
<h4 id="org32eaac9"><span class="section-number-4">5.4.2.</span> Preorder tree walk</h4>
<div class="outline-text-4" id="text-5-4-2">
<p>
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">preorder_print</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">node</span>){
<span style="color: #a626a4;">if</span>(node == <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
<span style="color: #a626a4;">return</span>;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">print the node</span>
printf(<span style="color: #50a14f;">"%d\t"</span>, node-&gt;value);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">recursively print left sub-tree</span>
preorder_print(node-&gt;left_child);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">recursively print right sub-tree</span>
preorder_print(node-&gt;right_child);
}
</pre>
</div>
<ul class="org-ul">
<li><b>This algorithm is used to create a copy of the Binary Search Tree</b>. 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.</li>
<li>This algorithm traverses the tree in a <b>topologically sorted</b> order.</li>
<li>This algorithm cannot be used to delete or free the nodes of the tree.</li>
</ul>
</div>
</div>
<div id="outline-container-orgdb18f9b" class="outline-4">
<h4 id="orgdb18f9b"><span class="section-number-4">5.4.3.</span> Postorder tree walk</h4>
<div class="outline-text-4" id="text-5-4-3">
<p>
In this algorithm, we first traverse the left sub-tree recursively, then the right-sub tree recursively and finally the node.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">postorder_print</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">binary_tree</span> * <span style="color: #8b4513;">node</span>){
<span style="color: #a626a4;">if</span>(node == <span style="font-weight: bold; text-decoration: underline;">NULL</span>)
<span style="color: #a626a4;">return</span>;
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">recursively print left sub-tree</span>
postorder_print(node-&gt;left_child);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">recursively print right sub-tree</span>
postorder_print(node-&gt;right_child);
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">print the node</span>
printf(<span style="color: #50a14f;">"%d\t"</span>, node-&gt;value);
}
</pre>
</div>
<ul class="org-ul">
<li><b>This algorithm can be used to delete or free all the nodes of a binary tree</b>.</li>
<li>This algorithm cannot be used to create a copy of the tree</li>
</ul>
</div>
</div>
</div>
</div>
<div id="outline-container-org2128999" class="outline-2">
<h2 id="org2128999"><span class="section-number-2">6.</span> Binary Heap</h2>
<div class="outline-text-2" id="text-6">
<p>
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.
<br />
<br />
The most common implementation of the heap is a <b>binary heap</b>. The binary heap is represented as a binary tree. We can use an array to implement binary heaps.
<br />
<br />
The heap data structure is used to implement <b>priority queues</b>. In many cases we even refer to heaps as priority queues and vice versa.
</p>
</div>
<div id="outline-container-org0ad3ed1" class="outline-3">
<h3 id="org0ad3ed1"><span class="section-number-3">6.1.</span> Heap Property</h3>
<div class="outline-text-3" id="text-6-1">
<p>
Heaps are of two types
</p>
<ul class="org-ul">
<li><b>min-heap</b> : the smallest element is at the root of the tree.</li>
<li><b>max-heap</b> : the largest element is at the root of the tree.</li>
</ul>
<p>
The heap property is different for min-heaps and max-heaps.
</p>
<ul class="org-ul">
<li><b>for min-heap</b> : the key stored in parent node is always less than or equal \((\le)\) to the key of child node.</li>
<li><b>for max-heap</b> : the key stored in parent node is always greter than or equal \((\ge)\) to the key of child node.</li>
</ul>
</div>
</div>
<div id="outline-container-org2ddce59" class="outline-3">
<h3 id="org2ddce59"><span class="section-number-3">6.2.</span> Shape of Heap</h3>
<div class="outline-text-3" id="text-6-2">
<p>
Also reffered to as <b>shape property</b> of heap.
<br />
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.
</p>
</div>
</div>
<div id="outline-container-orgc2ae7dd" class="outline-3">
<h3 id="orgc2ae7dd"><span class="section-number-3">6.3.</span> Array implementation</h3>
<div class="outline-text-3" id="text-6-3">
<p>
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.
<br />
<br />
<i><b>For a given level, the position in array from left to right is the position of elements in tree from left to right.</b></i>
<br />
<br />
For example, a max-heap implemented using array can be represented as tree as shown
<br />
<br />
<img src="./imgs/Heap-as-array.svg" alt="Heap-as-array.svg" class="org-svg" />
<br />
<br />
In C, we can create a heap struct for easier implementation of algorithms
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a626a4;">struct</span> <span style="color: #c18401;">heap_type</span>{
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">array</span>[];
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">capacity</span>;
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">len</span>;
};
</pre>
</div>
</div>
</div>
<div id="outline-container-org7251356" class="outline-3">
<h3 id="org7251356"><span class="section-number-3">6.4.</span> Operations on heaps</h3>
<div class="outline-text-3" id="text-6-4">
<p>
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.
</p>
</div>
<div id="outline-container-orgb8e21e1" class="outline-4">
<h4 id="orgb8e21e1"><span class="section-number-4">6.4.1.</span> Parent and child indices</h4>
<div class="outline-text-4" id="text-6-4-1">
<p>
In a binary heap, we can find parent and children for any given index using simple formulas.
</p>
<ul class="org-ul">
<li>If array is zero indexed, for element at index i
<ul class="org-ul">
<li>children at indices \((2i + 1)\) and \((2i + 2)\)</li>
<li>parent at index \(floor\left( (i - 1)/2 \right)\)</li>
</ul></li>
<li>If array is one indexed, for element at index i
<ul class="org-ul">
<li>children at indices \((2i)\) and \((2i + 1)\)</li>
<li>parent at index \(floor\left( i/2 \right)\)</li>
</ul></li>
</ul>
</div>
</div>
<div id="outline-container-orgd61130f" class="outline-4">
<h4 id="orgd61130f"><span class="section-number-4">6.4.2.</span> Down-heapify</h4>
<div class="outline-text-4" id="text-6-4-2">
<p>
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.
<br />
This function runs in \(\theta (log_2n)\) time. The algorithm for this works as follows
</p>
<ol class="org-ol">
<li>Compare the index element with its children and stop if in correct order in relation to both children.</li>
<li>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.</li>
</ol>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">down_heapify</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">heap_type</span> <span style="color: #8b4513;">heap</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">index</span>){
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">left</span> = 2 * index + 1;
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">right</span> = 2 * index + 2;
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">largest</span> = index;
<span style="color: #a626a4;">if</span>(left &lt; heap.len &amp;&amp; heap.array[left] &gt; heap.array[largest])
largest = left;
<span style="color: #a626a4;">if</span>(right &lt; heap.len &amp;&amp; heap.array[right] &gt; heap.array[largest])
largest = right;
<span style="color: #a626a4;">if</span>(largest != index){
swap(heap.array[index], heap.array[largest]);
down_heapify(heap, largest);
}
}
</pre>
</div>
<p>
Since we shift element downwards, this operation is often called <i>down-heap</i> operation. It is also known as <i>trickle-down, swim-down, heapify-down, or cascade-down</i>
</p>
</div>
</div>
<div id="outline-container-orgfa9b550" class="outline-4">
<h4 id="orgfa9b550"><span class="section-number-4">6.4.3.</span> Up-heapify</h4>
<div class="outline-text-4" id="text-6-4-3">
<p>
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.
<br />
This function runs in \(\theta (log_2n)\) time. The algorithm for this works as follows
</p>
<ol class="org-ol">
<li>Compare the index element to its parent and stop algorithm if it is in correct order.</li>
<li>If not in correct order, swap element with its parent. Repeat till element in correct position or at root position.</li>
</ol>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">up_heapify</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">heap_type</span> <span style="color: #8b4513;">heap</span>, <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">index</span>){
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">parent</span> = (index - 1) / 2;
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">smallest</span> = index;
<span style="color: #a626a4;">if</span>(parent &gt;= 0 &amp;&amp; heap.array[smallest] &gt; heap.array[parent])
smallest = parent;
<span style="color: #a626a4;">if</span>(smallest != index){
swap(heap.array[index], heap.array[smallest]);
up_heapify(heap, smallest);
}
}
</pre>
</div>
<p>
Since we shift element upwards, this operation is often called <i>up-heap</i> operation. It is also known as <i>trickle-up, swim-up, heapify-up, or cascade-up</i>
<br />
<br />
<b>TODO</b> : Maybe up-heapfiy funtion should be made cleaner rather than trying to mirror down-heapify funtion.
</p>
</div>
</div>
<div id="outline-container-orga289df9" class="outline-4">
<h4 id="orga289df9"><span class="section-number-4">6.4.4.</span> Insertion</h4>
<div class="outline-text-4" id="text-6-4-4">
<p>
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
<br />
The code shows example of insertion in a max-heap.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">void</span> <span style="color: #0184bc;">insert_element</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">heap_type</span> <span style="color: #8b4513;">heap</span>, <span style="color: #c18401;">int</span> <span style="color: #8b4513;">element</span>){
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">add element</span>
<span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">element_index</span> = heap.len;
<span style="color: #a626a4;">if</span>(element_index == heap.capacity){
printf(<span style="color: #50a14f;">"Heap reached full capacity"</span>);
<span style="color: #a626a4;">return</span>;
}
heap.array[heap.len++] = element;
up_heapify(heap, heap.len - 1);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org30cb28f" class="outline-4">
<h4 id="org30cb28f"><span class="section-number-4">6.4.5.</span> Deletion or Extraction</h4>
<div class="outline-text-4" id="text-6-4-5">
<p>
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.
<br />
<br />
The code shows example of extraction in max-heap.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">int</span> <span style="color: #0184bc;">extract_element</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">heap_type</span> <span style="color: #8b4513;">heap</span>){
<span style="color: #a626a4;">if</span>(heap.len &lt; 1){
printf(<span style="color: #50a14f;">"No elements in the heap"</span>);
<span style="color: #a626a4;">return</span> -1;
}
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">r</span> = heap.array[0];
heap.array[0] = heap.array[heap.len - 1];
heap.len -= 1;
<span style="color: #0184bc;">down_heapify</span>(heap, 0);
<span style="color: #a626a4;">return</span> r;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-orgf14f6ac" class="outline-4">
<h4 id="orgf14f6ac"><span class="section-number-4">6.4.6.</span> Insert then extract</h4>
<div class="outline-text-4" id="text-6-4-6">
<p>
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.
<br />
<br />
The algorithm for this will work as follows in a max-heap.
</p>
<ol class="org-ol">
<li>Compare whether the item we are trying to push is greater than root of heap.</li>
<li>If item we are pushing is greater, return it.</li>
<li>Else,
<ol class="org-ol">
<li>Replace root element with new item</li>
<li>Apply down-heapify on the root of heap</li>
<li>Return the orignal root heap which we replaced.</li>
</ol></li>
</ol>
<p>
In python, this is implemented by the name of <b><i>heap replace</i></b>.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #c18401;">int</span> <span style="color: #0184bc;">heap_replace</span>(<span style="color: #a626a4;">struct</span> <span style="color: #c18401;">heap_type</span> <span style="color: #8b4513;">heap</span>, <span style="color: #c18401;">int</span> <span style="color: #8b4513;">element</span>){
<span style="color: #a626a4;">if</span>(element &gt; heap.array[0])
<span style="color: #a626a4;">return</span> element;
<span style="color: #c18401;">int</span> <span style="color: #8b4513;">r</span> = heap.array[0];
swap(heap.array[0], element);
down_heapify(heap, 0);
<span style="color: #a626a4;">return</span> r;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org86b6aec" class="outline-4">
<h4 id="org86b6aec"><span class="section-number-4">6.4.7.</span> Searching</h4>
<div class="outline-text-4" id="text-6-4-7">
<p>
Searching for a arbitrary element takes linear time in a heap. We use linear search to search for element in array.
</p>
</div>
</div>
<div id="outline-container-org7e92748" class="outline-4">
<h4 id="org7e92748"><span class="section-number-4">6.4.8.</span> Deleting arbitray element</h4>
<div class="outline-text-4" id="text-6-4-8">
<p>
For a max-heap, deleting an arbitrary element is done as follows
</p>
<ol class="org-ol">
<li>Find the element to delete and get its index \(i\).</li>
<li>swap last element and the element at index \(i\), and decrease the size of heap.</li>
<li>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.</li>
</ol>
</div>
</div>
<div id="outline-container-org88a5120" class="outline-4">
<h4 id="org88a5120"><span class="section-number-4">6.4.9.</span> Decrease and increase keys</h4>
<div class="outline-text-4" id="text-6-4-9">
<p>
TODO : I don't know if it is neccessary to do this operation. It looks simple to implement.
</p>
</div>
</div>
</div>
<div id="outline-container-org7fa13c0" class="outline-3">
<h3 id="org7fa13c0"><span class="section-number-3">6.5.</span> Building a heap from array</h3>
<div class="outline-text-3" id="text-6-5">
<p>
We can convert a normal array into a heap using the down-heapify operation in linear time \(\left( \theta (n) \right)\)
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">array.array[..] contains an array which is not a heap yet</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">this funtion will turn it into a correct heap</span>
<span style="color: #c18401;">void</span> <span style="color: #0184bc;">build_heap</span>(<span style="color: #c18401;">int</span> <span style="color: #8b4513;">array</span>[], <span style="color: #c18401;">size_t</span> <span style="color: #8b4513;">len</span>){
<span style="color: #a626a4;">for</span>(<span style="color: #c18401;">int</span> <span style="color: #8b4513;">i</span> = (len/2) - 1; i &gt;= 0; i--)
down_heapify(array, i);
}
</pre>
</div>
<p>
As we see, for <b><i>zero indexed language</i></b>, the range of for loop is [(len(array)/2) - 1, 0]
<br />
If we are using a <b><i>one indexed language</i></b>, then range of for loop is [len(array)/2, 1]
</p>
</div>
</div>
</div>
<div id="outline-container-orga31eb53" class="outline-2">
<h2 id="orga31eb53"><span class="section-number-2">7.</span> Graphs</h2>
<div class="outline-text-2" id="text-7">
<p>
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.
</p>
</div>
<div id="outline-container-orgfc9e0fa" class="outline-3">
<h3 id="orgfc9e0fa"><span class="section-number-3">7.1.</span> Representing graphs</h3>
<div class="outline-text-3" id="text-7-1">
<p>
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.
<br />
<br />
The two common ways of representing graphs are either using adjacency lists and adjacency matrix. Either can represent both directed and undirected graphs.
</p>
</div>
<div id="outline-container-org29f60cc" class="outline-4">
<h4 id="org29f60cc"><span class="section-number-4">7.1.1.</span> Adjacency List</h4>
<div class="outline-text-4" id="text-7-1-1">
<p>
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.
<br />
Example, if list-0 contains node-3, then node-0 is connected to node-3 by an edge.
</p>
<ul class="org-ul">
<li>For <b>undirected graphs</b> this will simply work by storing all nodes in list who have a shared edge with list node.</li>
<li>For <b>directed graphs</b> we will only add node to list, if edge goes from list node to the stored node.</li>
</ul>
<p>
So in our previous example, if list-0 contains node-3, then the edge goes from 0 to 3 in the directed graph.
<br />
<br />
The space taken by adjacency list representation is \(\theta (V + E)\).
<br />
Since each node represents an edge, it is easy to convert an adjacency representation graph to a <b>weighted graph</b>. 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.
<br />
The adjacency list representation is very robust and can represent various types of graph variants.
</p>
</div>
</div>
<div id="outline-container-org7350965" class="outline-4">
<h4 id="org7350965"><span class="section-number-4">7.1.2.</span> Adjacency Matrix</h4>
<div class="outline-text-4" id="text-7-1-2">
<p>
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.
<br />
<br />
If there is an edge between vertices (x , y), we show it by setting
<br />
matrix[x][y] = true <b><i>or</i></b> matrix[x][y] = 1
<br />
If there is not an edge between vertices (x , y), we set
<br />
matrix[x][y] = false <b><i>or</i></b> matrix [x][y] = 0
</p>
<ul class="org-ul">
<li>For undirected graphs, to show edge (u , v) we have to set both matrix[u][v] and matrix[v][u] to 1.</li>
<li>For directed graphs, to show edge (u , v) which goes from u to v, we only set matrix[u][v] to 1.</li>
</ul>
<p>
The space taken by adjacency matrix is \(\theta (V^2)\).
<br />
For undirected graphs, the matrix will be symmetrical along the diagonal, because matrix will be equal to it's own <b>transpose</b>. So we can save space by only storing half the matrix in memory.
<br />
<br />
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.
<br />
<br />
We can store weighted graphs in adjacency matrix by storing the weights along with the edge information in matrix cells.
</p>
</div>
</div>
</div>
<div id="outline-container-org2779c9b" class="outline-3">
<h3 id="org2779c9b"><span class="section-number-3">7.2.</span> Vertex and edge attributes</h3>
<div class="outline-text-3" id="text-7-2">
<p>
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 (.)
<br />
<br />
For example, the attribute x of v will be denoted as v.x
<br />
Similarly, the attribute x of edge (u , v) will be denoted as (u , v).x
</p>
</div>
</div>
<div id="outline-container-org149b890" class="outline-3">
<h3 id="org149b890"><span class="section-number-3">7.3.</span> Density of graph</h3>
<div class="outline-text-3" id="text-7-3">
<p>
Knowing the density of a graph can help us choose the way in which we represent our graph.
<br />
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)} \]
</p>
<p>
Therefore, maximum density for a graph is 1. The minimum density for a graph is 0.
<br />
Knowing this, we can say graph with low density is a sparse graph and graph with high density is a dense graph.
</p>
</div>
<div id="outline-container-org68298dc" class="outline-4">
<h4 id="org68298dc"><span class="section-number-4">7.3.1.</span> Which representation to use</h4>
<div class="outline-text-4" id="text-7-3-1">
<p>
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.
<br />
Similarly, for directed graph when \(|E|\) is close to \(|V|^2\), we can say graph is dense, else it is sparse.
<br />
<br />
The list representation provides a more compact way to represent graph when the graph is <b>sparse</b>. Whereas matrix representation is better for <b>dense</b> graphs.
<br />
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.
</p>
</div>
</div>
</div>
<div id="outline-container-orgad83141" class="outline-3">
<h3 id="orgad83141"><span class="section-number-3">7.4.</span> Searching Graphs</h3>
<div class="outline-text-3" id="text-7-4">
<p>
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.
<br />
<br />
Searching graphs algorithm can also be used on trees, because trees are also graphs.
</p>
</div>
<div id="outline-container-org091c563" class="outline-4">
<h4 id="org091c563"><span class="section-number-4">7.4.1.</span> Breadth first search</h4>
<div class="outline-text-4" id="text-7-4-1">
<p>
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.
<br />
<br />
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.
<br />
<br />
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)\).
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #0184bc;">BFS</span>(<span style="color: #c18401;">graph_type</span> <span style="color: #8b4513;">graph</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">start</span>){
<span style="color: #c18401;">queue_type</span> <span style="color: #8b4513;">queue</span>;
start.explored = <span style="font-weight: bold; text-decoration: underline;">true</span>;
queue.add(start);
<span style="color: #a626a4;">while</span>(queue.len != 0){
<span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">v</span> = queue.dequeue();
<span style="color: #c18401;">node_list</span> <span style="color: #8b4513;">adjacency_list</span> = grap.adj_list(v);
<span style="color: #a626a4;">while</span>(adjacency_list != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">u</span> = adjacency_list.node;
<span style="color: #a626a4;">if</span>(u.explored == <span style="font-weight: bold; text-decoration: underline;">false</span>){
u.explored = <span style="font-weight: bold; text-decoration: underline;">true</span>;
queue.add(u);
}
adjacency_list = adjacency_list.next;
}
}
}
</pre>
</div>
<ul class="org-ul">
<li><b>Analysis</b></li>
</ul>
<p>
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) \]
</p>
</div>
</div>
<div id="outline-container-orgab43fa4" class="outline-4">
<h4 id="orgab43fa4"><span class="section-number-4">7.4.2.</span> Breadth-first trees for shortest path</h4>
<div class="outline-text-4" id="text-7-4-2">
<p>
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.
<br />
<br />
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.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #0184bc;">BFS_shortest_path</span>(<span style="color: #c18401;">graph_type</span> <span style="color: #8b4513;">graph</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">start</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">end</span>){
<span style="color: #c18401;">queue_type</span> <span style="color: #8b4513;">queue</span>;
start.explored = <span style="font-weight: bold; text-decoration: underline;">true</span>;
start.parent = <span style="font-weight: bold; text-decoration: underline;">NULL</span>; <span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">the start node is root node of tree</span>
queue.add(start);
<span style="color: #a626a4;">while</span>(queue.len != 0){
<span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">v</span> = queue.dequeue();
<span style="color: #c18401;">node_list</span> <span style="color: #8b4513;">adjacency_list</span> = grap.adj_list(v);
<span style="color: #a626a4;">while</span>(adjacency_list != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">u</span> = adjacency_list.node;
<span style="color: #a626a4;">if</span>(u.explored == <span style="font-weight: bold; text-decoration: underline;">false</span>){
u.explored = <span style="font-weight: bold; text-decoration: underline;">true</span>;
u.parent = v; <span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">the parent of u is v</span>
queue.add(u);
<span style="color: #a626a4;">if</span>(u == end) <span style="color: #a626a4;">return</span>; <span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">if we found the end node,</span>
<span style="color: #a0a1a7; font-weight: bold;">// </span><span style="color: #a0a1a7;">we have the path to it.</span>
}
adjacency_list = adjacency_list.next;
}
}
printf(<span style="color: #50a14f;">"end node not in graph"</span>);
}
</pre>
</div>
<p>
In this tree, the path upwards from any given node to start node will be the shortest path to the start node.
<br />
Therefore, we can get the shortest path now as follows
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #0184bc;">print_shortest_path</span>(<span style="color: #c18401;">graph_type</span> <span style="color: #8b4513;">graph</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">start</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">end</span>){
BFS_shortest_path(graph, start, end);
<span style="color: #a626a4;">while</span>(end != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
print_node(end);
end = end.parent;
}
}
</pre>
</div>
<p>
This will print shortest path from end node to start node.
</p>
</div>
</div>
<div id="outline-container-orgcf9333d" class="outline-4">
<h4 id="orgcf9333d"><span class="section-number-4">7.4.3.</span> Depth first search</h4>
<div class="outline-text-4" id="text-7-4-3">
<p>
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.
<br />
<br />
Implementation of DFS is very similar to BFS with two differences. Rather than using a queue, we use a <b>stack</b>. In BFS, the explored nodes are added to the queue, but in DFS we will add unexplored nodes to the stack.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #0184bc;">DFS</span>(<span style="color: #c18401;">graph_type</span> <span style="color: #8b4513;">graph</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">start</span>){
<span style="color: #c18401;">stack_type</span> <span style="color: #8b4513;">stack</span>;
stack.push(start);
<span style="color: #a626a4;">while</span>(stack.len != 0){
<span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">v</span> = stack.pop();
<span style="color: #a626a4;">if</span>(v.explored == <span style="font-weight: bold; text-decoration: underline;">false</span>){
v.explored = <span style="font-weight: bold; text-decoration: underline;">true</span>;
<span style="color: #c18401;">node_list</span> <span style="color: #8b4513;">adjacency_list</span> = graph.adj_list(start);
<span style="color: #a626a4;">while</span>(adjacency_list != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
stack.push(adjacency_list.node);
adjacency_list = adjacency_list.next;
}
}
}
}
</pre>
</div>
<p>
Another way to implement DFS is recursively.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #0184bc;">DFS</span>(<span style="color: #c18401;">graph_type</span> <span style="color: #8b4513;">graph</span>, <span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">node</span>){
node.discovered = <span style="font-weight: bold; text-decoration: underline;">true</span>;
<span style="color: #c18401;">node_list</span> <span style="color: #8b4513;">adjacency_list</span> = graph.adj_list(node);
<span style="color: #a626a4;">while</span>(adjacency_list != <span style="font-weight: bold; text-decoration: underline;">NULL</span>){
<span style="color: #c18401;">node_type</span> <span style="color: #8b4513;">u</span> = adjacency_list.node;
<span style="color: #a626a4;">if</span>(u.discovered == <span style="font-weight: bold; text-decoration: underline;">false</span>)
DFS(graph, u);
adjacency_list = adjacency_list.next;
}
}
</pre>
</div>
<p>
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.
</p>
<ul class="org-ul">
<li><b>Analysis</b></li>
</ul>
<p>
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) \]
</p>
</div>
</div>
<div id="outline-container-org1d56cc6" class="outline-4">
<h4 id="org1d56cc6"><span class="section-number-4">7.4.4.</span> Properties of DFS</h4>
<div class="outline-text-4" id="text-7-4-4">
<p>
DFS is very useful to understand the structure of a graph. To understand the
</p>
</div>
</div>
<div id="outline-container-orgf43e579" class="outline-4">
<h4 id="orgf43e579"><span class="section-number-4">7.4.5.</span> Topological sort using DFS</h4>
</div>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Anmol Nawani</p>
<p class="date">Created: 2023-07-30 Sun 18:20</p>
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>