Problem Solving with Data Structures using Java: A Multimedia Approach

Slides:



Advertisements
Similar presentations
Stacks, Queues, and Linked Lists
Advertisements

Discrete Event Simulation CS1316: Representing Structure and Behavior.
Stack & Queues COP 3502.
0 of 37 Stacks and Queues Lecture of 37 Abstract Data Types To use a method, need to know its essentials: signature and return type o additionally,
Stacks, Queues, and Deques. 2 A stack is a last in, first out (LIFO) data structure Items are removed from a stack in the reverse order from the way they.
Elementary Data Structures CS 110: Data Structures and Algorithms First Semester,
Chapter 5 Queues Modified. Chapter Scope Queue processing Comparing queue implementations 5 - 2Java Software Structures, 4th Edition, Lewis/Chase.
CS Data Structures II Review COSC 2006 April 14, 2017
Abstract Data Types (ADT) Collection –An object that can hold a list of other objects Homogeneous Collection –Contains elements all of the same type –Example:
Stacks, Queues, and Deques
Unit 11 1 Unit 11: Data Structures H We explore some simple techniques for organizing and managing information H This unit focuses on: Abstract Data Types.
CHAPTER 6 Stacks Array Implementation. 2 Stacks A stack is a linear collection whose elements are added and removed from one end The last element to be.
Stack: Linked List Implementation Push and pop at the head of the list New nodes should be inserted at the front of the list, so that they become the top.
30-Jun-15 Stacks. What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on the “top” of the stack Anything.
1 Lecture 26 Abstract Data Types – IV Overview  The List ADT  Implementing Stacks as Linked List  Linked List Implementation of Queues .  Preview:
Stacks, Queues, and Deques
Stacks, Queues, and Deques. A stack is a last in, first out (LIFO) data structure –Items are removed from a stack in the reverse order from the way they.
Stacks, Queues, and Deques
Building Java Programs
Topic 3 The Stack ADT.
Implementing Stacks Ellen Walker CPSC 201 Data Structures Hiram College.
Chapter 3 Introduction to Collections – Stacks Modified
Lists ADT (brief intro):  Abstract Data Type  A DESCRIPTION of a data type  The data type can be anything: lists, sets, trees, stacks, etc.  What.
CM0551 Exam Prep. What are an algorithm’s time and space complexity? (2 marks) Answer: The growth rate of the algorithm’s time requirement and the computer.
JAVA COLLECTIONS LIBRARY School of Engineering and Computer Science, Victoria University of Wellington COMP T2, Lecture 2 Marcus Frean.
© 2004 Goodrich, Tamassia Stacks. © 2004 Goodrich, Tamassia Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data.
CSE 12 – Basic Data Structures Cynthia Bailey Lee Some slides and figures adapted from Paul Kube’s CSE 12 CS2 in Java Peer Instruction Materials by Cynthia.
Stacks. A stack is a data structure that holds a sequence of elements and stores and retrieves items in a last-in first- out manner (LIFO). This means.
1 Chapter 7 Stacks and Queues. 2 Stack ADT Recall that ADT is abstract data type, a set of data and a set of operations that act upon the data. In a stack,
COMP 103 Linked Lists. 2 RECAP-TODAY RECAP  Linked Structures: LinkedNode  Iterating and printing Linked Nodes  Inserting and removing Linked Nodes.
30 May Stacks (5.1) CSE 2011 Winter Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data structure An.
Data structures Abstract data types Java classes for Data structures and ADTs.
1 The Stack Class Final Review Fall 2005 CS 101 Aaron Bloomfield.
Stacks and Queues. 2 3 Runtime Efficiency efficiency: measure of computing resources used by code. can be relative to speed (time), memory (space), etc.
CIS3023: Programming Fundamentals for CIS Majors II Summer 2010 Ganesh Viswanathan Generics and Collections Course Lecture Slides 19 th July 2010 “Never.
Chapter 12: Collections by Lewis and Loftus (Updated by Dan Fleck) Coming up: Collections.
C++ How to Program, 9/e © by Pearson Education, Inc. All Rights Reserved.
(c) University of Washington16-1 CSC 143 Java Linked Lists Reading: Ch. 20.
(c) University of Washington16-1 CSC 143 Java Lists via Links Reading: Ch. 23.
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Data Structures in Java: From Abstract Data Types to the Java Collections.
CS 367 Introduction to Data Structures Lecture 5.
Week 5 - Wednesday.  What did we talk about last time?  Recursion  Definitions: base case, recursive case  Recursive methods in Java.
Lecture Objectives  To understand how Java implements a stack  To learn how to implement a stack using an underlying array or linked list  Implement.
Chapter 5 Array-Based Structures © 2006 Pearson Education Inc., Upper Saddle River, NJ. All rights reserved.
ITI Introduction to Computing II Lab-5 Dewan Tanvir Ahmed University of Ottawa.
2005MEE Software Engineering Lecture 7 –Stacks, Queues.
JAVA COLLECTIONS LIBRARY School of Engineering and Computer Science, Victoria University of Wellington COMP T2, Lecture 2 Marcus Frean.
“The desire for safety stands against every great and noble enterprise.” – Tacitus Thought for the Day.
Computer Science Department Data Structure and Algorithms Lecture 3 Stacks.
Chapter 4 ADTs Stack and Queue. 4-2 Formal ADT Specifications The Java interface construct lets us collect together method interfaces into a syntactic.
M180: Data Structures & Algorithms in Java Stacks Arab Open University 1.
3-1 Java's Collection Framework Another use of polymorphism and interfaces Rick Mercer.
Click to edit Master text styles Stacks Data Structure.
1 Stacks Abstract Data Types (ADTs) Stacks Application to the analysis of a time series Java implementation of a stack Interfaces and exceptions.
Stacks as an Abstract Data Type CS1316: Representing Structure and Behavior.
Linked Data Structures
Chapter 6: The Stack Abstract Data Type
Week 3 - Friday CS221.
Stacks.
Chapter 6: The Stack Abstract Data Type
Queues Queues Queues.
The Stack ADT. 3-2 Objectives Define a stack collection Use a stack to solve a problem Examine an array implementation of a stack.
Stack and Queue APURBO DATTA.
Stacks Abstract Data Types (ADTs) Stacks
Stacks.
Stacks as an Abstract Data Type
More Data Structures (Part 1)
CSC 143 Java Linked Lists.
Stacks, Queues, and Deques
Stacks.
Presentation transcript:

