PERSONAL - Data Structures and Algorithms

Complexity

Different Cases

Landau-Notation

Properties of Big O Notation

Time Complexity

Expected Values

Amoritzed Analysis (Accounting Method)

Hashing

5cd305eeaab19318a6d99d7ca568539d.png

// implementing a hash table with hash function 
// only for dynamic dictionaries
void insert(Object e){
    T[h(key(e))] = e;
}

// only for dynamic dictionaries
void remove(Key k){
    T[h(k)] = null;
}

// for static and dynamic dictionaries
Object find(Key k){
    return T[h(k)];
}
// implementing a hash table with hash function 
// only for dynamic dictionaries
void insert(Object e){
    T[h(key(e))] = e;
}

// only for dynamic dictionaries
void remove(Key k){
    T[h(k)] = null;
}

// for static and dynamic dictionaries
Object find(Key k){
    return T[h(k)];
}

Hashing with Chaining

3be67d1670ba8377282d7430e77083d4.png

// init. array of linked lists
List<Object>[m] T;

// insert into linkedlist inside array
void insert(Object e){
    T[h(key(e))].insert(e);
}

// remove from linkedlist inside aray
void remove(Key k){
    T[h(k)].remove(k);
}

// find in linkedlist inside array
Object find(Key k){
    return T[h(k)].find(k);
}
// init. array of linked lists
List<Object>[m] T;

// insert into linkedlist inside array
void insert(Object e){
    T[h(key(e))].insert(e);
}

// remove from linkedlist inside aray
void remove(Key k){
    T[h(k)].remove(k);
}

// find in linkedlist inside array
Object find(Key k){
    return T[h(k)].find(k);
}

Universal Hashing

Perfect Hashing

da71d6528ec50d1e1b63e0fa57193e77.png

Linear Probing

faf079a108a864068fc42f559e2001e9.png

// insert into next available spot if ideal spot taken
void insert(Object e) {
    i = h(key(e));
    while (T[i] != null && T[i] != e)
        i = (i + 1) % m;
    T[i] = e;
}

// find object using linear search
Object find(Key k) {
    i = h(k);
    while (T[i] != null && key(T[i]) != k)
        i = (i+1) % m;
    return T[i];
}
// insert into next available spot if ideal spot taken
void insert(Object e) {
    i = h(key(e));
    while (T[i] != null && T[i] != e)
        i = (i + 1) % m;
    T[i] = e;
}

// find object using linear search
Object find(Key k) {
    i = h(k);
    while (T[i] != null && key(T[i]) != k)
        i = (i+1) % m;
    return T[i];
}

Sorting Algorithms and their Complexities

SelectionSort

void selectionSort(Object[] a, int n) {
    for (int i = 0; i < n; i++) {
        int k = i;
        
        // find smallest element from unsorted sublist
        for (int j = i + 1; j < n; j++)
            if (a[j] < a[k]) 
                k = j;
        
        // swap with leftmost unsorted element
        swap(a, i, k);
    }
}
void selectionSort(Object[] a, int n) {
    for (int i = 0; i < n; i++) {
        int k = i;
        
        // find smallest element from unsorted sublist
        for (int j = i + 1; j < n; j++)
            if (a[j] < a[k]) 
                k = j;
        
        // swap with leftmost unsorted element
        swap(a, i, k);
    }
}
Sorted Unsorted Least (unsorted)
() (11,25,12,22,64) 11
(11) (25,12,22,64) 12
(11,12) (25,22,64) 22
(11,12,22) (25,64) 25
(11,12,22,25) (64) 64
(11,12,22,25,64) ()

InsertionSort

void insertionSort(Object[] a, int n) {
    for (int i = 1; i < n; i++)
        // iterate backwards and insert at correct position
        for (int j = i − 1; j >= 0; j−−)
            if (a[j] > a[j + 1])
                swap(a, j, j + 1);
            else 
                break;
}
void insertionSort(Object[] a, int n) {
    for (int i = 1; i < n; i++)
        // iterate backwards and insert at correct position
        for (int j = i − 1; j >= 0; j−−)
            if (a[j] > a[j + 1])
                swap(a, j, j + 1);
            else 
                break;
}

MergeSort

QuickSort

