Download presentation
Presentation is loading. Please wait.
1
Analysis of Algorithms
Running Time Pseudo-Code Analysis of Algorithms Asymptotic Notation Asymptotic Analysis Mathematical facts Analysis of Algorithms Portions copyright Goodrich & Tommassia!
2
Average Case vs. Worst Case Running Timeof an algorithm
An algorithm may run faster on certain data sets than on others. Finding the average case can be very difficult, so typically algorithms are measured by the worst-case time complexity. Also, in certain application domains (e.g., air traffic control, surgery, IP lookup) knowing the worst-case time complexity is of crucial importance. Analysis of Algorithms
3
Measuring the Running Time
How should we measure the running time of an algorithm? Approach 1: Experimental Study Write a program that implements the algorithm Run the program with data sets of varying size and composition. Use a method like System.currentTimeMillis() to get an accurate measure of the actual running time. Analysis of Algorithms
4
Beyond Experimental Studies
Experimental studies have several limitations: It is necessary to implement and test the algorithm in order to determine its running time. Experiments can be done only on a limited set of inputs, and may not be indicative of the running time on other inputs not included in the experiment. In order to compare two algorithms, the same hardware and software environments should be used. Analysis of Algorithms
5
Beyond Experimental Studies
We will now develop a general methodology for analyzing the running time of algorithms. In contrast to the "experimental approach", this methodology: Uses a high-level description of the algorithm instead of testing one of its implementations. Takes into account all possible inputs. Allows one to evaluate the efficiency of any algorithm in a way that is independent from the hardware and software environment. Analysis of Algorithms
6
Pseudo-Code Pseudo-code is a description of an algorithm that is more structured than usual prose but less formal than a programming language. Example: finding the maximum element of an array. Algorithm arrayMax(A, n): Input: An array A storing n integers. Output: The maximum element in A. currentMax A[0] for i 1 to n -1 do if currentMax < A[i] then currentMax A[i] return currentMax Pseudo-code is our preferred notation for describing algorithms. However, pseudo-code hides program design issues. Analysis of Algorithms
7
What is Pseudo-Code ? A mixture of natural language and high-level programming concepts that describes the main ideas behind a generic implementation of a data structure or algorithm. -Expressions: use standard mathematical symbols to describe numeric and boolean expressions -use for assignment (“=” in Java) -use = for the equality relationship (“==” in Java) -Method Declarations: Algorithm name(param1, param2) -Programming Constructs: - decision structures: if ... then ... [else ... ] - while-loops: while ... do - repeat-loops: repeat ... until ... - for-loop: for ... do - array indexing: A[i] -Methods: calls: object method(args) - returns: return value Analysis of Algorithms
8
Analysis of Algorithms
Primitive Operations: Low-level computations independent from the programming language can be identified in pseudocode. Examples: calling a method and returning from a method arithmetic operations (e.g. addition) comparing two numbers, etc. By inspecting the pseudo-code, we can count the number of primitive operations executed by an algorithm.
9
Example analysis #1: Algorithm arrayMax(A, n): Input: An array A storing n integers. Output: The maximum element in A. currentMax = A[0] for i = 1 to n -1 do if currentMax < A[i] then currentMax A[i] return currentMax Analysis: Total time = 1 + (n-1)(loop time) loop time = 4 (assume the worst case -- test is always true) Total time = 1 + (n-1)4 = 4n - 3 = T(n) 2 operations 2 operations n-1 iterations 2 operations Analysis of Algorithms
10
Example of Asymptotic Analysis #2
Algorithm prefixAverages1(X): Input: An n-element array X of numbers. Output: An n -element array A of numbers such that A[i] is the average of elements X[0], ... , X[i]. Let A be an array of n numbers. for i 0 to n - 1 do a 0 for j 0 to i do a a + X[j] A[i] a/(i+ 1) return array A Analysis ... total time = 1 + 0i<n (outer loop body time) outer loop body time = 1 + (inner loop time) + 4 inner loop time = 0j<i (inner loop body time) inner loop body time = 3 total time = 1 + 0i<n(1+ 0j<i 3 + 4) = 1 + 0i<n(5+ 3i) = 1 + 0i<n5+ 3 0i<ni = 1 + 5(n-1) + 3((n-1)2+n-1)/2 = 1.5n2+4n-4 = T(n) 1 operation 1 operation n iterations i iterations with i=0,1,2, …, n-1 3 operations 4 operations 1i n i = (n2+n)/2
11
Example #3 Compare with T(n) = 1.5n2+4n-4 for previous alg
A better algorithm for computing prefix averages: Algorithm prefixAverages2(X): Input: An n-element array X of numbers. Output: An n -element array A of numbers such that A[i] is the average of elements X[0], ... , X[i]. Let A be an array of n numbers. s 0 for i 0 to n do s s + X[i] A[i] s/(i+ 1) return array A Analysis ... Total time = 1 + (n+1)(loop time) Loop time = 7 Total time = 1 + (n+1)7 = 7n+8 = T(n) Compare with T(n) = 1.5n2+4n-4 for previous alg Which is better? 1 operation n+1 iterations 7 operations Analysis of Algorithms
12
Asymptotic Notation Goal: to simplify analysis by getting rid of unneeded information (like “rounding” 1,000,001≈1,000,000) We want to say in a formal way 3n2 ≈ n2 The “Big-Oh” Notation: given functions f(n) and g(n), we say that f(n) is O(g(n)) if and only if there are positive constants c and n0 such that f(n)≤ c g(n) for all n ≥ n0 Analysis of Algorithms
13
Example conclusion: 2n+6 is O(n).
For functions f(n) and g(n) (to the right) there are positive constants c and n0 such that: f(n)≤c g(n) for n ≥ n0 conclusion: 2n+6 is O(n). Analysis of Algorithms
14
Another Example On the other hand…
n2 is not O(n) because there is no c and n0 such that: n2 ≤ cn for n ≥ n0 (As the graph to the right illustrates, no matter how large a c is chosen there is an n big enough that n2>cn ) . Analysis of Algorithms
15
Asymptotic Notation (cont.)
Note: Even though it is correct to say “7n - 3 is O(n3)”, a better statement is “7n - 3 is O(n)”, that is, one should make the approximation as tight as possible Simple Rule: Drop lower order terms and constant factors: 7n-3 is O(n) 8n2log n + 5n2 + n is O(n2log n) Analysis of Algorithms
16
Asymptotic Notation (terminology)
Special classes of algorithms: logarithmic: O(log n) linear: O(n) quadratic: O(n2) polynomial: O(nk), k ≥ 1 exponential: O(an), n > 1 “Relatives” of the Big-Oh O(f(n)): Big-Oh -- asymptotic upper bound (f(n)): Big Omega--asymptotic lower bound (f(n)): Big Theta--asymptotic tight bound Analysis of Algorithms
17
Asymptotic Analysis of The Running Time
Use the Big-Oh notation to express the number of primitive operations executed as a function of the input size parameter n. For example, we saw that the arrayMax algorithm has T(n) = 4n-3 = O(n) Similarly example #2: 1.5n2+4n-4 = O(n2) example #3: n+8 = O(n) Comparing the asymptotic running time -an algorithm that runs in O(n) time is better than one that runs in O(n2) time -similarly, O(log n) is better than O(n) -hierarchy of functions: log n << n << n2 << n3 << 2n Caution! Beware of very large constant factors. An algorithm running in time 1,000,000 n is still O(n) but might be less efficient on your data set than one running in time 2n2, which is O(n2) #2 is better (“asymptotically faster”) than #3
18
Summary we want to predict running time of an algorithm
summarize all possible inputs with a single “size” parameter n many problems with “empirical” approach (measure lots of test cases with various n and then extrapolate) prefer “analytical” approach - examine algorithm to derive a execution time function T(n) for the number of primitive operations executed as a function of n (err on the side of pessimism by always select the worst case) To select best algorithm, compare their T(n) functions To simplify this comparision “round” the function using asymptotic (“big-O”) notation Amazing fact: Even though asymptotic complexity analysis makes many simplifying assumptions, it is remarkably useful in practice: if A is O(n3) and B is O(n2) then B really will be faster than A no matter how they’re implemented. Analysis of Algorithms
19
Math You might Need to Review Logarithms and Exponents (Appendix A)
properties of logarithms: logb(xy) = logbx + logby logb (x/y) = logbx - logby logbxa = alogbx logba= logxa/logxb properties of exponentials: a(b+c) = aba c abc = (ab)c ab /ac = a(b-c) b = a logab bc = a c*logab Analysis of Algorithms
20
More Math to Review Floor: x = the largest integer ≤ x
Ceiling: x = the smallest integer ≥ x Summations: (see Appendix A) Geometric progression: (see Appendix A) Analysis of Algorithms
21
Stacks, Queues, Linked Lists, Deques
Abstract Data Types (ADTs) Interfaces and implementations Stacks, queues, linked lists, dequeues Java implementations This week: - complete P1-P3 - start P4 - read Next week: - complete P4 - read Analysis of Algorithms Portions copyright Goodrich & Tommassia!
22
More terminology: Abstract Data Types (ADTs)
An Abstract Data Type is an abstract specification of a data structure what operations can be involved on an instance of the ADT Perhaps: invariants that are guaranteed to hold if the ADT is used properly No code! Java’s “interface” construct is for specifying ADTs (except invariants!) For example, if we are going to model a bag of marbles as an ADT, we could specify that: Operations this ADT stores marbles this ADT supports putting in a marble and getting out a marble. Invariants No marbles are ever lost or spontaneously generated Analysis of Algorithms
23
Abstract Data Types (ADTs)
There are lots of formalized and standard ADTs. (A bag of marbles is not one of them.) In this course we are going to learn a lot of different standard ADTs. (stacks, queues, trees...) Analysis of Algorithms
24
Stacks A stack is a container of objects that are inserted and removed according to the last-in-first-out (LIFO) principle. Objects can be inserted at any time, but only the last (the most-recently inserted) object can be removed. Inserting an item is known as “pushing” onto the stack. “Popping” off the stack means removing an (the M-R-U!) item. A PEZ® dispenser as an analogy: Analysis of Algorithms
25
The Stack Abstract Data Type
A stack is an abstract data type (ADT) that supports two main methods: push(o): Inserts object o onto top of stack pop(): Removes the top object of stack and returns it; if the stack is empty, an error occurs The following support methods should also be defined: size(): Returns the number of objects in stack isEmpty(): Return a boolean indicating if stack is empty. top(): Return the top object of the stack, without removing it; if the stack is empty, an error occurs. Analysis of Algorithms
26
Stack Example #1 2 3 1 Laundry Basket Analysis of Algorithms
27
Example #2: Stacks in the Java Virtual Machine
Each process running in a Java program has its own Java Method Stack. Each time a method is called, it is pushed onto the stack. The choice of a stack for this operation allows Java to do several useful things: Perform recursive method calls Print stack traces to locate an error Analysis of Algorithms
28
Java Method Stack newest method context oldest method context
Analysis of Algorithms
29
Java stuff See lectures 3-4!
Given the stack ADT, we need to code the ADT in order to use it in the programs. You need to understand two program constructs: interfaces and exceptions. An interface is a way to declare what a class is to do. It does not mention how to do it. For an interface, you just write down the method names and the parameters. When specifying parameters, what really matters is their types. Later, when you write a class for that interface, you actually code the content of the methods. Separating interface and implementation is a useful programming technique. Interface example: See lectures 3-4! Analysis of Algorithms
30
A Stack Interface in Java
public interface Stack { // accessor methods public int size(); public boolean isEmpty(); public Object top() throws StackEmptyException; // update methods public void push (Object element); public Object pop() throws StackEmptyException; } (yes - Java has a built-in Stack utility class!) Analysis of Algorithms
31
Array-Based Stack in Java
We want to implement our Stack interface. Lots of possibilities… one simple technique is to use an array public class ArrayStack implements Stack { ? } Analysis of Algorithms
32
An Array-Based Stack implementation
Create a stack using an array by specifying a maximum size N for our stack, e.g., N = 1000. The stack consists of an N-element array S and an integer variable t, the index of the top element in array S. Algorithm size(): return t +1 Algorithm isEmpty(): return (t < 0) Algorithm top(): if isEmpty() then throw a StackEmptyException return S[t] ... NOTE: Array indices start at 0, so we initialize t to -1 Pseudo-code is to the right. Analysis of Algorithms
33
Pseudo-Code (contd.) Algorithm push(o): if size() = N then
the Stack interface doesn’t know/care about this situation, becomes stacks “in the abstract” have infinite capacity. However, our simple array implementation does not handle this requirement, so we need to introduce an extra exception even though it isn’t mentioned in Stack Algorithm push(o): if size() = N then throw a StackFullException t t + 1 S[t] o Algorithm pop(): if isEmpty() then throw a StackEmptyException e S[t] S[t] null t t-1 return e Enable garbage collection (re-use of S[t]’s memory, if not referenced elsewhere in program execution). Analysis of Algorithms
34
An Array-Based Stack (contd.)
Both the push and pop methods runs in O(1) time The array implementation is simple and efficient. There is a predefined upper bound, N, on the size of the stack, which may be too small for a given application, or cause a waste of memory. StackEmptyException is required by the interface. StackFullException is particular to this implementation. Algorithm pop(): if isEmpty() then throw a StackEmptyException e S[t] S[t] null t t-1 return e Algorithm push(o): if size() = N then throw a StackFullException t t + 1 S[t] o “f(n)=O(1)” means “f(n) is a constant, independent of n” Analysis of Algorithms
35
Array-Based Stack in Java
public class ArrayStack implements Stack { // Implementation of the Stack interface using an array. public static final int CAPACITY = 1000; // default capacity of the stack private int capacity; // maximum capacity of the stack. private Object S[ ]; // S holds the elements of the stack private int top = -1; // the top element of the stack. public ArrayStack( ) { // Initialize the stack this(CAPACITY);// with default capacity } public ArrayStack(int cap) { // Initialize the stack with given capacity capacity = cap; S = new Object[capacity]; } Analysis of Algorithms
36
Array-Based Stack in Java (contd.)
public int size( ) { //Return the current stack size return (top + 1); } public boolean isEmpty( ) { // Return true iff the stack is empty return (top < 0); public void push(Object obj) throws StackFullException{ // Push a new element on the stack if (size() == capacity) { throw new StackFullException(“Stack overflow.”); S[++top] = obj; Analysis of Algorithms
37
Array-Based Stack in Java (contd.)
public Object top( )// Return the top stack element throws StackEmptyException { if (isEmpty( )) { throw new StackEmptyException(“Stack is empty.”); } return S[top]; public Object pop() // Pop off the stack element throw new StackEmptyException(“Stack is Empty.”); Object elem = S[top]; S[top--] = null; // Dereference S[top] and decrement top return elem; Analysis of Algorithms
38
Array-Based Stack in Java (contd.)
class StackFullException extends RunTimeException { // don’t need anything in here! } class StackEmptyException extends RunTimeException { Complete code available from COMP web page Analysis of Algorithms
39
Casting With a Generic Stack
Have an ArrayStack that can store only Integer objects or Student objects. In order to do so using a generic stack, the return objects must be cast to the correct data type. A Java code example: Integer year = new Integer(2001); Stack s = new ArrayStack(); // Stacks can only store Objects s.push(year); // Returned values usually must be cast to appropriate class int y = ((Integer) s.pop()).intValue(); Analysis of Algorithms
40
Queues enter at end of line exit from front of queue This week:
- complete P4, start P5 - finish reading chap 4 Next week: - complete P5 - read Analysis of Algorithms
41
Queues A queue differs from a stack in that its insertion and removal routines follows the first-in-first-out (FIFO) principle. (Remember: Stack=LIFO) Elements may be inserted at any time, but only the element which has been in the queue the longest may be removed. Elements are inserted at the rear (enqueued) and removed from the front (dequeued) Analysis of Algorithms
42
Queue example - Web spider
Search engines (Altavista, Google, etc) uses programs called spiders to discover new pages on the web (which can then be indexed for searching, but that’s another story…) Input = some particular seed page Repeatedly: select a previously-discovered page, and traverse one of its hyperlinks. To ensure broad coverage of the entire web, spiders employ a queue data-structure to store & select discovered pages newly discovered pages next page to be explored Analysis of Algorithms
43
The Queue Abstract Data Type
The queue has two fundamental methods: enqueue(o): Insert object o at the rear of the queue dequeue(): Remove the object from the front of the queue and return it; an error occurs if the queue is empty These support methods should also be defined: size(): Return the number of objects in the queue isEmpty(): Return a boolean value that indicates whether the queue is empty front(): Return, but do not remove, the front object in the queue; an error occurs if the queue is empty Analysis of Algorithms
44
Queue ADT: Java interface code
interface Queue { boolean isEmpty(); int size(); Object front() throws QueueEmptyException; Object dequeue() throws QueueEmptyException; void enqueue(Object); } Analysis of Algorithms
45
An Array-Based Queue Create a queue using an array in a circular fashion A maximum size N is specified, e.g. N = 1,000. The queue consists of an N-element array Q and two integer variables: -f, index of the front element (initially, f=0) -r, index of the element after the rear one (initially r=0) “normal configuration” Questions: What does f=r mean? How do we compute the number of elements in the queue from f and r? Analysis of Algorithms
46
An Array-Based Queue (contd.)
Algorithm size(): return (N - f + r) mod N Algorithm isEmpty(): return size() < 1; Algorithm front(): if isEmpty() then throw a QEmptyException return Q[f] Algorithm dequeue(): if isEmpty() then throw a QEmptyException temp Q[f] Q[f] null f (f + 1) mod N return temp Algorithm enqueue(o): if size = N - 1 then throw a QFullException Q[r] o r (r+1) mod N Analysis of Algorithms
47
An Array-Based Queue - Java Code
public class ArrayQueue implements Queue { private final static int CAPACITY = 100; private int capacity; private Object[] Q; private int f; private int r; public ArrayQueue() { this(CAPACITY); } public ArrayQueue(int _capacity) { capacity = _capacity; Q = new Object[capacity]; f = r = 0; public int size() { // your code goes here! (Practical 6) public boolean isEmpty() { Analysis of Algorithms
48
Array-Queue Java code - Con’d
public void enqueue(Object o) throws QueueFullException { // your code goes here! (Practical 6) } public Object front() throws QueueEmptyException { public Object dequeue() throws QueueEmptyException { Analysis of Algorithms
49
Linked lists Analysis of Algorithms
50
Linked lists Arrays are one way to implement Stacks, queues, etc. Linked Lists are another -- extremely flexible and general idea! Linked list = “Node” objects connected in a “chain” by links (object references) Special “entry point” reference null Stored values (eg, Strings) Boxes are “Node” objects (not ‘built in’ -- you must define/manage them!) Analysis of Algorithms
51
Node objects class Node { Node next; // the next Node in the list
Object element; // the data } Wow - a class defined in terms of itself! Don’t be scared….. element next “Rome” Analysis of Algorithms Null means “end of list”
52
A useful trick Two special entry points null head tail
If we maintain these two special entry points, it is easy to delete or insert entries at the “head” and insert entries at the “tail” (but still tricky to delete entries at the “tail” -- why??!) insert delete Analysis of Algorithms
53
Removing at the Head 1. 2. removed item Analysis of Algorithms
54
Inserting at the Tail new item 1. 2. Analysis of Algorithms
55
The point of all this is….. Using linked lists to implement Queue
Leave queue enter queue null The head of the list is the front of the queue, and the tail of the list is the rear of the queue. Why not the opposite? LinkedListQueue is an alternative implementation of Queue to ArrayQueue. Unlimited capacity -- no wasted memory, no more QueueFullException Analysis of Algorithms
56
Linked List implementation of Queue - Java
public class LinkedListQueue implements Queue { private Node front; private Node rear; private int size; private class Node { // Node is an “inner” class since no one else will ever need it Object element; Node next; Node(Object _element, Node _next) { element = _element; next = _next; } public LinkedListQueue() { front = rear = null; size = 0; Guarantees we’ll provide same methods as ArrayQueue … Analysis of Algorithms
57
LinkedListQueue - continued
public int size() { return size; } public boolean isEmpty() { return size==0; public void enqueue(Object o) { // your code goes here -- Practical 6! public Object front() throws QueueEmptyException { public Object dequeue() throws QueueEmptyException { Analysis of Algorithms
58
Deques 2 detours: more O(.), pointers/references, then… This week:
- complete P5 - start P6 - read Chapter 5 Next week: - no lecture Monday - bank holiday! Analysis of Algorithms
59
Digression 1. More O(·) “3n n is O(n2)” means “as n gets larger, eventually n2 becomes larger than 3n2+100n (when linearly scaled up) n0 = c = 4 n>n0 cn2>3n2+100 “eventually” n0 Analysis of Algorithms
60
More O(·) “f(n) is O(g(n))” means “as n gets larger, eventually f(n) becomes larger than g(n) (when linearly scaled up by some amount) n0 = ? c = ? n>n0: c·g(n)>f(n) numbers you need to find in order to prove that f(n) is O(g(n)) c·g(n) f(n) g(n) Analysis of Algorithms n n0
61
O(·) cheat-sheet The formal (c,no) definition is needed sometimes, but usually the following simple rules of thumb suffices: Discard all constants Discard all lower-order terms 3n n O(n2+n) O(n2) (n2 log n)/ n O(n2 log n+n) O(n2 log n) Analysis of Algorithms
62
Digression 2. References/pointers
Java objects often refer to other objects: age name ppsn Fred 37 328723F class Person { Person f = new Person(); int age; f.age = 37; String name; f.name = “Fred”; String ppsn; f.ppsn = “328723F”; } These referred objects aren’t literally “inside” the object, but it’s easy to visualize the object this way, and it doesn’t cause any confusion. A pedant might draw the following diagram instead: age name ppsn arrows mean “refers to object” 37 Fred 328723F Analysis of Algorithms
63
References, con’t In some cases, these more accurate drawings can help clear up some confusion Person people[] = new Person[2]; Person f = new Person(); f.age = 37; f.name = “Fred”; f.ppsn = “328723F”; people[0] = f; people[1] = f; people[0].name = “Joe”; System.out.println(“First person’s is ” + people[1].name); age name ppsn people[0] people[1] 37 Fred 328723F Analysis of Algorithms
64
Make sure you understand such a beast!
Reference’s con’t Returning to our Linked-List diagrams… class Node { Node next; Object element; } Node head = new Node(); // 1 head.element = “Rome”; head.next = new Node(); // 2 head.next.element = “Seattle”; head.next.next = new Node(); // 3 head.next.next.element = “Toronto”; head.next.next.next = null; this code generates this list Make sure you understand such a beast! Analysis of Algorithms
65
Deque = Double-Ended Queues
A double-ended queue, or deque, supports insertion and deletion from the front and back. The Deque Abstract Data Type insertFirst(e): Insert e at the deginning of deque. insertLast(e): Insert e at end of deque removeFirst(): Removes and returns first element removeLast(): Removes and returns last element first() returns first element last() returns last element size() returns number of elements isEmpty() is this deque empty? Analysis of Algorithms
66
Implementing Stacks & Queues with Deques
Stacks with Deques: Queues with Deques: Analysis of Algorithms
67
The Adaptor Pattern “Patterns” are recurring typical solutions to software design problems (see Section 2.6) Programming languages don’t provide constructs that support for patterns (whereas they do provide constructs supporting modularity, encapsulation, abstraction, …) Using a deque to implement a stack or queue is an example of the adaptor pattern. An adaptor pattern means that you implement a class by using methods of another class (usually giving them other, more specialized names) In general, adaptor classes specialize more generic classes Two such applications: Specialize a general class by changing some methods. Ex: implementing a stack with a deque. Specialize the types of objects used by a general class. Ex: Defining an IntegerArrayStack class that adapts ArrayStack to only store integers. Analysis of Algorithms
68
Implementing Deques with Doubly Linked Lists
Deletions at the tail of a singly linked list cannot be done in constant time (recall slide 32) To implement a deque, we use a doubly linked list. with special header and trailer nodes A node of a doubly linked list has a next and a prev link. It supports the following methods: setElement(Object e) setNext(Object newNext) setPrev(Object newPrev) getElement() getNext() getPrev() By using a doubly linked list, all the methods of a deque run in O(1) time. head tail class DLNode { Object element; DLNode next; DLNode prev; } insert delete Analysis of Algorithms
69
Implementing Deques with Doubly Linked Lists (cont.)
When implementing a doubly linked lists, we add two special nodes to the ends of the lists: the header and trailer nodes. The header node goes before the first list element. It has a valid next link but a null prev link. The trailer node goes after the last element. It has a valid prev reference but a null next reference. NOTE: the header and trailer nodes are sentinel or “dummy” nodes because they do not store elements. Here’s a diagram of our doubly linked list: Analysis of Algorithms
70
Implementing Deques with Doubly Linked Lists (cont.)
Here’s a visualization of the code for removeLast(). 1. start 2. Slide references 3. done (see page 169 for more examples) Analysis of Algorithms
71
Linked Lists - Summary Linked lists are an extremely flexible, very general idea. Lead to efficient (time + space) implemented of queues, stacks Also, often much simpler (compared to, e.g., Q circular array) Basic idea -- design a Node class that holds the data element(s) as well as references to other (previous, next, …) Nodes as needed. The trick to successful implementation is to draw lots of “boxes and arrows” diagrams to make sure you understand in detail how all the Node references should be manipulated Analysis of Algorithms
72
Summary Abstract data types
Clearly separating specification (interface) from implementation (class) Three simple ADTs stack (LI-FO), queue (FI-FO), deque (LorF-IorO) Two implementation strategies for storing lists arrays (simpler, fixed capacity) linked lists (tricker, ‘infinite’ capacity) Analysis of Algorithms
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.