Queues, Algorithm Efficiency

Réussis tes devoirs et examens dès maintenant avec Quizwiz!

4.6 Lab: Queues 4: main.cpp

#include <iostream> #include <string> #include "QueueADT.h" void printData(QueueADT<string>, QueueADT<double>); using namespace std; int main() { QueueADT<string> queName; QueueADT<double> queUnits; string name; double numUnits; cin >> name; while (name.compare("#") != 0){ queName.push(name); cin >> name; } int unitLen = queUnits.getLength(); int nameLen = queName.getLength(); if (nameLen == 0) cout << "Empty Queue!" << endl; else { cin >> numUnits; char ch; while (ch != '\n') { queUnits.push(numUnits); cin >> numUnits; ch = cin.get(); } queUnits.push(numUnits); cout << nameLen << " " << unitLen << endl; printData(queName, queUnits); } return 0; } void printData(QueueADT<string> names, QueueADT<double> units) { int nameLen = names.getLength(); string firstName = names.peek(); double lastUnits = units.peekRear(); for (int i = 0; i < nameLen; i++) { cout << names.pop() << " " << units.pop() << endl; } cout << firstName << endl; cout << lastUnits; } /* Queue ADT You have already created and tested a queue class for strings. Now you have to convert it into templates, so it would work with any data type. To demonstrate the QueueADT class, create two queues: the first queue contains the names of the students enrolled in CIS 22C the second queue contains the number of units each student is taking this quarter Write code in main to test these functions. Write a loop to enter an unknown number of names (assume one word strings). The loop stops when you enter #. As you are entering names, they are to be inserted into the first queue. To test the getLength function display the number of values in both queues, then write another loop to enter the number of units (double) into a parallel queue. Display the two queues in parallel. On the last two lines display the front element in the first queue and the rear element in the second queue respectively. Ex.: If the user enters Ann Tim Jamie Bob # for the first queue and 9 4.5 15 13.5 for the second queue, the output should be: 4 0 Ann 9 Tim 4.5 Jamie 15 Bob 13.5 Ann 13.5 Ex.: If the user enters # the output should be: Empty queue!

4.3 Lab: Queues 1: We wrote getLength(), isEmpty(), peek(), peekRear(), and loop and conditions in main(); given push.

#include <iostream> #include <string> using namespace std; class Queue_str { private: // Structure for the stack nodes struct QueueNode { string value; // Value in the node QueueNode *next; // Pointer to next node }; QueueNode *front; // Pointer to the first node QueueNode *rear; // Pointer to the last node int length; // Number of nodes in the queue public: Queue_str(){ front = rear = NULL; length = 0; } //Constructor //~Queue_str(); // Destructor // Queue operations bool isEmpty() { return length == 0; } bool push(string); // string pop(); string peek() { return front->value; } string peekRear() { return rear->value; } int getLength() { return length; } }; /**~*~* Member function push: inserts the argument into the queue *~**/ bool Queue_str::push(string item) { QueueNode *newNode; // Pointer to a new node // Allocate a new node and store num there. newNode = new QueueNode; if (!newNode) return false; newNode->value = item; newNode->next = NULL; // Update links and counter if (!front) // front is NULL: empty queue front = newNode; else rear->next = newNode; rear = newNode; length++; return true; } int main() { Queue_str que; string item; cin >> item; while (item != "#") { que.push(item); cin >> item; } cout << que.getLength() << endl; if (!que.isEmpty()) { cout << que.peek() << endl << que.peekRear() << endl; } else { cout << "Empty Queue!" << endl; } return 0; }

4.5 Lab: Queues 3: write pop()

