CS245 - Comp Sci II Chapter 10

Chapter 10 - Process III: Algorithms

OBJECTIVES



10.1 Searching for an element in a list


Finding the Smallest Element


int FindMin(IntArray arr, int start, int end)
{
      int min = arr[start];
      int where = start;

      for (int j = start + 1; j <= end; j++)
     {
            if (arr[j] < min)
           {
                min = arr[j];
                where = j;
           }
     }
     return where;
}


Finding a Particular Element (I)



int Find(IntArray arr, int match, int end)
{
      for (int j = 0; j <= end; j++)
           if (arr[j] == match)
                return j;
      return -1;
}


10.2 Divide and Conquer: Finding a Particular Element (II)




int BinSearch (SortedArray arr, int match, int start, int end)
{
     if (start == end)
          return start;
     else
     {
          int middle = (start + end) / 2;
          if (match < arr[middle])
              return BinSearch(arr, match, start, middle-1);
          else if (match > arr[middle])
              return BinSearch(arr, match, middle+1, end);
          else
              return middle;
      }
}


Recursion


algorithms ­ finite sequence of clear instructions that can be performed in a finite length of time

recursive algorithm ­ algorithm which moves ahead by applying itself to a smaller part of the problem

recursive function - function that calls itself
Recursive Functions must have:

1) an exit case (trivial case)
2) one or more recursive cases, in which the problem is reduced to a simpler problem

ex. find N!

Binomial Theorem & Combinations
C(n,k) = C(n­1, k) + C(n­1, k­1)
= 1 if n = k
= 1 if k = 1

Towers of Hanoi



10.3 Safer Arrays: The IntArray Class
//­­­­­­­­­­
INTARRAY.H ­­­­­­­­­­

// An array of integers, with bounds­checking and careful memory management.

#include <iostream.h>

class IntArray
{
 friend ostream& operator<< (ostream& os, const IntArray& a);
public:
           IntArray();   // Construct a 10­element IntArray of zeros
           IntArray(int n);   // Construct a zero IntArray of size n
           IntArray(const IntArray& a); // Copy constructor
          ~IntArray() {delete data;}; // inline function to delete the array of data

          Length() {return (upper + 1);}; // inline function which returns actual length of array

           int& operator[] (int I) const;
           IntArray& operator= (const IntArray& a);

private:
          int upper;   // the upper bound on array indices
          int* data;   // ptr to the array elements (indices 0 .. upper)
};

The copy constructor for an object is invoked:

1) an object is defined to have the value of another object of the same type
2) an object is passed to a function by value
3) an object is returned by a function

ex.
 IntArray ZeroTail(IntArray arr, int end)  // 2 here
 {
  IntArray newArray = arr;                            // 1 here
  for (int j = end; j < Length(arr); j++)
          NewArray[j] = 0;
  return newArray;                                       // 3 here
 }

The copy constructor for a type TypeName is declared with a reference argument:

TypeName (const TypeName&);
If you design a class with pointers in its member data, it is always a good idea to provide the class with its own copy constructor, assignment operator, and destructor.

Defining Safe Arrays


//­­­­­­­­­­ INTARRAY.CPP ­­­­­­­­­­
#include <iostream.h> // for cerr
#include <stdlib.h> // for exit
#include "INTARRAY.H"
ostream& operator<< (ostream& os, const IntArray& a)
{
for (int I = 0; I <= a.upper; I++)
os << a.data[i] << '\t';
return os;
}


IntArray::IntArray()
// Construct a 10­element IntArray of zeros.
{
upper = 9;
data = new int[upper + 1];
if (data == 0)
{
cerr << "Out of memory in IntArray()" << endl;
exit(1);
}
else
for (int I = 0; I < 10; I++)
data[i] = 0;
}

IntArray::IntArray(int n)
// Construct a zero IntArray of size n.
{
if (n <= 0)
{
cerr << "Illegal size argument (" << n << ") in IntArray(int n)" << endl;
exit(1);
}
else
{
upper = n ­ 1;
data = new int[n];
if (data == 0)
{
cerr << "Out of memory in IntArray()" << endl;
exit(1);
}
else
for (int I = 0; I < n; I++)
data[i] = 0;
}
}

