CS 367 Introduction to Data Structures Lecture 4.

Slides:



Advertisements
Similar presentations
Chapter 22 Implementing lists: linked implementations.
Advertisements

Linked Lists Geletaw S..
Algorithm Analysis.
MATH 224 – Discrete Mathematics
Chapter 17 Linked List Saurav Karmakar Spring 2007.
Lower bound for sorting, radix sort COMP171 Fall 2005.
Fundamentals of Python: From First Programs Through Data Structures
Chapter 1 – Basic Concepts
the fourth iteration of this loop is shown here
Fall 2006CENG 7071 Algorithm Analysis. Fall 2006CENG 7072 Algorithmic Performance There are two aspects of algorithmic performance: Time Instructions.
CSC401 – Analysis of Algorithms Lecture Notes 1 Introduction
Lower bound for sorting, radix sort COMP171 Fall 2006.
Introduction to Analysis of Algorithms
Complexity Analysis (Part I)
Analysis of Algorithms1 Estimate the running time Estimate the memory space required. Time and space depend on the input size.
Lecture 4 Feb 5 completion of recursion (inserting into a linked list as last item) analysis of algorithms – Chapter 2.
Lecture 4 Sept 4 Goals: chapter 1 (completion) 1-d array examples Selection sorting Insertion sorting Max subsequence sum Algorithm analysis (Chapter 2)
Linked Lists part II. Linked Lists A linked list is a dynamic data structure consisting of nodes and links: 627 start 8 This symbol indicates a null reference.
Liang, Introduction to Java Programming, Eighth Edition, (c) 2011 Pearson Education, Inc. All rights reserved Chapter 23 Algorithm Efficiency.
Data Structure Algorithm Analysis TA: Abbas Sarraf
Analysis of Algorithms 7/2/2015CS202 - Fundamentals of Computer Science II1.
Analysis of Algorithm.
Searching1 Searching The truth is out there.... searching2 Serial Search Brute force algorithm: examine each array item sequentially until either: –the.
Analysis of Algorithms COMP171 Fall Analysis of Algorithms / Slide 2 Introduction * What is Algorithm? n a clearly specified set of simple instructions.
CHAPTER 7: SORTING & SEARCHING Introduction to Computer Science Using Ruby (c) Ophir Frieder at al 2012.
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All rights reserved Chapter 23 Algorithm Efficiency.
Algorithm Analysis & Complexity We saw that a linear search used n comparisons in the worst case (for an array of size n) and binary search had logn comparisons.
Analysis of Algorithm Lecture 3 Recurrence, control structure and few examples (Part 1) Huma Ayub (Assistant Professor) Department of Software Engineering.
Week 2 CS 361: Advanced Data Structures and Algorithms
SEARCHING, SORTING, AND ASYMPTOTIC COMPLEXITY Lecture 12 CS2110 – Fall 2009.
1 Recursion Algorithm Analysis Standard Algorithms Chapter 7.
{ CS203 Lecture 7 John Hurley Cal State LA. 2 Execution Time Suppose two algorithms perform the same task such as search (linear search vs. binary search)
Lecture 2 Computational Complexity
1 Joe Meehean.  Conceptual Picture N items chained together using pointers pointed to by head variable  Advantage allows list to grow indefinitely without.
Analysis of Algorithms
Arrays Tonga Institute of Higher Education. Introduction An array is a data structure Definitions  Cell/Element – A box in which you can enter a piece.
Analysis of Algorithms These slides are a modified version of the slides used by Prof. Eltabakh in his offering of CS2223 in D term 2013.
CSC 211 Data Structures Lecture 13
Data Structure Introduction.
Computer Science and Software Engineering University of Wisconsin - Platteville 8. Comparison of Algorithms Yan Shi CS/SE 2630 Lecture Notes Part of this.
Introduction to Analysis of Algorithms CS342 S2004.
(c) University of Washington16-1 CSC 143 Java Linked Lists Reading: Ch. 20.
CS 367 Introduction to Data Structures Lecture 2 Audio for Lecture 1 is available Homework 1 due Friday, September 18.
© 2006 Pearson Addison-Wesley. All rights reserved5 B-1 Chapter 5 (continued) Linked Lists.
Copyright © 0 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Starting Out with Java From Control Structures through Data Structures by Tony.
Linked Lists Chapter 4. Linked Structures: Motivations Arrays have fixed size –Problematic for data structures of arbitrary size Arrays order items physically.
1 Today’s Material List ADT –Definition List ADT Implementation: LinkedList.
Chapter 5 Linked Lists. © 2004 Pearson Addison-Wesley. All rights reserved 5 A-2 Preliminaries Options for implementing an ADT –Array Has a fixed size.
CS 367 Introduction to Data Structures Lecture 5.
Algorithm Analysis (Big O)
Chapter 5 Linked List by Before you learn Linked List 3 rd level of Data Structures Intermediate Level of Understanding for C++ Please.
Searching and Sorting Searching: Sequential, Binary Sorting: Selection, Insertion, Shell.
DS.A.1 Algorithm Analysis Chapter 2 Overview Definitions of Big-Oh and Other Notations Common Functions and Growth Rates Simple Model of Computation Worst.
A Introduction to Computing II Lecture 5: Complexity of Algorithms Fall Session 2000.
CPS 100e 5.1 Inheritance and Interfaces l Inheritance models an "is-a" relationship  A dog is a mammal, an ArrayList is a List, a square is a shape, …
Algorithm Analysis with Big Oh ©Rick Mercer. Two Searching Algorithms  Objectives  Analyze the efficiency of algorithms  Analyze two classic algorithms.
Analysis of Algorithms Spring 2016CS202 - Fundamentals of Computer Science II1.
Section 1.7 Comparing Algorithms: Big-O Analysis.
Chapter 15 Running Time Analysis. Topics Orders of Magnitude and Big-Oh Notation Running Time Analysis of Algorithms –Counting Statements –Evaluating.
1 Algorithms Searching and Sorting Algorithm Efficiency.
CSC 427: Data Structures and Algorithm Analysis
Week 4 - Friday CS221.
Analysis of Algorithms
Introduction to Search Algorithms
Algorithm Analysis CSE 2011 Winter September 2018.
Programming II (CS300) Chapter 07: Linked Lists and Iterators
Searching, Sorting, and Asymptotic Complexity
8. Comparison of Algorithms
Programming II (CS300) Chapter 07: Linked Lists
Linked Lists Chapter 5 (continued)
Presentation transcript:

CS 367 Introduction to Data Structures Lecture 4

Big O Notation This is a notation that expresses the overall complexity of an algorithm. Only the highest-order term is used; constants, coefficients, and lower-order terms are discarded. O(1) is constant time. O(N) is linear time. O(N 2 ) is quadratic time. O(2 N ) is exponential time.

The three functions: 4N 2 +3N+2, 300N 2, N(N-2)/2 Are all O(N 2 ).

Formal Definition A function T(N) is O(F(N)) if for some constant c and threshold n 0, it is the case T(N) ≤ c F(N) for all N > n 0

Example The function 3n 2 -n+3 is O(n 2 ) with c =3 and n 0 = 3: n3n 2 -n+33n

Complexity in Java Code Basic Operations (assignment, arithmetic, comparison, etc.) : Constant time, O(1) List of statements: statement 1 ; statement 2 ; … statement k ; // k is independent of problem size

If each statement uses only basic operations, complexity is k*O(1) = O(1) Otherwise, complexity of the list is the maximum of the individual statements.

If-Then-Else if (cond) { sequence 1 of statements } else { sequence 2 of statements } Assume conditional requires O(N c ), then requires O(N t ) and else requires O(N e ).

Overall complexity is: O(N c ) + O(max(N t, N e )) = O(max(N c, max(N t, N e ))) = O(max(N c,N t, N e ))

Basic loops for (i = 0; i < M; i++) { sequence of statements } We have M iterations. If the body’s complexity is O(N b ), the whole loop requires M*O(N b ) = O(M*N b ) (simplify O term if possible).

Nested Loops for (i = 0; i < M; i++) { for (j = 0; j < L; j++) { sequence of statements } We have M*L iterations. If the body’s complexity is O(N b ), the whole loop requires M*L*O(N b ) = O(M*L*N b ) (simplify O term if possible).

Method calls Suppose f1(k) is O(1) (constant time): for (i = 0; i < N; i++) { f1(i); } Overall complexity is N*O(1) = O(N)

Suppose f2(k) is O(k) (linear time): for (i = 0; i < N; i++) { f2(N); } Overall complexity is N*O(N) = O(N 2 )

Suppose f2(k) is O(k) (linear time): for (i = 0; i < N; i++) { f2(i); } ”Unroll” the loop. Complexity is: O(0)+O(1)+… +O(N-1) = O(0+1+ … +N-1) = O(N*(N-1)/2) = O(N 2 )

Number Guessing Game Person 1 picks a number between 1 and N. Repeat until number is guessed: Person 2 guesses a number Person 1 answers "correct", "too high", or "too low” problem size = N count : # guesses

Algorithm 1: Guess number = 1 Repeat If guess is incorrect, increment guess by 1 until correct Best case: 1 guess Worst case: N guesses Average case: N/2 guesses Complexity = O(N)

Algorithm 2: Guess number = N/2 Set step = N/4 Repeat If guess is too large, next guess = guess - step If guess is too small, next guess = guess + step step = step/2 (alternate rounding up/down) until correct

Best case: 1 guess Worst case: log 2 (N). So complexity is O(log N). Algorithm 2 is way better!

Returning N Papers to N Students problem size (N) = # students count # of "looks" at a paper What is the complexity of each algorithm below?

Algorithm 1: Call out each name, have student come forward & pick up paper best-case: O(N) worst-case: O(N) But, this algorithm “cheats: a bit! Why? Concurrency!

Algorithm 2: Hand pile to first student, student searches & takes own paper, then pass pile to next student. best-case: Each of N students “hits” at first search. This is N*O(1) = O(N). worst-case: N compares, then N-1 compares, etc. Time is O(N)+O(N-1)+… + O(1) = O(N 2 ).

Algorithm 3: Sort the papers alphabetically, hand pile to first student who does a binary search, then pass pile to next student. Sort is O(N log N). Student 1 takes O(log N), Student 2 takes O(log (N-1)), … Bounded by N*O(log n). Overall complexity is O(N log N).

Practice with analyzing complexity For each of the following methods, determine the complexity. Assume arrays A and B are each of size N (i.e., A.length = B.length = N)

method1 void method1(int[] A, int x, int y) { int temp = A[x]; A[x] = A[y]; A[y] = temp;} Constant time per call, thus O(1).

method2 void method2(int[] A, int s) { for (int i = s; i < A.length - 1; i++) if (A[i] > A[i+1]) method1(A, i, i+1); } Number of iterations is at most N. Each call is O(1) so overall complexity is O(N).

method3 void method3(int[] B) { for (int i = 0; i < B.length - 1; i++) method2(B, i); } Number of iterations is N-1. method2 does N-1 iterations, then N-2, etc. This totals to N 2, so overall complexity is O(N 2 ).

method4 void method4(int N) { int sum = 0, M = 1000; for (int i = N; i > 0; i--) for (int j = 0; j < M; j++) sum += j; } Since M is a constant, the entire inner loops takes a bounded amount of time; its complexity is O(1). Outer loop iterates N times, so overall complexity is O(N).

What if M is a parameter? void method4a(int N, int M) { int sum = 0; for (int i = N; i > 0; i--) for (int j = 0; j < M; j++) sum += j; } Now the entire inner loops takes O(M) time. The overall complexity is now O(N*M).

method5 public void method5(int N) { int tmp, arr[]; arr = new int[N]; for (int i = 0; i < N; i++) arr[i] = N - i; for (int i = 1; i < N; i++) { for (int j = 0; j < N - i; j++) { if (arr[j] > arr[j+1]) { tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; }}}} What does this do?

Complexity of method5 Analyze in steps: 1. The call to new is O(1). 2. The first loop iterates N times; loop body is O(1), so loop is O(N). 3. The nested loop body iterates N-1 times, then N-2 times, …, 1 time. Total is O(N 2 ). Overall complexity is O(1)+O(N)+O(N 2 ) = O(N 2 ).

Complexity Caveats 1. Algorithms with the same complexity can differ when constants, coefficients and lower-order terms are considered. Which of these is better? 2N 2 +3N vs. 10N 2

2. A better complexity means eventually an algorithm will be better. But for small to intermediate problem sizes, an inferior complexity may win out! Consider 100*N vs. N 2 /100. The quadratic complexity is better until N = 10,000.

Primitive vs. Reference Types Primitive types represent fundamental data values (integer, floating point, characters). Values are placed directly in memory. An int value in one word (4 bytes): 1234

Reference Types Data objects (created by new ) are pointed to by a reference type. Int []

Assignment Assignment of a primitive type copies the actual value. A = 1234; A: B = A; B: 1234

Assignment of a reference type copies a pointer to an object. The object is not duplicated. B = A; B B A

Assignment of Reference Types Leads to Sharing Given A[1] = 1; causes B B A B B A 1 1

Use clone() to create a distinct copy of an Object B = A.clone(); creates: A B

But clone() makes a copy only of the object itself Objects accessed by references aren’t copied. If we clone A we get A A B B

A A B B A’ Why isn’t B copied too?

Consider: But you can create your own version of clone() if you wish! A A B B

Linked Lists Individual data items, called nodes, are linked together using references: Advantages: Easy to reorder nodes (by changing links). Easy to add extra nodes as needed.

Disadvantages: Each node needs a “next” field Moving forward is tedious (one node at a time). Moving backward is difficult or impossible.

Linked List in Java public class Listnode { //*** fields *** private E data; private Listnode next; //*** constructors *** (why two?) public Listnode(E d) { this(d, null); } public Listnode(E d, Listnode n) { data = d; next = n; }

// methods to access fields public E getData() { return data; } public Listnode getNext() { return next; }

// methods to modify fields public void setData(E d) { data = d; } public void setNext(Listnode n) { next = n; }

Example Create first node: Listnode l; l = new Listnode ("ant");

Then add second node at end of list: l.setNext( new Listnode ("bat"));

Adding a Node into a Linked List Assume l points to start of list, n points to node after which do insert:

Create node to be inserted: Listnode tmp = new Listnode (“xxx”);

Set the new node’s next field: tmp.setNext( n.getNext() );

Reset n ’s next field : n.setNext ( tmp );

Removing a Node from a List Goal: Remove node n from list l Approach: Find n ’s predecessor in the list Link that predecessor to n ’s successor

We search from head of list (l) to find n’s predecessor Listnode tmp = l; while (tmp.getNext() != n) { // find the node before n tmp = tmp.getNext(); }

We then reset the Predecessor’s next field tmp.setNext( n.getNext() ); // remove n from the linked list

Special Case Alert What happens if n is first element of list? It has no predecessor! How does the code fail? while (tmp.getNext() != n) { tmp = tmp.getNext(); }

How do we handle this? Add special case code Make sure every node has a predecessor!

Enhanced Code if (l == n) { // special case: n is the first node in the list l = n.getNext(); } else { // general case: find the node before n, then "unlink" n Listnode tmp = l; while (tmp.getNext() != n) { // find the node before n tmp = tmp.getNext(); } tmp.setNext(n.getNext()); }

Null List Reference vs. Null List If L is a variable of type Listnode, what does L == null mean? L is a null list (size == 0) Maybe not! L may be uninitialized (undefined) These two interpretations are different!

Header Nodes To distinguish between an undefined list and an empty (or null) list, we can add an extra header node at the start of each list. All lists now have at least one node. So an empty list isn’t equal to null. Moreover, inserting a node at the start of a list is easy – it is placed just after the header node!

The LinkedList Class Let’s implement a class that implements the ListADT interface using a linked list rather than an array. We’ll use a header node to illustrate its utility.

Interface definition for ListADT public interface ListADT { void add(E item); void add(int pos, E item); boolean contains(E item); int size( ); boolean isEmpty( ); E get(int pos); E remove(int pos); }

public class LinkedList implements ListADT { /* private data declarations */ /* constructor(s) */ /* interface methods */ }

public class LinkedList implements ListADT { private Listnode head; private Listnode tail; private int itemCount; /* constructor(s) */ /* interface methods */ }

public class LinkedList implements ListADT { private Listnode head; private Listnode tail; private int itemCount; public LinkedList() { itemCount = 0; head = new Listnode (null); tail = head; } /* interface methods */ }

public class LinkedList implements ListADT { /* data defs & constructor */ public int size( ){ return itemCount; } public boolean isEmpty( ){ return (size() == 0); }

public class LinkedList implements ListADT { /* data defs & constructor */ public void add(E item) { if (item == null) throw new NullPointerException(); Listnode newNode = new Listnode (item); tail.setNext(newNode); tail = newNode; itemCount++; }

public class LinkedList implements ListADT { public void add(int pos, E item){ if (item == null) throw new NullPointerException(); if (pos itemCount) { throw new IndexOutOfBoundsException(); } if (pos == itemCount) add(item); else {// Find where to insert Listnode ptr = head; for (int i = 0; i < pos; i++) ptr = ptr.getNext(); Listnode newNode = new Listnode (item); newNode.setNext(ptr.getNext()); ptr.setNext(newNode); } itemCount++;}

public class LinkedList implements ListADT { /* data defs & constructor */ public E get(int pos) { // check for bad pos if (pos = itemCount) { throw new IndexOutOfBoundsException(); } Listnode ptr = head.getNext(); for (int i = 0; i < pos; i++) ptr = ptr.getNext(); return ptr.getData();}

public class LinkedList implements ListADT { /* data defs & constructor */ public boolean contains(E item){ // null values are not allowed in the list if (item == null) return false; Listnode ptr = head.getNext(); while (ptr != null){ if (ptr.getData().equals(item)) return true; else ptr = ptr.getNext(); } return false; }}

public class LinkedList implements ListADT { /* data defs & constructor */ public E remove(int pos) { // check for bad pos if (pos = itemCount) { throw new IndexOutOfBoundsException();} // decrease the number of items itemCount--; Listnode prev = head, target; for (int i = 0; i < pos; i++) prev = prev.getNext(); target = prev.getNext(); prev.setNext(target.getNext()); if (target.getNext() == null) tail = prev; return target.getData();}}