Lecture 7: Implementing Lists, Version 2

Similar documents
Lecture 7: Lists, Version 2 (with Mutation)

Lecture 5: Implementing Lists, Version 1

Lecture 8: Iterators and More Mutation

Homework 2: Imperative Due: 5:00 PM, Feb 15, 2019

Lecture 17: Implementing HashTables 10:00 AM, Mar 5, 2018

Subclassing for ADTs Implementation

Lecture 14: Exceptions 10:00 AM, Feb 26, 2018

Lecture 11: In-Place Sorting and Loop Invariants 10:00 AM, Feb 16, 2018

CS 151. Linked Lists, Recursively Implemented. Wednesday, October 3, 12

COMP 250 Winter 2011 Reading: Java background January 5, 2011

Homework 2: Imperative Due: 5:00 PM, Feb 16, 2018

Lecture 16: HashTables 10:00 AM, Mar 2, 2018

Lecture 23: Priority Queues 10:00 AM, Mar 19, 2018

Lecture 4: Inheritence and Abstract Classes

Exercise 12 Initialization December 16, 2016

Class 26: Linked Lists

(Provisional) Lecture 08: List recursion and recursive diagrams 10:00 AM, Sep 22, 2017

Announcements. Prelude (2) Prelude (1) Data Structures and Information Systems Part 1: Data Structures. Lecture 6: Lists.

CS18000: Programming I

Lecture 21: The Many Hats of Scala: OOP 10:00 AM, Mar 14, 2018

Abstract Data Types - Lists Arrays implementation Linked-lists implementation

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Comp215: More lists. Dan S. Wallach (Rice University) Copyright 2015, Dan S. Wallach. All rights reserved.

Lab 2: Object-Oriented Design 12:00 PM, Jan 31, 2018

Lists using LinkedList

Linked Lists. College of Computing & Information Technology King Abdulaziz University. CPCS-204 Data Structures I

(Provisional) Lecture 22: Rackette Overview, Binary Tree Analysis 10:00 AM, Oct 27, 2017

Lecture 22: Garbage Collection 10:00 AM, Mar 16, 2018

Topic 6: Inner Classes

Name Section Number. CS210 Exam #1 *** TURN OFF ALL ELECTRONIC DEVICES *** Practice

The list abstract data type defined a number of operations that all list-like objects ought to implement:

CMSC 341 Lecture 7 Lists

CS2102: Lecture on Abstract Classes and Inheritance. Kathi Fisler

Introduction to Linked Data Structures

An Introduction to Data Structures

3. Design by Contract

Homework 4: Hash Tables Due: 5:00 PM, Mar 9, 2018

(Provisional) Lecture 20: OCaml Fun!

CSE 505: Concepts of Programming Languages

Exercise 12 Initialization December 15, 2017

Lab 9: More Sorting Algorithms 12:00 PM, Mar 21, 2018

Linked Lists. private int num; // payload for the node private Node next; // pointer to the next node in the list }

Object-Oriented Design Lecture 3 CSU 370 Fall 2007 (Pucella) Friday, Sep 14, 2007

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

CS112 Lecture: Defining Classes. 1. To describe the process of defining an instantiable class

Lab 4: Imperative & Debugging 12:00 PM, Feb 14, 2018

Exercise 12 Initialization December 14, 2018

Matching & more list functions

Arrays. COMS W1007 Introduction to Computer Science. Christopher Conway 10 June 2003

CSci 4223 Lecture 12 March 4, 2013 Topics: Lexical scope, dynamic scope, closures

Good Coding Practices Spring 2018

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

CS152: Programming Languages. Lecture 7 Lambda Calculus. Dan Grossman Spring 2011

Recursive Data and Recursive Functions

ITI Introduction to Computing II

Lab 4: Super Sudoku Solver CSCI 2101 Fall 2017

20 Subclassing and Mutation

Case Study: Undefined Variables

CS 455 Midterm Exam 1 Fall 2016 [Bono] Thursday, Sept. 29, 2016

Homework 8: Matrices Due: 11:59 PM, Oct 30, 2018

Notes on access restrictions

Lecture 19: Signatures, Structures, and Type Abstraction

Specifications for the ADT List Ali list provides a way to organize data List of students List of sales List of lists

CSCI-1200 Data Structures Spring 2018 Lecture 14 Associative Containers (Maps), Part 1 (and Problem Solving Too)

Homework 7: Subsets Due: 11:59 PM, Oct 23, 2018

ITI Introduction to Computing II

Classes Classes 2 / 35

Homework 5: Fun with Scala Due: 5:00 PM, Mar 16, 2018

CS103 Handout 29 Winter 2018 February 9, 2018 Inductive Proofwriting Checklist

COSC 2P91. Introduction Part Deux. Week 1b. Brock University. Brock University (Week 1b) Introduction Part Deux 1 / 14

Scala Style Guide Spring 2018

Object-Oriented Design Lecture 11 CS 3500 Spring 2010 (Pucella) Tuesday, Feb 16, 2010