IntArray::IntArray(const IntArray& a)
// Copy constructor
{
upper = a.upper;
data = new int[upper + 1];
if (data == 0)
{
cerr << "Out of memory in IntArray()" << endl;
exit(1);
}
else
for (int I = 0; I <= upper; I++)
data[i] = a.data[i];
}

int& IntArray::operator[] (int I) const
// overload of subscript operator
{
if ((I < 0) || (I > upper))
{
cerr << "Illegal array index [" << I << ']' << endl;
exit(1);
}
return (data[i]);
}

IntArray& IntArray::operator= (const IntArray& a)
// Assign one array to another
{
int u = ((a.upper < upper) ? a.upper : upper);

if (a.upper != upper)
cerr << "Size mismatch: (" << upper << ") = (" << a.upper << ')' << endl;
for (int I = 0; I <= u; I++)
data[i] = a.data[i];
return *this;
}

10.4 Sorting


void SelectionSort(IntArray& arr, int start, int end)
{
int pos;
for (j = start; j < end; j++)
{
pos = FindMin(arr, j, end);
Swap(arr[j], arr[pos]);
}
}

10.5 Analysis of Algorithms


Selection Sort: n-j+1elements inspected each time FindMin is called --
n + (n-1) + ... + 2 + 1 = (n+1)(n/2) ~ n2 inspections

Big O

Efficiency


time vs space size of data
initial arrangement of data language used
generated machine code speed of computer


Definition The dominant segment of a program is that collection of steps that consume the most time (measured by # of times they are executed). The dominant segment often occurs within the innermost loop and/or the most deeply nested calling level for a method.

Definition The complexity of an algorithm is the number of times the dominant operation in the dominant segment is performed

Definition The worst-case complexity of an algorithm is the maximum number of times the dominant operation can be performed. the average-case complexity is the average number of times the dominant operation in the dominant segment would be performed for all possible arrangements of the input data. The best-case complexity is the minimum number of times the dominant operation in the dominant segment can be performed.

Algorithm Growth Rates


growth rate ­ part of formula that varies with problem size
O(1) ­ constant; O(log(N)) ­ logarithmetic; O(N) ­ linear;
O(Nlog(N)); O(N2) ­ quadratic

Estimating the Growth Rate of an Algorithm


(Big O of inner steps * number of loops)
        for (OuterCounter = 1; OuterCounter <=  N; OuterCounter++)
           for (InnerCounter = 1; InnerCounter <= OuterCounter; InnerCounter++)

Multiplicatively controlled loop


      Control = 1;
      while (Control <= N) 
 {
                 :                       O(log(N))
         Control := 2 * Control
 }


Some Examples of Performance Prediction


Factorial O(N)
Reverse of a String O(N * O(TextConcatenate)
Permuations of a set O(N!)
Recursive binary search O(log(N))
Recursive merge/sort O(N log(N))


MAINTAINING A DYNAMIC TABLE


phone list table ­ key part & value part

ADT ­ Create, Update, Search, Delete, Report

Unordered Array vs. Ordered Array

UNORDERED ORDERED
Create O(1) O(1)
Update O(1) O(N)
Search O(N) O(Log(N))
Delete O(N) O(N)
Report O(N Log(N)) O(N)

10.6 Faster Sorting



void QuickSort (IntArray& arr, int start, int end)
{
      if (start < end)
      {
           int split = Partition(arr, start, end);
          QuickSort(arr, start, split);
          QuickSort(arr, split+1, end);
       }
}


int Partition (IntArray& arr, int start, int end)
{
      int top = end + 1;
      int bottom = start -1;
      int pivot = arr[start];
      while (top > bottom)
      {
          do 
              { bottom++; }
          while (arr[bottom] < pivot);
          do
              { top--;  }
          while (arr[top] > pivot);
          Swap(arr[top], arr[bottom]);
      }
      Swap(arr[top], arr[bottom]);
      return top;
}


Recursive MergeSort
        IF Size(List) > 1 
           Split(List, first half, second half)
           MergeSort(first half of List)
           MergeSort(second half of List)
           Merge(two halves of List)


Empirical Evaluation of Sorting Algorithms (100 Integers)


Sorting Algorithm Run Time - List in Random Order Run Time - List in Ascending Order
Selection3.0 3.1
Insertion2.4 0.0
Shell0.8 0.4
Merge4.0 3.9
Quick0.6 0.3
Heap1.4 1.6

Exercises

pp. 355-356: #2, #6, #14