#include <iostream> #include <string> using namespace std; class Queue_str { private: // Structure for the stack nodes struct QueueNode { string value; // Value in the node QueueNode *next; // Pointer to next node }; QueueNode *front; // Pointer to the first node QueueNode *rear; // Pointer to the last node int length; // Number of nodes in the queue public: Queue_str(){ front = rear = NULL; length = 0; } //Constructor //~Queue_str(); // Destructor // Queue operations bool isEmpty() { return length == 0; } bool push(string); string pop(); //string peek(); //string peekRear(); //int getLength(); }; /**~*~* Member function push: inserts the argument into the queue *~**/ bool Queue_str::push(string item) { QueueNode *newNode; // Pointer to a new node // Allocate a new node and store num there. newNode = new QueueNode; if (!newNode) return false; newNode->value = item; newNode->next = NULL; // Update links and counter if (!front) // front is NULL: empty queue front = newNode; else rear->next = newNode; rear = newNode; length++; return true; } /**~*~* Member function dequeue deletes the value at the front of the queue and returns it. Assume queue has at least one node *~**/ string Queue_str::pop() { string item = front->value; QueueNode *temp; temp = front; front = front->next; delete temp; length--; return item; } int main() { Queue_str que; string item; cin >> item; while (item != "#") { que.push(item); cin >> item; } if (que.isEmpty()) { cout << "Empty Queue!" << endl; } while (!que.isEmpty()) { cout << que.pop() << endl; } return 0; }

4.4 Lab: Queues 2: write destructor

#include <iostream> #include <string> using namespace std; class Queue_str { private: // Structure for the stack nodes struct QueueNode { string value; // Value in the node QueueNode *next; // Pointer to next node }; QueueNode *front; // Pointer to the first node QueueNode *rear; // Pointer to the last node int length; // Number of nodes in the queue public: Queue_str(){ front = rear = NULL; length = 0; } //Constructor ~Queue_str(); // Destructor // Queue operations // bool isEmpty(); bool push(string); // string pop(); // string peek(); // string peekRear(); // int getLength(); }; /**~*~* Member function push: inserts the argument into the queue *~**/ bool Queue_str::push(string item) { QueueNode *newNode; // Pointer to a new node // Allocate a new node and store num there. newNode = new QueueNode; if (!newNode) return false; newNode->value = item; newNode->next = NULL; // Update links and counter if (!front) // front is NULL: empty queue front = newNode; else rear->next = newNode; rear = newNode; length++; return true; } /**~*~* Destructor *~**/ Queue_str::~Queue_str() { QueueNode *cur; QueueNode *prev; cur = front; while (cur != nullptr) { prev = cur->next; cout << cur->value << " - deleted!" << endl; delete cur; cur = prev; } cout << "Empty queue!" << endl; } int main() { Queue_str que; string item; cin >> item; while (item != "#" ) { que.push(item); cin >> item; } return 0; }

4.6 Lab: Queues 4: QueueADT.h

// // Created by Peter on 4/25/2020. // #include <iostream> using namespace std; #ifndef LAB_QUEUES_QUEUEADT_H #define LAB_QUEUES_QUEUEADT_H template<typename TheType> class QueueADT { private: struct QueueNode { TheType value; // value inside node is of template typename QueueNode *next; // pointer to next (upper) node }; QueueNode *front; // pointer to first node QueueNode *rear; // pointer to last node int length; // num nodes in queue public: QueueADT() { front = rear = nullptr; length = 0; } ~QueueADT(); bool isEmpty() { return length == 0; } bool push(TheType); TheType peek() { return front->value; } TheType peekRear() { return rear->value; } int getLength() { return length; } TheType pop(); }; /**~*~* Member function push: inserts the argument into the queue *~**/ template <typename TheType> bool QueueADT<TheType>::push(TheType item) { QueueNode *newNode; // Pointer to a new node // Allocate a new node and store value and next ptr to NULL there. newNode = new QueueNode; if (!newNode) return false; newNode->value = item; newNode->next = nullptr; // Update links and counter if (!front) // front is NULL: empty queue front = newNode; else rear->next = newNode; rear = newNode; length++; return true; } /**~*~* Destructor *~**/ template <typename TheType> QueueADT<TheType>::~QueueADT() { QueueNode *cur; QueueNode *prev; cur = front; while (cur != nullptr) { prev = cur->next; //cout << cur->value << " - deleted!" << endl; delete cur; cur = prev; } //cout << "Empty queue!" << endl; } /**~*~* Member function dequeue deletes the value at the front of the queue and returns it. Assume queue has at least one node *~**/ template <typename TheType> TheType QueueADT<TheType>::pop() { TheType item = front->value; QueueNode *temp; temp = front; front = front->next; delete temp; length--; return item; } #endif //LAB_QUEUES_QUEUEADT_H