The Design Recipe Fall 2017

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Lab 10: Sockets 12:00 PM, Apr 4, 2018

Computer Science 1 Ah

Binghamton University. CS-140 Fall Problem Solving. Creating a class from scratch

Programming Languages and Techniques (CIS120)

1/22/13. Queue? CS 200 Algorithms and Data Structures. Implementing Queue Comparison implementations. Photo by David Jump 9. Colorado State University

Enums. In this article from my free Java 8 course, I will talk about the enum. Enums are constant values that can never be changed.

1/22/13. Queue. Create an empty queue Determine whether a queue is empty Add a new item to the queue

Why Design by Contract! CS 619 Introduction to OO Design and Development. Design by Contract. Fall 2012

Programming II (CS300)

CS125 : Introduction to Computer Science. Lecture Notes #38 and #39 Quicksort. c 2005, 2003, 2002, 2000 Jason Zych

Queue? Part 4. Queues. Photo by David Jump. Create an empty queue Items leave a queue from its front.

List ADT. Announcements. The List interface. Implementing the List ADT

Programming Languages and Techniques (CIS120)

CS 455 Midterm 2 Spring 2018 [Bono] Apr. 3, 2018

Homework 3: Recursion Due: 11:59 PM, Sep 25, 2018

3 ADT Implementation in Java

Lecture 7: Data Abstractions

Object-oriented programming. and data-structures CS/ENGRD 2110 SUMMER 2018

OCaml Style Guide Fall 2017

Review: Using Imported Code. What About the DrawingGizmo? Review: Classes and Object Instances. DrawingGizmo pencil; pencil = new DrawingGizmo();

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

Java Magistère BFA

Total Score /15 /20 /30 /10 /5 /20 Grader

Inf1-OOP. OOP Exam Review. Perdita Stevens, adapting earlier version by Ewan Klein. March 16, School of Informatics

Racket Style Guide Fall 2017

Last time s big ideas

Transcription:

CS18 Integrated Introduction to Computer Science Fisler, Nelson Lecture 7: Implementing Lists, Version 2 Contents 1 The Impact of addfirst on Lists 1 2 Mutating List Contents 2 2.1 The Basic List Classes................................... 2 2.2 List Invariants....................................... 3 2.3 Implementing addfirst................................... 4 2.4 Getting the First Element................................. 5 3 Aside 1: Node as an Inner Class 5 4 Aside 2: Allowing Any Type of Elements 5 4.0.1 Integer vs int.................................... 6 Objectives By the end of this lecture, you will know: ˆ How functional and mutating implementations of LinkedLists differ from one another By the end of this lecture, you will be able to: ˆ Implement LinkedLists whose contents change on add and remove operations ˆ Create inner classes ˆ Define a class that is parameterized by a field type ˆ Write a while loop to traverse a data structure in Java 1 The Impact of addfirst on Lists Consider the following sequence of let-like expressions that use our previous definition of lists. What do you expect this code fragment to print? LinkedList L1 = (new EmptyList()).addFirst(9).addFirst(3); LinkedList L2 = L1.addFirst(7); LinkedList L3 = L1.addFirst(5); System.out.println(L1.head());