Problem Solving with Data Structures using Java: A Multimedia Approach Chapter 11: Abstract Data Types: Separating the Meaning from the Implementation

Chapter Objectives

Separating Meaning from Implementation Powerful engineering idea in computer science. Meaning Identify the behavior of an object or data structure. Build other program components to interact with that behavior. Implementation Hide how that behavior is implemented, so that no program components can be dependent on the implementation.

Abstract Data Type: Stacks An example of an Abstract Data Type (ADT): We can define the methods and the behavior apart from any implementation. There are multiple implementations, some better than others. Can use a stack to reverse a list in less time, but more space. A classic tradeoff! Space for time. Only put on top, Never pull from bottom.

A Stack is a LIFO List Last-In-First-Out (LIFO) List First item in the list is the last one out. Last one in is first one out. I got here third! I got here second! I got here first! This is the top of the stack

New items go at the top I got here fourth! I got here third! I got here second! I got here first! This is the new top of the stack

Items only get removed from the top I got here fourth! And now I’m outta here! I got here third! I got here second! I got here first! This is the new (er, old) top of the stack

What can we do with stacks? push(anObject): Tack a new object onto the top of the stack pop(): Pull the top (head) object off the stack. peek(): Get the top of the stack, but don’t remove it from the stack. size(): Return the size of the stack