Given a function that describes the running time of an algorithm, the Big O notation for that function can be determined using the following rules:

1. If f(N) is a sum of several terms, the highest order term (the one with the fastest growth rate) is kept and others are discarded. 2. If f(N) has a term that is a product of several factors, all constants (those that are not in terms of N) are omitted. O(N^2) Pronounced: "Oh N squared"

Runtime growth rate

1. efficiency of the algorithm is most critical for large input sizes. 2. Small inputs are likely to result in fast running times because N is small, so efficiency is less of a concern.

i = 0 sum = 0 while (i < N) { sum = sum + numbers[i] ++i } Which function best represents the number of operations in the worst-case?

2 operations execute before the loop. The loop condition and 2 operations in the loop executes N times, yielding 3N operations. The loop condition is checked 1 additional time before the loop terminates. The total operations as a function of N can be expressed as 2 + 3N + 1, or 3N + 3.

An algorithm with runtime complexity T(N) has a lower bound

A function f(N) that is ≤ the best case T(N), for all values of N ≥ 1. An algorithm with best case runtime T(N)=7N+36 and worst case runtime T(N)=3N^2+10N+17, has a lower bound f(N)=7N

An algorithm with runtime complexity T(N) has an upper bound

A function f(N) that is ≥ the worst case T(N), for all values of N ≥ 1. An algorithm with best case runtime T(N)=7N+36 and worst case runtime T(N)=3N^2+10N+17, has a lower bound f(N)=30N^2

Growth rates and asymptotic notations

An additional simplification can factor out the constant from a bounding function, leaving a function that categorizes the algorithm's growth rate. Ex: Instead of saying that an algorithm's runtime function has an upper bound of 30N^2, the algorithm could be described as having a worst case growth rate of N^2

T/F: The hardware running the code is the only thing that affects what is and what is not a constant time operation.

False. The programming language also affects what is a constant time operation. Ex: A programming language could provide variable size floating point values as the only available numerical type and implement arithmetic operations in software. Since the values are not fixed size, arithmetic operations would not be constant time.

Suppose T(N)=2N^2+N+9. T/F: T(N) = Ω( N^3 )

False: No positive constant c exists such that 2N^2+N+9 >= c * N^3 for all N >= 1. This can be seen by realizing that no matter how small c<<1 is chosen, N^3 increases on N >= 1 by a factor N faster than 2N^2. Furthermore: lim (c*N^3)/(2N^2+N+9) = +infinity as N>=1 approaches infinity

T/F: Runtime and memory usage are the only two resources making up computational complexity.

False: Although runtime and memory usage are the most common, computational complexity can include other factors, such as network communication.

T/F: An algorithm's best and worst case scenarios are always different.

False: An algorithm can have the same best and worst case, in which case the algorithm always does the same number of operations regardless of input data.

T/F: Nearly every algorithm has a best case time complexity when N = 0.

False: The variable value N cannot be replaced with a constant of 0 to describe a best case scenario. A best case scenario must describe the contents of the data being processed.

T/F: Two different algorithms that produce the same result have the same computational complexity.

False: Two different algorithms can produce the same result in various ways and may have different computational complexities.

Queue

First-In-First-Out (FIFO) data structure, items are inserted at the end of the queue and removed from the front of the queue, with operations insert and delete, commonly named enqueue and dequeue respectively.

Growth rates for different input sizes. The table shows the runtime to perform f(N) instructions for different functions f and different values of N. For large N, the difference in computation time varies greatly with the rate of growth of the function f. The data assumes that a single instruction takes 1 μs to execute.

