Data Structures and Algorithms

muigai unaka

Week 3

Sorting

A comparison-based sorting algorithm in which a pair of elements, current and next, is compared and the elements are swapped if they are not in order. This algorithm is not suitable for large data sets as its time complexity is quadratic Ο (n^2)

Bubble Sort

Say you are sorting a line of 5 people by height from shortest to tallest...

  • Start with them lined up in any order
  • Go to the first two people and swap them if the second person is taller than the first
  • Compare the 2nd person with the person after them, repeat until at end of line
  • Repeat until you have gone through the line 5 times

Bubble Sort

Example

/*
 * ITERATIVE BUBBLE SORT IMPLEMENTATION
 * @params {Array} an array of numbers
 * @return {Array} a sorted array of numbers
 * @complexity time: O(n^2), space: O(1)
 */
const bubbleSort = (arr = [3, 2, 4, 5]) => {
  let len = arr.length;
  
  for (let i = 1; i < len; i++) {
    // bubble up the numbers until the last element is in correct place
    for (let j = 0; j < len - 1; j++) {
      let current = arr[j];
      let next = arr[j + 1];
      // Compare current item with next. If current item is greater than next item, swap
      if (current > next) {
        // swap elemenets in place
        arr[j] = next;
        arr[j + 1] = current;
      }
    }
  }
  return arr;
}
bubbleSort([7, 5, 2, 4, 3, 9]); //[2, 3, 4, 5, 7, 9]
bubbleSort([9, 7, 5, 4, 3, 1]); //[1, 3, 4, 5, 7, 9]
bubbleSort([1, 2, 3, 4, 5, 6]); //[1, 2, 3, 4, 5, 6]

Bubble Sort

BubbleSort runs in quadratic time and takes up constant space. This is far too inefficient. We can do better. . .

Quick sort is a divide-and-conquer algorithm. You start off by choosing one element as a pivot element and partitioning the array around it such that: Left side of pivot contains all the elements that are less than the pivot element and Right side contains all elements greater than the pivot.

Quick Sort

Say you are sorting a line of 5 people by height from shortest to tallest...

  • Start with them lined up in any order
  • Pick a random person in line to use as your pivot.
  • Anyone shorter than your pivot goes to their left, anyone taller goes to their right
  • Combine everyone then repeat these steps on the people to the left and the right of the original pivot

Quick Sort

Example

/* 
 * RECURSIVE QUICKSORT IMPLEMENTATION
 * @params {Array} arr is an array of numbers
 * @returns {Array} an array of sorted numbers
 * @complexity time: O(n^2), space: O(log n)
 */
const quicksort = (arr) => {
    if (arr.length < 2) return arr;
    // select pivot index at middle of array (or at random)
    let pivot = Math.floor((arr.length - 1) / 2);
    // store element from the array at that pivot index
    let val = arr[pivot];
    // array to hold elements less than pivot and one for elements greater than pivot
    let lesser = [], greater = [];
    // remove the pivot from the array so it is not compared
    arr.splice(pivot, 1)
    // iterate through the array to partition it into 2 sub arrays
    for (let item of arr) {
        if (item < val) {
            lesser.push(item)
        } else {
            greater.push(item)
        }
    }
	// recurse on the elements that are less/greater than the pivot, 
	// and place the pivot in between
    return [
        ...quicksort(lesser), val, ...quicksort(greater)
    ];
}

quicksort([2, 45, 1, 24, 5325, 6, 4]) 
// [1,2,4,6,24,45,5325]

Quick Sort

Quicksort runs in quadratic time [O(n^2)] in it's worst case but it's average case runs in logarithmic time [O(log n)].

Merge Sort

Merge sort is a divide and conquer algorithm. It divides the bigger problem into smaller problems, conquers (or solves) them and then combines each of the solutions to the small problems in order to solve the bigger problem that we started out with.

/*
 * RECURSIVE MERGE SORT IMPLEMENTATION
 * @params {Array} an array of numbers
 * @return {Array} a sorted array of numbers
 * @complexity time: O(n*log n), space: O(n)
 */ 