Separation of Concerns Separation definition of behavior of data structure from implementation. Lets one change without changing the other. Java allows us to use an interface as a way specify that behavior definition.

Stack Interface Just defining the operations here. /** * An abstract definition of a stack * @author Barb Ericson */ public interface Stack<E> { * Method to add the element to the top of the stack * @param element the element to add public void push(E element); * Method to return the top element on the * stack, but not remove it from the stack * @return the top object from the stack public E peek(); Stack Interface Just defining the operations here. E is the type of the things in the Stack. Stack<E> represents the generic stack for any time element

/** * Method to remove the top element from the * stack and return it * @return the top element from the stack */ public E pop(); * Method to return the number of elements in * the stack * @return the number of elements in the stack public int size(); * Method to check if the stack is empty * @return true if empty, else false public boolean isEmpty(); }

Creating an implementation We declare a class as implementing that interface. We can continue to use the <E> generic, so that we can later create a stack for any type object.

import java. util. LinkedList; // Need for LinkedList / import java.util.LinkedList; // Need for LinkedList /** * Class that represents a stack using a linked list * of objects * @author Mark Guzdial * @author Barb Ericson */ public class LinkedListStack<E> implements Stack<E> { /** Where we store the elements */ private LinkedList<E> elements; * Constructor that takes no arguments public LinkedListStack() { elements = new LinkedList<E>(); } Stack as a LinkedList

//// Methods /// /** * Method to add an element to the stack * @param element the element to add */ public void push(E element) { // New elements go at the front elements.addFirst(element); } * Method to return the top element on the stack * but leave the element on the stack * @return the top element on the stack public E peek() { return elements.getFirst();