Function N = 10 N = 50 N = 100 N = 1000 N = 10000 N = 100000 log_2 (N): 3.3 μs 5.65 μs 6.6 μs 9.9 μs 13.3 μs 16.6 μs N: 10 μs 50 μs 100 μs 1000 μs 10 ms 100 ms N log_2 (N): .03 ms .28 ms .66 ms .099 s .132 s 1.66 s N^2: .1 ms 2.5 ms 10 ms 1 s 100 s 2.7 hours N^3: 1 ms .125 s 1 s 16.7 min 11.57 days 31.7 years 2^N: .001 s 35.7 years > 1000 years

5.1 Constant time operations

In practice, designing an efficient algorithm aims to lower the amount of time that an algorithm runs. However, a single algorithm can always execute more quickly on a faster processor. Therefore, the theoretical analysis of an algorithm describes runtime in terms of number of constant time operations, not nanoseconds.

Push(queue, x)

Inserts x at end of the queue. starting with queue: 43, 12, 77 (front is 43) Push(queue, 56). Queue: 43, 12, 77, 56

PushBack(deque, x)

Inserts x at the back of the deque starting with deque: 59, 63, 19 (front is 59) PushBack(deque, 41). Deque: 59, 63, 19, 41

PushFront(deque, x)

Inserts x at the front of the deque starting with deque: 59, 63, 19 (front is 59) PushFront(deque, 41). Deque: 41, 59, 63, 19

FindMax(list, listSize) { if (listSize >= 1) { maximum = list[0] i = 1 while (i < listSize) { if (list[i] > maximum) { maximum = list[i] } i = i + 1 } return maximum } } // What are the memory (input) and memory (non-input) variables? // fixed-size integers? variable sized? // space complexity? auxiliary space complexity?

Memory (input): listSize: fixed-size integer list: Array of N integers Memory (non-input): maximum: fixed-size integer i: fixed-size integer => space complexity excluding input data: 2=S(N) auxiliary space complexity N + 3 = S(N) space complexity since the list's size is a variable, N, and k=3 integers are also used.

Common constant time operations.

Most modern processors perform arithmetic operations on integers and floating point values at a fixed rate that is unaffected by operand values. Part of the reason for this is that the floating point and integer values have a fixed size. Addition, subtraction, multiplication, and division of fixed size integer or floating point values. w = 10.4 x = 3.4 y = 2.0 z = (w - x) / y Assignment of a reference, pointer, or other fixed size data value. x = 1000 y = x a = true b = a Comparison of two fixed size data values. a = 100 b = 200 if (b > a) { ... } Read or write an array element at a particular index. x = arr[index] arr[index + 1] = x + 1

Three asymptotic notations are commonly used in complexity analysis:

O notation provides a growth rate for an algorithm's upper bound. A positive constant c exists such that, for all N ≥ 1, T(N) <= c * f(N) holds true <=>T(N) = O( f(N) ) Ω notation provides a growth rate for an algorithm's lower bound. A positive constant c exists such that, for all N ≥ 1, T(N) >= c * f(N) holds true <=>T(N) = Ω( f(N) ) Θ notation provides a growth rate that is both an upper and lower bound. T(N) = Ω( f(N) ) and T(N) = O( f(N) ) hold true <=>T(N) = Θ( f(N) )

Common Big O complexities