There are two plausible answers: 3 and 5. If addfirst returns a new list without modifying the existing one (the behavior in Racket and OCaml), you d get 3. If addfirst modifies the list object when adding an element, you d get 5. Each behavior is desirable in certain situations. So let s look at a second implementation of lists, this time one that would return 5 in the above scenario. Specifically, we are looking to support the following ListTest class, with 5 being printed out when the main method is run: public class ListTest { static LinkedList L1 = new LinkedList(); public static void main(string[] args) { L1.addFirst(3); L1.addFirst(5); L1.addLast(8); System.out.println(L1.getFirst()); // want to see 5 2 Mutating List Contents 2.1 The Basic List Classes As before, the heart of our list implementation is a Node class that stores an item and a link to the next item in the list. In keeping with typical idioms of programming with mutation (called imperative programming, in contrast to functional programming), we ll name the rest field next. class Node { int item; Node next; Node(int item, Node next) { this.item = item; this.next = next; /** * return the item in a node */ public int getitem() { return this.item; In our first implementation, we represented a list by the node that holds the first element in the list. Since the contents of the list never changed, that representation worked fine. But here, as we add elements, the first item will keep changing. We want a programmer to have a fixed object that represents the list, even as the elements change. So we will need a separate class for the list, which has a field that refers to the current first item on the list. It will also be handy for this class 2

to have a field that refers to the end of the list (so we can optionally add items to the end, rather than the beginning, of a list). public class LinkedList implements IList { public LinkedList() { this.start =???; this.end =???; When we create a new list, what should the constructor do with the start and end fields? They should get a value that signals that there are no contents yet, akin to our EmptyList objects from the first implementation. A pure OO implementation would set these to an object from a separate class such as NoNode. In practice, this isn t what Java programmers do. Instead, they use a Java construct called null, which, like void, is a way of saying no information (null can be used in place of an object in field values without triggering compiler errors). The use of null here is a bit off, because we don t have no information we actually know that there is no list contents here. However, using null is idiomatic Java practice so we show it to you here. But don t abuse it. You should really only use null when you really have no information about the object in question. public class LinkedList implements IList { public LinkedList() { this.start = null; this.end = null; 2.2 List Invariants Before we start to implement the methods, let s step back and think a bit about the start and end fields. For our lists to behave properly, our methods have to maintain certain properties about these fields. The technical term for such properties is invariants. An invariant is a boolean predicate that should be true about our data before and after each method call. In our implementation of linked lists, we will maintain the following invariants: 1. When the linked list is empty, ˆ start is null ˆ end is null 2. When the linked list is nonempty, 3

ˆ start refers to the first node of the list ˆ end refers to the last node of the list ˆ if the list contains exactly one node, then both start s and end s next fields are null ˆ if the list contains more than one node, then only end.next is null; no other node s next field is null. Are the invariants true about LinkedList objects after the constructor has finished? Yes te list is empty, and both start and end are null. With this, let s go on to write addfirst. 2.3 Implementing addfirst Here s a first attempt at writing addfirst: public void addfirst(int newitem) { Node newnode = new Node(newItem, this.start); this.start = newnode; Are you satisifed with this definition? A good strategy here is to check it against the invariants. Assume the invariants were true before the call to addfirst are they still true afterwards? Not quite we have start referring to the first item in the list, but if the list had been empty before calling addfirst, then end still refers to null, rather than the new Node. This suggests the following modification: public void addfirst(int newitem) { Node newnode = new Node(newItem, this.start); this.start = newnode; if (this.end == null) { this.end = newnode; You should work through all the invariants and convince yourself that this method preserves them. The process of writing addlast is similar, though it raises a couple of interesting tidbits: ˆ A helper method that determines whether the list is empty makes the code a bit cleaner ˆ When adding a element to the end of a list, the next field of the Node for the new element will remain null. It s useful to have a second constructor in the Node class that only takes the element, and internally sets the next field to null (the source code posted with this lecture shows both constructors in the Node class). boolean isempty() { return ((this.start == null) && (this.end == null)); 4

public void addlast(int newitem) { if (this.isempty()) { this.addfirst(newitem); else { Node newnode = new Node(newItem); this.end.next = newnode; this.end = newnode; 2.4 Getting the First Element public int getfirst() { return this.start.getitem(); With the addition of getfirst, our desired ListTest class runs as desired. 3 Aside 1: Node as an Inner Class Now that we have addfirst on linked lists, we never create nodes directly. Only the LinkedList class creates nodes. This suggests that Node is really more of a helper class, than a class in its own right. How can we capture the idea that only the LinkedList class should be allowed to create nodes? (Note that this is a very different situation from making classes abstract here we need to be able to create nodes, we just want to limit which class can create them). The solution is to define the Node class inside the LinkedList class. This is sort of like defining one function inside of another (like a local lambda) in Racket. Such inner classes aren t visible outside their enclosing class, so we get the restriction we want: public class LinkedList implements IList { // the LinkedList fields // the inner class class Node { int item; Node next; // the LinkedList methods public void addfirst(int newitem) { The posted source code shows this version of the class layout. 5

4 Aside 2: Allowing Any Type of Elements As of now, we can only create lists of ints, which is rather limiting. We would like to be able to create lists of strings, students, animals, and so on. Nearly all of the code would be the same as what we have now, aside from the type of item in the Node class. Surely there is a way to be flexible on the types without having to copy all of this code for every new type!?! Indeed there is. Java actually allows classes to take separate type parameters. The notation <T> after a class name introduces a type parameter named T (you can use any name you want it doesn t have to bet). You can then use T in place of any type that should come from the parameter. Here s the skeleton of the LinkedList class with the type parameter. public class LinkedList<T> implements IList<T> { // the LinkedList fields // the inner class class Node { T item; Node next; // the LinkedList methods public void addfirst(t newitem) { Notice that we use T for both the type of the item in a Node, as well as for the input type of addfirst. (You can have multiple type parameters, separated by commas, in the class annotation, should you need that we ll see uses of that in a couple of weeks). How does this change how we create LinkedList objects? Here s ListTest rewritten to use the type parameter: public class ListTest { static LinkedList<Integer> L1 = new LinkedList<Integer>(); public static void main(string[] args) { L1.addFirst(3); L1.addFirst(5); L1.addLast(8); System.out.println(L1.getFirst()); When we write down the type of a list variable, or when we use the constructor, we provide a concrete type to use for the item. 6

4.0.1 Integer vs int Here we are using Integer, rather than the int we have been using. Basically, Integer is a class that contains an int, whereas int is just a numeric constant. Anytime you are in a context that needs integers as objects, use the type Integer instead. The same distinction holds for Boolean vs boolean and String vs string. Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CS18 document by filling out the anonymous feedback form: http://cs.brown.edu/ courses/cs018/feedback. 7