/. Method to remove the top element from a stack. and return it /** * Method to remove the top element from a stack * and return it * @return the top element from the stack and remove it */ public E pop() { E toReturn = this.peek(); elements.removeFirst(); return toReturn; } * Method to get the number of elements in the stack * @return the number of elements in the stack public int size(){return elements.size();} * Method to test if the stack is empty * @return true if the stack is empty, else false public boolean isEmpty() { return (size() == 0);

Using the Stack with Strings > Stack<String> stack = new LinkedListStack<String>(); > stack.push("This") > stack.push("is") > stack.push("a") > stack.push("test") > stack.size() 4 > stack.peek() "test" > stack.pop() "a" "is" "This" Notice the use of <String>

> Stack<Picture> stack = new LinkedListStack<Picture>(); > stack.push(new Picture(FileChooser.getMediaPath("beach.jpg"))); > stack.push(new Picture(FileChooser.getMediaPath("arch.jpg"))); > stack.push(new Picture(FileChooser.getMediaPath("bridge.jpg"))); > stack.size() 3 > stack.peek() Picture, filename C:\dsBook\media-source/bridge.jpg height 640 width 480 > stack.pop() Picture, filename C:\dsBook\media-source/arch.jpg height 480 width 360 Picture, filename C:\dsBook\media-source/beach.jpg height 480 width 640 A Stack of Pictures Note: You can’t create an object using an interface name, e.g., new Stack<String>()

A stack is a stack, no matter what lies beneath. Our description of the stack minus the implementation is an example of an abstract data type (ADT). An abstract type is a description of the methods that a data structure knows and what the methods do. We can actually write programs that use the abstract data type without specifying the implementation. There are actually many implementations that will work for the given ADT. Some are better than others.

New implementation: Stack as Array /** * Implementation of a stack as an array * @author Mark Guzdial * @author Barb Ericson */ public class ArrayStack<E> implements Stack<E> { /** default size of the array */ private static final int ARRAY_SIZE = 20; /** Where we'll store our elements */ private Object[] elements;

Constructor /** Index where the top of the stack is */ private int top; /** * No argument constructor */ public ArrayStack() { elements = new Object[ARRAY_SIZE]; top = 0; }

Methods for Stack as Array /** * Method to add an element to the top of the stack * @param element the element to add */ public void push(E element) { // New elements go at the top elements[top]=element; // then add to the top top++; if (top==ARRAY_SIZE) { System.out.println("Stack overflow!"); }

/. Method to return the top element on the stack. but not remove it /** * Method to return the top element on the stack * but not remove it. * @return the object at the top of the stack */ public E peek() { if (top==0) { System.out.println("Stack empty!"); return null; } else { // this will give a warning but it is unavoidable return (E) elements[top-1]; }

/** * Method to remove and return the top element on the stack * @return the element on the top of the stack */ public E pop() { E toReturn = this.peek(); top--; return toReturn; } * Method to return the number of elements in the stack * @return the number of elements in the stack public int size(){return top;} * Method to check if the stack is empty * @return true if the stack is empty else false public boolean isEmpty() {return this.size() == 0;}

Trying out Stack as Array > Stack<String> stack = new ArrayStack<String>();

Pushing one element > stack.push("Matt");

Push two more, pop one > stack.push("Katie"); > stack.push("Jenny"); > stack.size() // without the ending ';' it prints out the result 3 > stack.peek() // without the ending ';' it prints out the result "Jenny" > stack.pop()

Critique the array-based implementation What happens if the number of elements in the stack is more than 20?

What are stacks good for? The algorithm for converting an equation into a tree uses a stack. Often use stacks when describing card games, like solitaire. The list of Web pages you have visited in a browser is stored in a stack, so that you can go “back.” The list of operations you have executed is stored in a stack, so that you can “undo.”

Stacks describe function calls As new functions get called, position in old functions get pushed on a stack. So you always return to the last function you were in. If an error occurs, you get a stack trace. If your recursion goes into an infinite loop, what error do you get? Stack overflow!

A Stack Example: New Reverse Recall our original implementation of reverse(). We go to the end of the original list to find the last(). We then remove() it (which involves walking the list until we find the one before last()) We then insert it at the end of the new list (via add(), which does last().insertAfter()). All told: For each node, we walk the whole list three times. O(n*n2)=O(n3)

/** * Reverse the list starting at this, * and return the last element of the list. * The last element becomes the FIRST element * of the list, and THIS points to null. */ public LayeredSceneElement reverse() { LayeredSceneElement reversed, temp; // Handle the first node outside the loop reversed = this.last(); this.remove(reversed); while (this.getNext() != null) { temp = this.last(); this.remove(temp); reversed.add(temp); } // Now put the head of the old list on the end of // the reversed list. reversed.add(this); // At this point, reversed // is the head of the list return reversed; Original Reverse Highly inefficient. Touching each node requires touching every other node: O(n2)

New Reverse: Push all, pull off reversed /** * Reverse2: Push all the elements on * the stack, then pop all the elements * off the stack. */ public LayeredSceneElement reverse2() { LayeredSceneElement reversed, current, popped; Stack<LayeredSceneElement> stack = new LinkedListStack<LayeredSceneElement>();

// Push all the elements on the list current=this; while (current // Push all the elements on the list current=this; while (current != null) { stack.push(current); current = current.getNext(); } // Make the last element (current top of stack) into new first reversed = stack.pop(); // Now, pop them all onto the list current = reversed; while (stack.size()>0) { popped = stack.pop(); current.insertAfter(popped); current = popped; return reversed;

What’s the diff? Time How often is each node touched in reverse2()? Twice: Once going onto the stack, once coming off. O(2*n) => O(n) The stack-based reverse is faster than the original reverse.

What’s the diff? Space How much space does reverse2() take? Whatever space the stack takes. How much additional space does reverse() take? None Very common tradeoff: Space for time. You can make an algorithm go faster, by using more space. If you need to fit into less memory, you have to do more processing, which takes more time.

Testing Reverse in SoundListTest() public void reverseTest(){ Sound s = null; // For copying in sounds s = new Sound(FileChooser.getMediaPath("guzdial.wav")); SoundNode root = new SoundNode(s); s = new Sound(FileChooser.getMediaPath("is.wav")); SoundNode one = new SoundNode(s); root.last().insertAfter(one); s = new Sound(FileChooser.getMediaPath("scritch-q.wav")); SoundNode two = new SoundNode(s); root.last().insertAfter(two); s = new Sound(FileChooser.getMediaPath("clap-q.wav")); SoundNode three = new SoundNode(s); two.insertAfter(three); //root.playFromMeOn(); SoundNode reversed = (SoundNode) root.reverse2(); reversed.playFromMeOn(); }

Second ADT: Introducing a Queue First-In-First-Out List First person in line is first person served I got here third! I got here second! I got here first! This is the tail of the queue This is the front or head of the queue

First-in-First-out New items only get added to the tail. Never in the middle Items only get removed from the head. I got here third! I got here second! I got here first! This is the tail of the queue This is the front or head of the queue

As items leave, the head shifts I got here third! I got here second! I got here first! AND NOW I’M UP! This is the tail of the queue Now, this is the front or head of the queue Served!

As new items come in, the tail shifts I got here fourth! I got here third! I got here second! Now, this is the tail of the queue Now, this is the front or head of the queue

Queue Operations push(element): Tack a new element onto the tail (end) of the queue. pop(): Pull the top (head) element off the queue. peek(): Get the head of the queue, but don’t remove it from the queue. size(): Return the size of the queue. isEmpty(): Return true or false, if the size of the queue is zero.

Queue Interface /** * Interface to define an abstract queue * @author Barb Ericson */ public interface Queue<E> { * Push an element onto the tail of the Queue * @param element the element to add to the queue public void push(E element); * Peek at, but don't remove, the head of the queue * @return the head of the queue (top) public E peek(); Queue Interface

/. Pop an object from the Queue /** * Pop an object from the Queue * @return the head (top) of the queue and * remove it from the queue */ public E pop(); * Return the size of a queue * @return the number of elements in the queue public int size(); * Method to see if the queue is empty * @return true if the queue is empty, else false public boolean isEmpty(); }

Implementing a Queue as a Linked List import java.util.*; // LinkedList representation /** * Implements a simple queue using a linked list * @author Mark Guzdial * @author Barb Ericson */ public class LinkedListQueue<E> extends AbstractQueue<E> { /** Where we'll store our elements */ private LinkedList<E> elements;

/. No argument constructor /** * No argument constructor */ public LinkedListQueue() { elements = new LinkedList<E>(); } /// Methods * Push an element onto the tail of the Queue * @param element the element to add to the queue public void push(E element) { elements.addFirst(element); * Peek at, but don't remove, top (first) of queue * @return the first object in the queue public E peek() { return elements.getLast();

//. Pop an object from the Queue //** * Pop an object from the Queue * @return the top object from the queue (and remove it) */ public E pop() { E toReturn = this.peek(); elements.removeLast(); return toReturn; } /** * Return the size of a queue * @return the number of elements in the queue public int size() { return elements.size(); } * Method to see if the queue is empty * @return true if the queue is empty, else false public boolean isEmpty() { return size() == 0; }

Testing our implementation: Behaving as expected? > Queue<String> line = new LinkedListQueue<String>(); > line.push("Fred"); > line.push("Mary"); > line.push("Jose"); > line.size() 3 > line.peek() // without ending ';' prints the result "Fred" > line.pop() > line.peek() "Mary" "Jose" Testing our implementation: Behaving as expected?

/. Implements a simple queue using an array. @author Mark Guzdial /** * Implements a simple queue using an array * @author Mark Guzdial * @author Barb Ericson */ public class ArrayQueue<E> extends AbstractQueue<E> { /** constant for the size of the queue */ private static final int ARRAY_SIZE = 20; /** Where we'll store our elements */ private Object[] elements; /** The index of the head */ private int head; /** The index of the tail */ private int tail; Queue as Array

/. No argument constructor /** No argument constructor */ public ArrayQueue() { elements = new Object[ARRAY_SIZE]; head = 0; tail = 0; } /// Methods /** * Push an element onto the tail of the Queue * @param element the element to add to the queue */ public void push(E element) { if ((tail + 1) >= ARRAY_SIZE) { System.out.println("Queue underlying implementation failed");} else { // Store at the tail, // then increment to a new open position elements[tail] = element; tail++;}

/. Peek at, but don't remove, the head of the queue /** * Peek at, but don't remove, the head of the queue * @return the head of the queue (top) */ public E peek() { // this will give a warning but there is no way around it return (E) elements[head]; }

/. Pop an object from the Queue /** * Pop an object from the Queue * @return the head (top) of the queue and * remove it from the queue */ public E pop() { E toReturn = this.peek(); if (((head + 1) >= ARRAY_SIZE) || (head > tail)) { System.out.println("Queue underlying implementation failed."); return toReturn; } else { // Increment the head forward, too. head++;

/. Return the size of a queue /** * Return the size of a queue * @return the number of elements in the queue */ public int size() { return tail-head;} * Method to see if the queue is empty * @return true if the queue is empty, else false public boolean isEmpty() { return size() == 0; } }

Again, testing implementation > Queue<String> line = new ArrayQueue<String>(); > line.push("Fred"); > line.push("Mary"); > line.push("Jose"); > line.size() 3 > line.peek() // without ending ';' prints the result "Fred" > line.pop() > line.peek() "Mary" "Jose"

How the array implementation of queue works An empty queue

Pushing “Matt”

Pushing “Katie”

Popping (returns “Matt”) Notice that we’ve now permanently “lost” the first cell. Challenge: Can you “recover” that cell?

Improving the implementation Our two implementations have duplicated code. Check out isEmpty() in each. Where could we put the code so that it’s not duplicated? Interfaces can’t have method bodies. We can use an abstract class.

Abstract Queue Class /** * Class to define an abstract queue * @author Barb Ericson */ public abstract class AbstractQueue<E> implements Queue<E> { * Push an object onto the Queue * @param element the element to add to the queue public abstract void push(E element);

/. Peek at, but don't remove, the head of the queue /** * Peek at, but don't remove, the head of the queue * @return the head of the queue (top) */ public abstract E peek(); * Pop an object from the Queue * @return the head (top) of the queue and * remove it from the queue public abstract E pop(); * Return the size of a queue * @return the number of elements in the queue public abstract int size();

Finally, the isEmpty method, factored out /** * Method to see if the queue is empty * @return true if the queue is empty, else false */ public boolean isEmpty() { return (size() == 0); }

/. Implements a simple queue using an array. @author Mark Guzdial /** * Implements a simple queue using an array * @author Mark Guzdial * @author Barb Ericson */ public class ArrayQueue extends AbstractQueue { /// ... fields and other methods as before * Method to see if the queue is empty * @return true if the queue is empty, else false // commented out since inherited from AbstractQueue // public boolean isEmpty() { return size() == 0; } } Revised ArrayQueue

Revised LinkedListQueue /** * Implements a simple queue using a linked list * @author Mark Guzdial * @author Barb Ericson */ public class LinkedListQueue extends AbstractQueue { // ... fields and other methods as before * Check if the queue is empty * @return true if no elements in the queue, else false // commented out since inherited from AbstractQueue // public boolean isEmpty() {return this.size() == 0;} } Revised LinkedListQueue

Can switch implementations easily As ArrayList If inserting/deleting a lot, use LinkedList > import java.util.*; > List<String> nameList = new ArrayList<String>(); > nameList.add("Shayna"); > nameList.add("Marcus"); > nameList.add("Jakita"); > nameList [Shayna, Marcus, Jakita] > import java.util.*; > List<String> nameList = new LinkedList<String>(); > nameList.add("Shayna"); > nameList.add("Marcus"); > nameList.add("Jakita"); > nameList [Shayna, Marcus, Jakita] How the List is used (methods and behavior) is the same in both cases.

A Common Pattern We see this structure repeated throughout java.util Interface defines ADT Abstract class defines common parts Concrete classes differ in implementation

Switching implementations Switching the underlying implementation can provide advantages. Of speed Of flexibility For example, our stack implemented as an Array can go out of bounds if grows too large. But not if we use ArrayList!

Using an ArrayList: ArrayListStack import java.util.*; /** * Implementation of a stack as an ArrayList * @author Mark Guzdial * @author Barb Ericson */ public class ArrayListStack<E> implements Stack<E> { /** Where we'll store our elements */ private List<E> list = new ArrayList<E>(); * No argument constructor public ArrayListStack() { } Using an ArrayList: ArrayListStack

//// Methods /// /. Method to add an element to the top of the stack //// Methods /// /** * Method to add an element to the top of the stack * @param element the element to add */ public void push(E element) { list.add(element); } * Method to return the top element on the stack * but not remove it. * @return the object at the top of the stack public E peek() { return list.get(list.size() - 1);

/. Method to remove and return the top element on the stack /** * Method to remove and return the top element on the stack * @return the element on the top of the stack */ public E pop() { return list.remove(list.size() - 1); } * Method to return the number of elements in the stack * @return the number of elements in the stack public int size(){return list.size();}

Main() for testing public static void main(String[] args) { Stack<String> stack = new ArrayListStack<String>(); stack.push("Matt"); stack.push("Katie"); stack.push("Jenny"); System.out.println(stack.size()); System.out.println(stack.peek()); System.out.println(stack.pop()); }

New ADT: A Map A Map associates a value with a key. The key can be any unique object. The value can be any single object. If you store two values under one key, the second value will overwrite the first value as THE value for THAT key.

Using a Map to create oil paintings Oil paintings have only one color for region (size of brush) Using the Java implementation of Map (java.util.Map) to track how often a color (the key) appears in a region. For each region, Store color counts in map. Get most common (highest count) color. Set all colors in region to the most common color.

oilPaint method in Picture /** * Method to do an oil paint effect on a picture * @param dist the distance from the current pixel * to use in the range * @return the new picture */ public Picture oilPaint(int dist) { // create the picture to return Picture retPict = new Picture(this.getWidth(),this.getHeight()); // declare pixels Pixel currPixel = null; Pixel retPixel = null;

// loop through the pixels for (int x = 0; x < this // loop through the pixels for (int x = 0; x < this.getWidth(); x++) { for (int y = 0; y < this.getHeight(); y++) { currPixel = this.getPixel(x,y); retPixel = retPict.getPixel(x,y); retPixel.setColor(currPixel.getMostCommonColorInRange(dist)); } return retPict;

getMostCommonColorInRange in class Pixel /** * Method to return the most common color in the given * range from the current pixel in the picture or just * return this color. * @param dist the distance to use for the range * @return the most common color in this range */ public Color getMostCommonColorInRange(int dist) { Map<Color,Integer> colorMap = new HashMap<Color,Integer>(); Pixel currPixel = null; Integer value = null; Color theKey = null; The variable colorMap is of type Map. We instantiate HashMap, but could switch to another implementation

// loop through the pixels around this one within the distance for (int currY = y - dist; currY <= y + dist; currY++) { for (int currX = x - dist; currX <= x + dist; currX++) { if (currY >= 0 && currY < picture.getHeight() && currX >= 0 && currX < picture.getWidth()) { currPixel = picture.getPixel(currX,currY); theKey = currPixel.getColor(); value = colorMap.get(theKey); if (value == null) colorMap.put(theKey,1); else colorMap.put(theKey, value + 1); }

// find the color that is most common int maxValue = 1; int currValue = 0; theKey = this.getColor(); // use current color as default Set<Color> keySet = colorMap.keySet(); for (Color key : keySet) { currValue = colorMap.get(key); if (currValue > maxValue) { theKey = key; maxValue = currValue; } return theKey;

Example Use