O(1): Constant FindMin(x, y) { if (x < y) { return x } else { return y } } O(log N): Logarithmic BinarySearch(numbers, N, key) { mid = 0 low = 0 high = N - 1 while (high >= low) { mid = (high + low) / 2 if (numbers[mid] < key) { low = mid + 1 } else if (numbers[mid] > key) { high = mid - 1 } else { return mid } } return -1 // not found } O(N): Linear LinearSearch(numbers, numbersSize, key) { for (i = 0; i < numbersSize; ++i) { if (numbers[i] == key) { return i } } return -1 // not found } O(N log N): Linearithmic MergeSort(numbers, i, k) { j = 0 if (i < k) { j = (i + k) / 2 // Find midpoint MergeSort(numbers, i, j) // Sort left part MergeSort(numbers, j + 1, k) // Sort right part Merge(numbers, i, j, k) // Merge parts } } O(N^2): Quadratic SelectionSort(numbers, numbersSize) { for (i = 0; i < numbersSize; ++i) { indexSmallest = i for (j = i + 1; j < numbersSize; ++j) { if (numbers[j] < numbers[indexSmallest]) { indexSmallest = j } } temp = numbers[i] numbers[i] = numbers[indexSmallest] numbers[indexSmallest] = temp } } O(c^N): Exponential Fibonacci(N) { if ((1 == N) || (2 == N)) { return 1 } return Fibonacci(N-1) + Fibonacci(N-2) }

nVal = N steps = 0 while (nVal > 0) { nVal = nVal / 2 steps = steps + 1 } What is the big-O notation for the worst-case runtime?

O(log(N)): nVal is decreased by half each iteration, so the loop will execute log_2(N) times. f(N)=2+3*log_2(N)+1=O(log(N))

PopBack(deque)

Returns and removes item at back of deque starting with deque: 59, 63, 19 (front is 59) PopBack(deque) returns 19. Deque: 59, 63

PopFront(deque)

Returns and removes item at front of deque starting with deque: 59, 63, 19 (front is 59) PopFront(deque) returns 59. Deque: 63, 19

Pop(queue)

Returns and removes item at front of queue starting with queue: 43, 12, 77 (front is 43) Pop(queue) returns: 43. Queue: 12, 77

Peek(queue)

Returns but does not remove item at the front of the queue starting with queue: 43, 12, 77 (front is 43) Peek(queue) return 43. Queue: 43, 12, 77

PeekBack(deque)

Returns but does not remove the item at the back of deque starting with deque: 59, 63, 19 (front is 59) PeekBack(deque) returns 19. Deque is still: 59, 63, 19

PeekFront(deque)

Returns but does not remove the item at the front of deque starting with deque: 59, 63, 19 (front is 59) PeekFront(deque) returns 59. Deque is still: 59, 63, 19

GetLength(deque)

Returns the number of items in the deque starting with deque: 59, 63, 19 (front is 59) GetLength(deque) returns 3.

GetLength(queue)

Returns the number of items in the queue starting with queue: 43, 12, 77 (front is 43) GetLength(queue) returns 3.

IsEmpty(queue)

Returns true if queue has no items starting with queue: 43, 12, 77 (front is 43) IsEmpty(queue) returns false.

IsEmpty(deque)

Returns true if the deque is empty starting with deque: 59, 63, 19 (front is 59) IsEmpty(deque) returns false.

Runtime analysis: Finding the max value maxVal = numbers[0] // 1 operation for (i = 0; i < N; ++i) { // 1 operation & N true iterations // for each iteration, 1 operation increment, // 1 operation compare guaranteed if ( numbers[i] > maxVal) { // 1 operation compare guaranteed, //then 1 more operation (worst case if true) maxVal = numbers[i] } // last iteration through loop results in false 1 more operation }

Runtime analysis determines the total number of operations. Operations include assignment, addition, comparison, etc. The for loop iterates N times, but the for loop's initial expression i = 0 is executed once. For each loop iteration, the increment and comparison expressions are each executed once. In the worst-case, the if's expression is true, resulting in 2 operations. One additional comparison is made before the loop ends. The function f(N) specifies the number of operations executed for input size N. The big-O notation for the function is the algorithm's worst-case runtime complexity: f(N)=1 first op + 1 set i + 1 last op + N( 2 increment and compare + 2 worst case compare and assign)=3+4N=O(N)

GetEvens(list, listSize) { i = 0 evensList = Create new, empty list while (i < listSize) { if (list[i] % 2 == 0) Add list[i] to evensList i = i + 1 } return evensList } //What is the worst case space complexity of GetEvens if N is the list's size and k is a constant?

S(N) = N + k In the worst case, all items from the input list are added to the returned list. As the input size N increases, the output size increases to match.

GetEvens(list, listSize) { i = 0 evensList = Create new, empty list while (i < listSize) { if (list[i] % 2 == 0) Add list[i] to evensList i = i + 1 } return evensList } //What is the best case auxiliary space complexity of GetEvens if N is the list's size and k is a constant?

S(N)=k In the best case, the input list contains only odd numbers and the output size is 0, whether the list has 10 odd numbers or 1000 odd numbers. A constant output size of zero corresponds to an auxiliary space complexity of k.

negCount = 0 for(i = 0; i < N; ++i) { if (numbers[i] < 0 ) ++negCount } What is the big-O notation for the worst-case runtime?

The total number of operations include: 1 operation before the loop, 1 operation at the start of the loop, 4 operations that execute each of the N loop iterations, and 1 operation for the final loop condition check. f(N)=4N+3 O(4N+3)=O(N)

Worst-case algorithm analysis

To analyze how runtime of an algorithm scales as the input size increases, we first determine how many operations the algorithm executes for a specific input size, N. Then, the big-O notation for that function is determined. Algorithm runtime analysis often focuses on the worst-case runtime complexity.

T/F: In the code below, suppose str1 is a pointer or reference to a string. The code only executes in constant time if the assignment copies the pointer/reference, and not all the characters in the string.

True. Copying all characters in the string would require more operations for longer strings. But assignment of a pointer/reference is a constant time operation.

T/F: Certain hardware may execute division more slowly than multiplication, but both may still be constant time operations.

True. Division is often slower than multiplication on many processors. But each division operation takes the same amount of time regardless of operand values, so is still a constant time operation.

Suppose T(N)=2N^2+N+9. T/F: T(N) = O( N^3 )

True: If c=12, 2N^2+N+9 <= c * N^3 is true for all N>=1.

Suppose T(N)=2N^2+N+9. T/F: T(N) = Ω( N^2 )

True: c=1, then 2N^2+N+9 >= c * N^2 is true for all N>=1

Suppose T(N)=2N^2+N+9. T/F: T(N)= O( N^2 )

True: c=12, then 2N^2+N+9 <= c * N^2 is true for all N>=1

Suppose T(N)=2N^2+N+9. T/F: T(N) = Θ( N^2 )

True: Bc T(N) = Ω( N^2 ) and T(N) = O( N^2 ) are both true

T/F: Computational complexity analysis allows the efficiency of algorithms to be compared.

True: Runtime and space complexity analysis, discussed below, provide a mathematical way to compare algorithm efficiency.

algorithm's space complexity

a function, S(N), that represents the number of fixed-size memory units used by the algorithm for an input of size N. Space complexity includes the input data and additional memory allocated by the algorithm. Ex: The space complexity of an algorithm that duplicates a list of numbers is S(N) = 2N + k, where k is a constant representing memory used for things like the loop counter and list pointers.

algorithm's runtime complexity

a function, T(N), that represents the number of constant time operations performed by the algorithm on an input of size N. Because an algorithm's runtime may vary significantly based on the input data, a common approach is to identify best and worst case scenarios. An algorithm's best case is the scenario where the algorithm does the minimum possible number of operations. An algorithm's worst case is the scenario where the algorithm does the maximum possible number of operations.

A queue can be implemented using ____, ______ or a _______

a linked list, an array, or a vector.

Big O Notation (definition)

a mathematical way of describing how a function (running time of an algorithm) generally behaves in relation to the input size. In Big O notation, all functions that have the same growth rate (as determined by the highest order term of the function) are characterized using the same Big O notation. In essence, all functions that have the same growth rate are considered equivalent in Big O notation.

Computational complexity

amount of resources used by the algorithm. The most common resources considered are the runtime and memory usage. Complexity analysis is used to identify and avoid using algorithms with long runtimes or high memory usage: we want runtime and memory use "balanced".

deque (pronounced "deck" and short for double-ended queue)

an ADT in which items can be inserted and removed at both the front and back. Ex: After the operations "push-back 7", "push-front 14", "push-front 9", and "push-back 5", "pop-back" returns 5. A subsequent "pop-front" returns 9. A deque can be implemented using a linked list or an array.

constant time operation

an operation that, for a given processor, always operates in the same amount of time, regardless of input values: ie multiplication, assignment are constant time operations, a body of constant ops, or a loop with a constant number of iterations and only executing a body of constant ops, x = 10 // assignment y = 20 // assignment a = 1000 // assignment b = 2000 // assignment z = x * y // multiplication c = a * b // multiplication for (i = 0; i < 10; i++) sum += y // loop constant body ops as opposed to non-constant time operations, ie loop that iterates a variable x number of times, adding y to a sum each iteration, will take longer if x is larger, wherein the loop itself is not constant time, despite it's body containing only a constant time op for (i = 0; i < x; i++) sum += y or as opposed to string concatenation is another operation that is not constant time, because more characters need to be copied for larger strings.

Rules for determining Big O notation of composite functions.

c · O(f(N)) := O(f(N)) c + O(f(N)) := O(f(N)) g(N) · O(f(N)) := O(g(N) · f(N)) g(N) + O(f(N)) := O(g(N) + f(N)) Special Case: The logarithm base does not affect the growth rate, so the base is omitted in Big O notation. Converting from one logarithm base to another base involves a constant factor, which can be simplified in Big O notation. O( log_2 (N) ) =O(log(N)/log(2)) = O(log(N) * (1/log(2))) = O ( log(N) )

The only queue operation that has a loop is ______________

destructor

queue op'n: push

inserts an item at the end of the queue.

deque op'n: push-front

inserts an item at the front of the deque

deque op'n: push-back

inserts at the back of the deque

Determining the average-case runtime requires

knowledge of the statistical properties of the expected data inputs, aka a large (randomly, feasibly encompassing) robust dataset.

for (i = 0; i < N; ++i) { if ((i % 2) == 0) { outVal[i] = inVals[i] * i } } What is the big-O notation for the worst-case runtime?

outVal[i] = inVals[i] * i; executes every other loop iteration, so the total number of operations include: 1 operation at the start of the loop, 3 operations every loop iteration, 1 operation every other loop iteration, and 1 operation for the final loop condition check. f(N) = 1 + 3N + N/2 + 1 = O(N)

deque op'n: pop-back

removes and returns the item at the back of the deque

deque op'n: pop-front

removes and returns the item at the front of the deque

queue op'n: pop

removes and returns the item at the front of the queue. Ex: After the operations "Push 7", "Push 14", and "Push 9", "Pop" returns 7. A second "Pop" returns 14. Analogy: A queue ADT is similar to waiting in line at the grocery store. A person enters at the end of the line and exits at the front. British English actually uses the word "queue" in everyday vernacular where American English uses the word "line".

Asymptotic notation

the classification of runtime complexity that uses functions that indicate only the growth rate of a bounding function.

worst-case runtime of an algorithm

the runtime complexity for an input that results in the longest execution.

algorithm's auxiliary space complexity

the space complexity not including the input data. Ex: An algorithm to find the maximum number in a list will have a space complexity of S(N) = N + k, but an auxiliary space complexity of S(N) = k, where k is a constant.

Linearithmic or Linear Logarithmic or Quasilinear

time elapsed proportional to N log(N) to run on inputs of size N.

Algorithm efficiency

typically measured by the algorithm's computational complexity.


Ensembles d'études connexes

Exam 1 Stereotyping and Prejudice

View Set

Ch 1. Overview of professional med surg nursing concepts

View Set

CSU GEOL-120 Cumulative Final Exam

View Set

Exam I Medsurg II Ch 9, 25, 31, 32, 33, 37

View Set

Earth Science - Ch 10 Multiple Choice

View Set