void quickSort(int[] a, int l, int r) {
    if (l < r) {
        int p = a[r]; // choose rightmost element as pivot
        int i = l - 1; // left index
        int j = r; // right index
        do {
            // move left index
            do {
                i++;
            } while (a[i] < p);
            
            // move right index
            do {
                j--;
            } while (j >= l && a[j] > p);
            
            // swap elements if possible
            if (i < j)
                swap(a, i, j);
        } while (i < j);
        
        // at end of iteration, move pivot into correct position
        swap (a, i, r);
        // do quicksort for lower and greater subarrays
        quickSort(a, l, i - 1);
        quickSort(a, i + 1, r);
    }
}
void quickSort(int[] a, int l, int r) {
    if (l < r) {
        int p = a[r]; // choose rightmost element as pivot
        int i = l - 1; // left index
        int j = r; // right index
        do {
            // move left index
            do {
                i++;
            } while (a[i] < p);
            
            // move right index
            do {
                j--;
            } while (j >= l && a[j] > p);
            
            // swap elements if possible
            if (i < j)
                swap(a, i, j);
        } while (i < j);
        
        // at end of iteration, move pivot into correct position
        swap (a, i, r);
        // do quicksort for lower and greater subarrays
        quickSort(a, l, i - 1);
        quickSort(a, i + 1, r);
    }
}

RadixSort

HeapSort

HeapSort(Object[] H, int n) {
    // build min-heap from array
    build(H[0], ... , H[n − 1]);
    // deleteMin until heap empty
    for (i = n − 1; i >= 1; i−−) {
        swap(H, 0, i);
        H.length−−;
        siftDown(H, 0);
    }
}
HeapSort(Object[] H, int n) {
    // build min-heap from array
    build(H[0], ... , H[n − 1]);
    // deleteMin until heap empty
    for (i = n − 1; i >= 1; i−−) {
        swap(H, 0, i);
        H.length−−;
        siftDown(H, 0);
    }
}

Summary of Sorting Algorithm Complexities

Algorithm Best Case Average Case Worst Case Space Complexity
SelectionSort O(n^2) O ( n 2 ) O(n^2) O(n^2) O ( n 2 ) O(n^2) O(n^2) O ( n 2 ) O(n^2) O(1) O ( 1 ) O(1)
InsertionSort O(n) O ( n ) O(n) O(n^2) O ( n 2 ) O(n^2) O(n^2) O ( n 2 ) O(n^2) O(1) O ( 1 ) O(1)
MergeSort O(n \log n) O ( n log n ) O(n \log n) O(n \log n) O ( n log n ) O(n \log n) O(n \log n) O ( n log n ) O(n \log n) O(n) O ( n ) O(n)
QuickSort O(n \log n) O ( n log n ) O(n \log n) O(n \log n) O ( n log n ) O(n \log n) O(n^2) O ( n 2 ) O(n^2) O(n) O ( n ) O(n)
RadixSort O(nk) O ( n k ) O(nk) O(nk) O ( n k ) O(nk) O(nk) O ( n k ) O(nk) O(n + k) O ( n + k ) O(n + k)
HeapSort O(n \log n) O ( n log n ) O(n \log n) O(n \log n) O ( n log n ) O(n \log n) O(n \log n) O ( n log n ) O(n \log n) O(1) O ( 1 ) O(1)

Selection using QuickSelect

Recursion Analysis and Master Theorem

Data Structures

Priority Queues

Operation unsorted list sorted list
build() O(n) O ( n ) O(n) O(n \log n) O ( n log n ) O(n \log n)
insert() O(1) O ( 1 ) O(1) O(n) O ( n ) O(n)
min() O(n) O ( n ) O(n) O(1) O ( 1 ) O(1)
deleteMin() O(n) O ( n ) O(n) O(1) O ( 1 ) O(1)

Binary Tree

Binary Heaps