function merge_sort(arr) {
  // BASE CASE: if array only has one item, it's sorted, return it
  if (arr.length === 1) { return arr; }
  // find midpoint of array, use it to divide
  const center = Math.floor(arr.length / 2);
  // all the elements to the left of arr[center]
  const left = arr.slice(0, center);
  // all the elements to the right of arr[center]
  const right = arr.slice(center);
  // call merge helper to merge the sorted arrays
  return merge_helper(merge_sort(left), merge_sort(right));
}

function merge_helper(left, right) {
  // linear space complexity
  const results = [];
  // iterate through left and right
  while (left.length && right.length) {
    if (left[0] < right[0]) {
      results.push(left.shift());
    } else {
      results.push(right.shift());
    }
  }
  // all elements sorted, and either left or right has been emptied
  return [...results, ...left, ...right];
}

Many Ways to Sort

There are many ways to go about sorting elements from a collection. The ones worth learning are:

  • Quicksort ( O (n^2) )
  • Heap Sort ( O(n log(n)) )
  • Mergesort ( O(n log(n)) )
  • Bucket Sort ( O (n^2) )
  • Radix Sort ( O(nk) )

асуултууд?

Divide and Conquer

Divide/Break

This step involves breaking the problem into smaller sub-problems. Sub-problems should represent a part of the original problem. This step generally takes a recursive approach to divide the problem until no sub-problem is further divisible. At this stage, sub-problems become atomic in nature but still represent some part of the actual problem.

Conquer/Solve

This step receives a lot of smaller sub-problems to be solved. Generally, at this level, the problems are considered 'solved' on their own.

Merge/Combine

When the smaller sub-problems are solved, this stage recursively combines them until they formulate a solution of the original problem. This algorithmic approach works recursively and conquer & merge steps works so close that they appear as one.

Divide and Conquer

Divide and conquer is the basis for a few common algorithms:

  • Quicksort
  • Mergesort
  • Binary Search
  • Strassen's Matrix Multiplication
  • Closest Pair (points)

Binary Search

The most popular search algorithms; it finds the position of a target value within a sorted array by repeatedly dividing the search interval in half

Say you are given a list of all of the names in the world sorted alphabetically and you want to find the position of a specific name

  • Start off by picking the name at the middle of the list and compare it to the name you are searching for
  • If that name is before your name in the alphabet, ignore the names that come before it; else ignore the names after it
  • Your list is now half the size it was; select a new middle and repeat the above steps

Binary Search

Example

/*
 * ITERATIVE BINARY SEARCH IMPLEMENTATION
 * @description Find the position of a passed in value in a sorted collection of data
 * @params {Array} a sorted array of numbers
 * @params {Number} the number to search for 
 * @returns the index of the found value, -1 if not found
 * @complexity time: O(log n), space: O(1)
 * @variants Must operate on a sorted collection
 */
const binarySearchIterative = (arr, numToFind) => {
  // set low and high bounds
  let low = 0;
  let high = arr.length - 1;
  let mid;
  while (low <= high) {
    // find midppint of array
    mid = Math.floor(low + ((high - low) / 2));
    if (numToFind == arr[mid]) {
      return mid; // SUCCESS! found value at this index
    } else if (numToFind < arr[mid]) {
      // set new high since the value at the 
      // most recent midpoint is greater than what we're searching for
      high = mid - 1;
    } else {
      // set new low since the value at the 
      // most recent midpoint is less than what we're searching for
      low = mid + 1;
    }
  }
  // numToFind is not found in the array so let's return -1
  return -1;
}

binarySearchIterative([1, 2, 3, 4, 5, 6], 4) // 3

Perguntas?

Data Structures and Algorithms Week 3

By Muigai Unaka

Data Structures and Algorithms Week 3

Data Structures and Algorithms week 3 at Resilient Coders. Sorting Algorithms and Binary Search

  • 391