// pseudocode
Element deleteMin(Heap<Element> H) {
    Element min = root of H;
    replace root of H with last element of H;
    siftDown(H, root of H);
    return min;
}
// pseudocode
Element deleteMin(Heap<Element> H) {
    Element min = root of H;
    replace root of H with last element of H;
    siftDown(H, root of H);
    return min;
}
// pseudocode
siftDown(Heap<Element> H, Node v) {
    // cannot sift down if node is leaf
    if (isLeaf(v)) return;
    
    Node m;
    // choose direction
    if (key(v.left) < key(v.right)){
        m = v.left;
    }
    else {
        m = v.right;
    }
    
    // restore heap invariant or quit
    if (key(m) < key(v)) {
        swap content of m and v;
        siftDown(H, m);
    }
}
// pseudocode
siftDown(Heap<Element> H, Node v) {
    // cannot sift down if node is leaf
    if (isLeaf(v)) return;
    
    Node m;
    // choose direction
    if (key(v.left) < key(v.right)){
        m = v.left;
    }
    else {
        m = v.right;
    }
    
    // restore heap invariant or quit
    if (key(m) < key(v)) {
        swap content of m and v;
        siftDown(H, m);
    }
}
// pseudocode
insert(Heap<Element> H, Element e) {
    Node v = insert e at end of H;
    siftUp(H, v);
}
// pseudocode
insert(Heap<Element> H, Element e) {
    Node v = insert e at end of H;
    siftUp(H, v);
}
// pseudocode
siftUp(Heap<Element> H, Node v) {
    while (v is not root && key(v.parent) > key(v)) {
        swap content of v and v.parent;
        v = v.parent;
    }
}
// pseudocode
siftUp(Heap<Element> H, Node v) {
    while (v is not root && key(v.parent) > key(v)) {
        swap content of v and v.parent;
        v = v.parent;
    }
}
decreaseKey(Heap<Element> H, Node v, int k) {
    if (k > key(v)) error();
    key(v) = k;
    siftUp(H, v);
}
decreaseKey(Heap<Element> H, Node v, int k) {
    if (k > key(v)) error();
    key(v) = k;
    siftUp(H, v);
}
increaseKey(Heap<Element> H, Node v, int k) {
    if (k < key(v)) error();
    key(v) = k;
    siftDown(H, v);
}
increaseKey(Heap<Element> H, Node v, int k) {
    if (k < key(v)) error();
    key(v) = k;
    siftDown(H, v);
}

Binary Heap example using Max-Heap

Binomial Trees

7c311d6e3c23cf14a15333d9050fdd35.png

Binomial Heaps

Binary Search Tree

5a117cf9a675301c1a7688dd95218557.png

AVL-Trees

Summary: AVL-Tree Rotations

Source: https://www.geeksforgeeks.org/insertion-in-an-avl-tree/
T1, T2, T3 and T4 are subtrees.
S - single, D - double

S: RIGHT ROTATE
         z                                      y 
        / \                                   /   \
       y   T4      Right Rotate (z)          x      z
      / \          - - - - - - - - ->      /  \    /  \ 
     x   T3                               T1  T2  T3  T4
    / \
  T1   T2
  
D: LEFT-RIGHT ROTATE
     z                               z                           x
    / \                            /   \                        /  \ 
   y   T4  Left Rotate (y)        x    T4  Right Rotate(z)    y      z
  / \      - - - - - - - - ->    /  \      - - - - - - - ->  / \    / \
T1   x                          y    T3                    T1  T2 T3  T4
    / \                        / \
  T2   T3                    T1   T2
  
S: LEFT ROTATE
  z                                y
 /  \                            /   \ 
T1   y     Left Rotate(z)       z      x
    /  \   - - - - - - - ->    / \    / \
   T2   x                     T1  T2 T3  T4
       / \
     T3  T4
     
D: RIGHT-LEFT ROTATE
   z                            z                            x
  / \                          / \                          /  \ 
T1   y   Right Rotate (y)    T1   x      Left Rotate(z)   z      y
    / \  - - - - - - - - ->     /  \   - - - - - - - ->  / \    / \
   x   T4                      T2   y                  T1  T2  T3  T4
  / \                              /  \
T2   T3                          T3   T4
Source: https://www.geeksforgeeks.org/insertion-in-an-avl-tree/
T1, T2, T3 and T4 are subtrees.
S - single, D - double

S: RIGHT ROTATE
         z                                      y 
        / \                                   /   \
       y   T4      Right Rotate (z)          x      z
      / \          - - - - - - - - ->      /  \    /  \ 
     x   T3                               T1  T2  T3  T4
    / \
  T1   T2
  
D: LEFT-RIGHT ROTATE
     z                               z                           x
    / \                            /   \                        /  \ 
   y   T4  Left Rotate (y)        x    T4  Right Rotate(z)    y      z
  / \      - - - - - - - - ->    /  \      - - - - - - - ->  / \    / \
T1   x                          y    T3                    T1  T2 T3  T4
    / \                        / \
  T2   T3                    T1   T2
  
S: LEFT ROTATE
  z                                y
 /  \                            /   \ 
T1   y     Left Rotate(z)       z      x
    /  \   - - - - - - - ->    / \    / \
   T2   x                     T1  T2 T3  T4
       / \
     T3  T4
     
D: RIGHT-LEFT ROTATE
   z                            z                            x
  / \                          / \                          /  \ 
T1   y   Right Rotate (y)    T1   x      Left Rotate(z)   z      y
    / \  - - - - - - - - ->     /  \   - - - - - - - ->  / \    / \
   x   T4                      T2   y                  T1  T2  T3  T4
  / \                              /  \
T2   T3                          T3   T4

(a,b)-Trees

Graphs

5289ceb9bcdff3340e1b8536ecb6f31a.png

Type of Edge dfsNum[v] < dfsNum[w] finishNum[v] > finishNum[w]
Root Edge yes yes
Forwards Edge yes yes
Backwards Edge no no
Rest no yes

Connectivity

Shortest Paths (SSSP)

DAG - Topological Sorting

L ← Empty list that will contain the sorted elements
S ← FIFO-Queue of all nodes with no incoming edge

while S is not empty do
    remove a node n from S
    add n to L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into S

if graph has edges then
    return error   (graph has at least one cycle)
else 
    return L   (a topologically sorted order)
L ← Empty list that will contain the sorted elements
S ← FIFO-Queue of all nodes with no incoming edge

while S is not empty do
    remove a node n from S
    add n to L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into S

if graph has edges then
    return error   (graph has at least one cycle)
else 
    return L   (a topologically sorted order)

Dijkstra’s Algorithm

Dijkstra_Animation.gif

Bellman-Ford[8]

Bellman–Ford_algorithm_example.gif

Shortest Paths (APSP)

Floyd-Warshall’s Algorithm

let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity)
for each edge (u, v) do
    dist[u][v] ← w(u, v)
for each vertex v do
    dist[v][v] ← 0
for k from 1 to |V|
    for i from 1 to |V|
        for j from 1 to |V|
            if dist[i][j] > dist[i][k] + dist[k][j] 
                dist[i][j] ← dist[i][k] + dist[k][j]
            end if
let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity)
for each edge (u, v) do
    dist[u][v] ← w(u, v)
for each vertex v do
    dist[v][v] ← 0
for k from 1 to |V|
    for i from 1 to |V|
        for j from 1 to |V|
            if dist[i][j] > dist[i][k] + dist[k][j] 
                dist[i][j] ← dist[i][k] + dist[k][j]
            end if

4526c4cee06e3b8fea84f08d89de5ccd.png

Johnson’s Algorithm

Minimum Spanning Trees


  1. source: “https://commons.wikimedia.org/wiki/File:Heapsort-example.gif”, Swfung8 on Wikimedia, 19.04.2011, licensed under CC BY-SA 3.0, no changes made ↩︎

  2. source: “https://en.wikipedia.org/wiki/File:Binomial_Trees.svg”, Lemontea (?) on Wikipedia, 19.03.2006, licensed under CC BY-SA 3.0, no changes made ↩︎

  3. source: https://en.wikipedia.org/wiki/File:Binomial_heap_merge1.svg, Lemontea on Wikipedia, 15.05.2006, licensed under CC BY-SA 3.0, no changes made ↩︎

  4. source: https://en.wikipedia.org/wiki/File:Binomial_heap_merge2.svg, Lemontea on Wikipedia, 15.05.2006, licensed under CC BY-SA 3.0, no changes made ↩︎

  5. source: https://en.wikipedia.org/wiki/File:AVL-tree-wBalance_K.svg, Nomen4Omen on Wikipedia, 01.06.2016, licensed under CC BY-SA 4.0, no changes made ↩︎

  6. source: https://en.wikipedia.org/wiki/File:Breadth-first-tree.svg, Alexander Drichel on Wikipedia, 28.03.2008, licensed under CC BY 3.0, no changes made ↩︎

  7. source: https://commons.wikimedia.org/wiki/File:Depth-first-tree.svg, Alexander Drichel on Wikimedia, 28.03.2008, licensed under CC BY 3.0, no changes made ↩︎

  8. source: https://commons.wikimedia.org/wiki/File:Bellman–Ford_algorithm_example.gif, Michel Bakni, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein (2001) Introduction to Algorithms (2nd ed.), p. 589 ISBN: 9780262032933, 01.05.2021, licensed under CC BY-SA 4.0, no changes made ↩︎

  9. source: https://en.wikipedia.org/wiki/File:KruskalDemo.gif, Shiyu Ji on Wikipedia, 24.12.2016, licensed under CC BY-SA 4.0, no changes made ↩︎

  10. source: https://en.wikipedia.org/wiki/File:PrimAlgDemo.gif, Shiyu Ji on Wikipedia, 24.12.2016, licensed under CC BY-SA 4.0, no changes made ↩︎


Summary by Flavius Schmidt, ge83pux, 2023.
https://home.in.tum.de/~scfl/