Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java Programming: From the Ground Up

Similar presentations


Presentation on theme: "Java Programming: From the Ground Up"— Presentation transcript:

1 Java Programming: From the Ground Up
Chapter 16 Data Structures and Generics

2 Data Structures A data structure is a collection of data together with a well-defined set of operations for storing, retrieving, managing, and manipulating the data.

3 Data Structures Some elementary data structures: ArrayList Stack Queue
Linked List

4 ArrayList An array holds an indexed contiguous collection of data of a single type. Once an array is instantiated and its size declared, the size cannot be altered. Dynamic arrays, which grow as needed, would offer a convenience not provided by ordinary arrays.

5 ArrayList An ArrayList object is an indexed list of references that can grow as the number of data increases. An ArrayList can resize itself

6 ArrayList Unlike an ordinary array, an ArrayList does not hold primitive values. An ArrayList stores references and only references. Primitive data can be automatically wrapped in objects and subsequently stored in an ArrayList.

7 ArrayList Methods void add(int index, Object o) inserts o at position index. If an element, x, is currently stored at position index, then x and all the elements following x are shifted “down” one position to make room for o, i.e., x is moved to position index+1 and all elements following x are also moved down one position.

8 ArrayList Methods boolean add(Object o)
adds o to the end of the list. The boolean return value is necessary because ArrayList implements Java’s Collection interface. For our purposes, we can ignore the return value.

9 ArrayList Methods void clear() removes all objects from the list.
boolean contains (Object o) returns true if o is a member of the list. Object get(int index) returns the Object reference at position index. boolean isEmpty() returns true if the list has no elements.

10 ArrayList Methods boolean remove (Object o) If o is a member of the list, this method removes the first occurrence of o from the list, returns true, and shifts all elements following o “up” one position, i.e., if x follows o and x is stored in position i then x is moved from position i to position i – 1. Object remove (int index) removes and returns a reference to the object o that is currently at position index; shifts allelements following o up one position.

11 ArrayList Methods Object set (int index, Object o) replaces the object at position index with o; returns a reference to the object that was replaced. int size() returns the number of objects currently in the list. Object [] toArray() returns the objects of a list as an array reference.

12 ArrayList Constructors
public ArrayList(); instantiates an ArrayList that is empty and sets the initial capacity to 10. public ArrayList(int initialSize); instantiates an ArrayList that is empty and sets the initial capacity to initialSize.

13 ArrayList An ArrayList can store Object references.
The following list (anything) ArrayList anything = new ArrayList() can hold references to Integers, Strings, Circles, Airplanes, any Object. However in many applications, an ArrayList is intended to hold a single type of reference. Java provides generics for this purpose.

14 Generics A generic class is one that allows you to specify the data type of one or more fields as a parameter.

15 ArrayList and Generics
The following segment declares and instantiates three different ArrayList objects each capable of holding references to one and only one type of object. ArrayList<Student> students = new ArrayList<Student>(); ArrayList<String> strings = new ArrayList<String>(50); ArrayList<Integer> numbers = new ArrayList<Integer>();

16 ArrayList and Generics
Example The Student class encapsulates a student. A Student object holds a student’s name his/her ID number. The Student class has getter and setter methods. Student overrides the equals(Object o) method inherited from Object so that two students are equal if they have the same name and ID number.

17 ArrayList and Generics
public class Student { private String name; private String id; public Student() name = ""; id = ""; } public Student (String n, String idNum) name = n; id = idNum; public String getName() return name; public String getID() return id;

18 ArrayList and Generics
public void setName(String n) { name = n; } public void setID( String idNum) id = idNum; public boolean equals(Object o) // name and id are the same return ( (((Student)o).name).equals(name) && (((Student)o).id).equals(id) );

19 ArrayList and Generics
Example An Elementary School holds a “Principal for a Day” lottery. A student can participate by entering his/her name and ID number into a pool of candidates. The winner is selected randomly from all entries. Each student is allowed one entry.

20 ArrayList and Generics
Problem Statement Implement a class, StudentLottery, with methods that enter students in the “Principal for a Day” lottery, and pick a winner from the entries. The application should check that no student enters the lottery more than once.

21 ArrayList and Generics
Solution The StudentLottery class uses an ArrayList, entries, to hold Student references. The class has methods: void addStudents() that enters students in the lottery and void pickWinner(). pickWinner() uses the Random class to select one winner from among all student entries. addStudents() checks that there are no duplicate entries. When all students are entered, the name of the winning student and his/her ID are displayed.

22 ArrayList and Generics
import java.util.*; public class SchoolLottery { private ArrayList<Student> entries;// holds Student references public SchoolLottery() entries = new ArrayList<Student>(250); // initial capacity is 250 }

23 ArrayList and Generics
public void addStudents() { // prompts for student names and ID numbers // adds students to entries list // does not allow duplicate entries Scanner input = new Scanner(System.in); System.out.println("Press Enter to end input"); System.out.print("Name: "); String name = input.nextLine();

24 ArrayList and Generics
do { System.out.print("ID: "); String id = input.nextLine(); Student student = new Student(name, id); if (!entries.contains(student)) //only one entry per student entries.add(student); System.out.println(name + " entered in the lottery."); } else System.out.println(name + " not entered."); System.out.print("\nName: "); name = input.nextLine(); } while (! name.equals(""));// signals end of data pickWinner();

25 ArrayList and Generics
public void pickWinner() { // chooses a random entry and displays winners name and ID int numEntries = entries.size();// size of ArrayList Random random = new Random(); Student winner = entries.get(random.nextInt(numEntries)); System.out.print("The winner and Principal for a Day is "); System.out.println (winner.getName()); System.out.println (winner.getID()); } public static void main(String[] args) SchoolLottery lottery = new SchoolLottery(); lottery.addStudents();

26 More About Generics A generic class has the form ClassName <E1,E2,…En> where Ei are type parameters. Each Ei is a stand-in or placeholder for some reference type. That is, the arguments supplied in place of each Ei cannot be primitive types.

27 Generics:restrictions
Java does not allow generic arrays. The statement E[] myArray = new E[size]; // illegal attempts to create an array called myArray that holds elements of type E. This is illegal; instead, use an explicit cast, such as E[] myArray = (E[]) new Object[size]; // legal The Java compiler will issue a warning to the effect that the cast may be unsafe. Because of the way that Java implements generics, the compiler has no way of knowing whether or not this type of cast is safe. Consequently, the compiler generates a warning message.

28 Generics:restrictions
Java does not permit instantiation of a generic type. For example, the method public illegalMethod (E t) { E copy = new E(); // illegal // other statements } generates a compilation error.

29 Generics, Inheritance, and Polymorphism
The use of inheritance in combination with generics naturally imposes a helpful limitation on the kinds of types allowed. The class declaration public className <T extends P> restricts type parameter T to the class P and its subclasses.

30 Generics, Inheritance, and Polymorphism
public class Average<T extends Number > // does not compile { private T[] list; public Average(T[] l) list = l; } public double findAverage() double sum = 0.0; for(int i = 0; i < list.length; i++) sum = sum+ list[i].doubleValue() return sum/list.length; The type parameter T is intended to be a numeric type such as Integer, Double, Float, Byte, Short, or Long.

31 Stack A stack is a ordered list of data such that items can be added to and removed from just one end of the list, the top of the stack. Access to a stack is more restrictive than access to an ArrayList. When you add an item to the top of the stack you push the item onto the stack. When you remove the top item from a stack, you pop the stack.

32 Stack If s is a stack of strings that is initially empty, the operations push “Hamlet”, push “Rosencranz”, and push “Guildenstern” place the three strings on s. Because “Guildenstern” is the last string pushed onto s, “Guildenstern” occupies the top position.

33 A stack after three push operations

34 Stack Two pop operations, remove the top two strings from s.

35 Stack Implementation The standard stack operations include:
push: add an element the stack. pop: remove and return the top element of the stack . peek: view or “peek at” the top of the stack. empty: determine whether or not there are any elements in the stack. size: get the number of elements stored in the stack. We bundle these operations into an interface, StackInterface<E>, that declares the methods guaranteed to clients of any class that implements StackInterface<E>.

36 Stack Implementation public interface StackInterface<E> {
public void push(E x); // places x on a stack public E pop(); // removes and returns the top item // returns null if the stack is empty public boolean empty(); // returns true if no elements are on the stack public E peek(); // returns the top item, does not alter the stack public int size(); // returns the number of items on the stack }

37 Stack Implementation Problem Statement
Design a Stack<E> class that implements StackInterface<E>. Include a main(...) method that demonstrates the operation of a Stack<E> object. Use an ArrayList to hold the data of the stack

38 Stack Implementation import java.util.*; // for ArrayList<E>
class Stack<E> implements StackInterface<E> { private ArrayList<E> items; public Stack() // default constructor; creates an empty stack items = new ArrayList<E>(); // initial capacity is 10 } public Stack(int initialCapacity) //one argument constructor //creates a stack with initial capacity initialCapacity items = new ArrayList<E>(initialCapacity); public void push(E x) items.add(x); //uses the ArrayList method add(E o)

39 Stack Implementation public E pop() {
if (empty()) // determine whether or not there is an item to remove return null; return items.remove(items.size()-1) //uses the ArrayList method remove(int n) } public boolean empty() return items.isEmpty(); //uses the ArrayList method isEmpty() public int size() return items.size(); //uses the ArayList method size() public E peek() { // determine whether or not there is an item on the stack if (empty()) return null; return items.get(items.size()-1); //uses the ArrayList method get(int i)

40 Line 2: class Stack<E> implements StackInterface<E>
Stack<E> is a generic class. The type parameter E is a stand-in or placeholder for a reference type E. Line 4: private ArrayList<E> items; Stack<E> data are stored in the ArrayList<E> items. Lines 5 – 9: public Stack() // default constructor; creates an empty stack { items = new ArrayList<E>(); // initial capacity is 10 } By default, the initial capacity of items is 10. Thus, the stack can hold 10 items before the underlying ArrayList<E> must be resized. The initial stack size is 0. Do not confuse the array capacity with the size of the stack.

41 Stack Implementation Lines 10 – 14:
public Stack(int initialCapacity) //one argument constructor //creates a stack with initial capacity initialCapacity { items = new ArrayList<E>(initialCapacity); } The one argument constructor sets the initial capacity of items to initialCapacity. The initial stack size is 0 as it is in the default constructor.

42 Stack Implementation Lines 15 – 18:
public void push(E x) { items.add(x); //uses the ArrayList method add(E o) } The push(E x) method places an element x on the top of the stack. The add(E x) method of ArrayList<E> inserts item x of type E at the end of items. The top of the stack is the element at position items.size() – 1.

43 Stack Implementation public E pop() Lines 19 – 25
{ if (empty()) // determine whether or not there is an item to remove return null; return items.remove(items.size()-1) //uses the ArrayList method remove(int n) } To remove an item from the stack, first check that the stack is not empty. If there is at least one item on the stack, the call items.remove( items.size() –1) removes the last item that was placed into items. That is, the call removes the element that is on top of the stack, and returns that item.

44 Stack Example A Stack For Checking Balanced Parentheses, Brackets, and Braces Expressions and statements typically include parentheses, braces and brackets; syntactically correct expressions require balanced parentheses, braces, and brackets. For example, the parentheses in the expression ((2+3) * 3) are balanced; but those in ((2+3) * 3 are not. The parentheses and brackets of array[2*(3+4)] are balanced but the brackets of array[2*(3+4)[ are not.

45 Stack Example With the aid of a stack, determining whether or not the parentheses, braces, and brackets of an expression are balanced is an easy task that is specified by the following algorithm. initialize a stack to empty for each character, ch, of an expression if ch is a left parenthesis (, brace {, or bracket [ push ch onto the stack if ch is a right parenthesis, brace, or bracket if a matching left parenthesis, brace, or bracket is on top of the stack pop the stack else report an error and stop // No characters remain as input. if the stack is empty, the expression is correctly balanced. Otherwise, it is not

46 Using a stack to check that ([2+3]–(a +b) +1) is balanced
Stack String Action empty ([2+3]-(a +b) +1) Push ( ( [2+3]-(a +b) +1) Push [ ( [ (top) 2+3]-(a +b) +1) read 2 ( [ +3]-(a +b) +1) read + 3]-(a +b) +1) read 3 ]-(a +b) +1) read ]– Pop the matching left bracket [ -(a +b) +1) read the - (a +b) +1) ( ( a +b) +1) read a +b) +1) b) +1) read b ) +1) read ) –Pop the matching left parenthesis ( +1) 1) read 1 ) read ) -- Pop the matching left parenthesis ( end of string The expression is balanced.

47 Stack Example Problem Statement:
Implement a class with a single utility method, public static void boolean expressionChecker( String ex), that determines whether or not the parentheses, braces, and brackets of ex are balanced. Include a main(…) method that tests expressionChecker(…).

48 Stack Example import java.util.*; public class ExpressionChecker {
public static boolean checkExpression(String ex) Stack<Character> stack = new Stack<Character>(); for (int i = 0; i < ex.length(); i++) char ch = ex.charAt(i); // if ch is a left parenthesis, brace, or bracket push ch onto the stack if (ch == '(' || ch == '[' || ch == '{') stack.push(ch); // if ch is a left parenthesis and there is a matching right parenthesis //on the stack, pop else if (ch == ')' && (!stack.empty()) && stack.peek().equals( '(')) stack.pop(); // if ch is a left bracket and there is a matching right bracket on the stack, pop else if (ch == ']' && (!stack.empty()) && stack.peek().equals( '['))

49 Stack Example // if ch is a left brace and there is a matching right brace on the stack, pop else if (ch == '}' && (!stack.empty()) && stack.peek().equals('{')) stack.pop(); // if ch is a left parenthesis, bracket, or brace with no match on the stack,error else if (ch== ')' || ch == ']' || ch == '}') return false; // expression is incorrect } if (!stack.empty()) return false; return true;

50 Stack Example public static void main(String [] args) {
Scanner input = new Scanner(System.in); System.out.println("Enter an expression; press <ENTER> to exit"); System.out.print(": "); String expression = input.nextLine(); do boolean correct = checkExpression(expression); if (correct) System.out.println("Expression "+ expression+ " is correct"); else System.out.println("Expression "+ expression+ " is incorrect"); System.out.print("\n: "); expression = input.nextLine(); } while (!expression.equals("")); }

51 Stack Example Output: Enter an expression; press <ENTER> to exit
: (1+3)* (3+5)*4 Expression (1+3)* (3+5)*4 is correct : (1+3)*x[3-2]+(a+5 Expression (1+3)*x[3-2]+(a+5 is incorrect : array[3+(4+5] Expression array[3+(4+5] is incorrect

52 Stack Example Discussion
The statement on line 6 instantiates a Stack<Character> object. However, the statement on line 12 stack.push(ch); pushes a primitive value onto the stack. Autoboxing invisibly wraps the value of ch with a Character object. The statement stack.push(ch) is akin to stack.push(new Character(ch)).

53 Queue A queue is an ordered list of data into which data can be inserted and removed. However, unlike a stack, data is always inserted at one end of a queue, the rear, and removed from the other end, the front.

54 Queue vs. Stack

55 Queue Implementation Typical queue operations include:
insert: add an item to the rear of the queue. remove: remove and return an item from the front of the queue. peek: view or “peek at” the front item. empty: determine whether or not there are any elements in the queue. size: get the number of elements stored in the queue

56 Queue Implementation The queue operations are specified the following generic interface: public interface QueueInterface<E> { public void insert(E x); // inserts x at the rear of the queue public E remove(); // removes and returns the front item // returns null if the queue is empty public boolean empty(); // returns true if no elements are in the queue public E peek(); // returns the front item, does not alter the queue public int size(); // returns the number of items in the queue }

57 Queue Implementation We can implement a queue using an ArrayList<E> for storage. However, this is not the most expedient implementation. Suppose, for example, that items is an ArrayList<E> and that items holds queue elements. T he insert() operation can be implemented as: void insert(E x) { items.add(x): } which places element x at the end of items. The method is easy and efficient.

58 Queue Implementation On the other hand, the remove() operation, although easy to implement, is not particularly efficient. If the first queue element is always located at position 0, the remove operation can be implemented as: E remove() { if (empty()) return null; return items.remove(0); } The method works correctly but at a cost. When the element at position 0 is deleted from an ArrayList<E> object, all other elements in the list are shifted. That is, the element in position 1 is moved to position 0, the element in position 2 is moved to position 1 etc. So every remove() operation necessitates that all remaining elements in items are moved

59 Queue Implementation A queue can be more efficiently implemented using a simple array for storage. The only real limitation with such an implementation is that the size of an array is fixed. However, if you can estimate the maximum size of a queue, an array implementation is a good option.

60 Queue Implementation A queue that uses an array, items, with maximum capacity 5. The variable front holds the index of the first item in the queue and a second Variable rear holds the index of the last item in the queue. The queue after four insert operations; (b) after two remove operations , and (c) after one more Insert operation.

61 Queue Implementation . Will one more insert() operation throw an ArrayOutOfBoundsException? Not necessarily. There are two available cells in the array: items[0] and items[1]. If the next insert operation, insert("Saturn"), places "Saturn" in items[0], then no error occurs. That is, we consider items[0] to be the cell that follows items[4]. In practice, we imagine the array as circular.

62 Queue Implementation By using “circular array,” we do not waste any array locations, and the queue can hold as many elements as the size of the underlying array. Nevertheless, overflow errors can still occur once we use all the space in the array.

63 Queue Implementation Problem Statement:
Implement a queue using an array for storage. The Queue<E> class should implement QueueInterface<E>.

64 Queue Implementation Solution
The Queue<E> class uses an array, items for storage. There are also four integer fields: front, which holds the index of the first item in the queue, rear, which holds the index of the last item in the queue, numItems, which stores the number of items in the queue, and maxQueue, which stores the maximum capacity of the queue. The array, items, is considered circular. This means that, if space remains, items[0] is the storage location following items[maxQueue-1], where maxQueue is items.length. Because an array has a fixed size, it is possible to exceed the capacity of a queue. In this case, the insert() method issues a message and exits. Alternatively, insert() might throw an exception.

65 Queue Implementation import java.util.*;
public class Queue<E> implements QueueInterface<E> { private E[] items; private int numItems; // number of elements currently in the queue int front, rear; // holds the indices of the front an rear elements int maxQueue; // maximum capacity public Queue() // default constructor, sets maxQueue to 10 items =(E[]) new Object[10]; // new E[10] is illegal; the cast is necessary numItems= 0; front = rear= -1; // -1 indicates that the queue is empty maxQueue = 10; } public Queue(int max) // one argument constructor , accepts maximum capacity maxQueue = max; items =(E[]) new Object[maxQueue]; // new E[maxQueue] is illegal; the cast is necessary numItems = 0;

66 Queue Implementation public void insert(E x)
// inserts x at the rear of the queue // if overflow occurs, issues a message and exits { if ( numItems == maxQueue) // queue is full System.out.println(" Queue Overflow"); System.exit(0); } rear = (rear +1) % maxQueue; // % maxQueue ensures wraparound items[rear] = x; numItems++; if (numItems == 1) // if queue was previously empty front = rear;

67 Queue Implementation public E remove()
// removes and returns the first item in the queue // if the queue is empty , returns null { if (numItems == 0) // empty queue return null; E temp = items[front]; // holds the first item in the queue numItems--; if ( numItems == 0) // if the queue is now empty set front and rear to –1 front = rear = -1; else front = (front + 1) % maxQueue; // %maxQueue ensures wraparound return temp; } public E peek() // returns the first item in the queue or null if the queue is empty // does not alter the queue if (numItems == 0) // empty queue return items[front];

68 Queue Implementation public boolean empty()
// returns true if the queue is empty { return numItems == 0; } public int size() // returns the number of items currently in the queue return numItems;

69 Queue Implementation Discussion Lines 10 and 18:
items =(E[]) new Object[10]; items =(E[]) new Object[maxQueue]; Java does not allow generic arrays. The statement items = new E[10]; results in a compilation error. To avoid this error, we instantiate an array of Object and cast that to E[]. When the class is compiled the compiler issues a warning to the effect that the cast on lines 10 and 18 may be unsafe. However, no problem occurs here because every item in the queue belongs to the class represented by E.

70 Queue Implementation Lines 31 and 48:
rear = (rear +1) % maxQueue; front = (front+1) % maxQueue; These lines effect wraparound. For example, suppose that that maximum capacity of a queue is 10, and that the queue consists of three items stored at items[7], items[8], and item[9]. Since the value of rear is 9, rear = (rear+1)% maxQueue = (9+1)% 10 = 0. Thus, the next item is stored at items[0]. The array is circular; 0 follows 9.

71 Linked List A linked list is an ordered collection, group, or list of items such that each item holds a reference or “link” to the next item of the collection.

72 Linked List To implement a linked list we use nodes
A node is an object that contains data as well as a reference to another node. Thus, a node has at least two fields, one of which holds the address of another node

73 A Node class public class Node { public String data;
public Node next; // next is a reference to a Node public Node () // default constructor data = “”; // the empty string next = null; } public Node(String s) // one argument constructor data = s; }

74 Node The data type of next is Node.
The next field of a Node is itself a reference to a Node object. The next field holds the address of another node. Node is a recursive structure.

75 Node The statements Node p = new Node("Mercury"); // one-argument constructor Node q = new Node ("Venus"); instantiate two Node objects, one referenced by p and another referenced by q.

76 Node Nodes can be linked together to form a “chain of nodes.”
The horizontal arrow indicates that the field p.next (in the “Mercury” node) holds the address of the “Venus” node, which also happens to be stored in q. The linking of these two nodes is accomplished by the statement p.next = q; //q holds the address of the “Venus” node, which assigns the address of the “Venus” node (q) to the next field of the “Mercury” node (p.next).

77 Node Four linked nodes

78 Creating a Chain of Nodes

79 Creating a Chain of Nodes

80 Chain of Nodes Problem Statement
Implement a class, Chain, that creates a chain of Node objects such that each Node holds a String entered via the console. Include a method that displays the data stored in the chain.

81 Chain of Nodes In the following application note that
a private Node class is declared within Chain; and a reference front holds the address of the first node in the chain. Without such a reference, the data in the chain is inaccessible. The reference front serves as an anchor for the chain of nodes.

82 Chain of Nodes import java.util.*; public class Chain {
private class Node // a class declared within Chain, an inner class private String data; private Node next; public Node() // default constructor data = “”; next = null; } public Node(String s) // one argument constructor data = s;

83 Chain of Nodes private Node front;
public Chain() // constructor builds a chain { Scanner input = new Scanner(System.in); String name; Node q, r; System.out.print("Enter name -- Press <Enter> to signal end of data: " ); name = input. nextLine(); // create the first node front = new Node(name); q = front; // front and q both reference the first node System.out.print("Enter name: " ); while (!name.equals("")) r = new Node(name); // get a new node q.next = r; // link the previous node to the new node q = r; // move q to the "new" node }

84 Chain of Nodes public void printChain() {
Node q = front; // q references the first node in the chain System.out.println("\nThe names in the chain of nodes are: "); while (q!= null) System.out.println(q.data); q = q.next; // move q to the next node in the chain } public static void main(String[] args) Chain chain = new Chain(); chain.printChain();

85 Node, an inner class Node is declared as a private class declared within another class, Chain. Node is declared solely for Chain’s convenience. Node is called an inner class and Chain, an outer or surrounding class. Inner classes are useful when one class has meaning only in the context of another class. For example, on its own, a Node may have no apparent purpose, but a part of a chain, a Node object has a well-defined function. The methods of an inner class have direct access to variables and methods of the surrounding outer class. On the other hand, the methods of an outer class can access an inner class field or invoke an inner class method only via an object of the inner class. For example, consider the following class definitions.

86 Linked List Because each node in a chain holds the address of the next node, a chain of nodes suggests a natural storage structure for a linked list class, LList<E>. In addition to the instance variable front, which references the first node of the chain, LLInk<E> includes a field, rear, which holds the address of last node, and a third reference variable current, which can reference any node in the chain.

87 Linked List The methods of LList<E> include methods for adding, removing, and retrieving data. That is, the methods of LList<E> mirror the methods of ArrayList<E>. These methods, common to ArrayList<E> and LList<E>, are grouped together in the following interface

88 ListInterface public interface ListInterface<E> {
void add(int index, E x); // inserts x into position index void add(E x); // adds x to the end of the list void clear(); // removes all objects from the list boolean contains ( E x); // returns true if x is a member of the list E get(int index); // returns the Object at position index

89 ListInterface boolean isEmpty(); // returns true if the list has no elements boolean remove (E x); // if x is a member of the list, removes the first occurrence of x from the // list, shifts all elements // and returns true; otherwise returns false. E remove (int index); // removes and returns the object x at position index; // shifts all elements following x down one position E set (int index, E x); // replaces the object at index index with x; returns the replaced object. int size(); // returns the number of objects currently in the list }

90 Linked List The LList<E> class not only implements ListInterface<E> but also provides three additional methods, not found in ArrayList<E>, void reset(), sets current equal to front boolean hasNext() returns true if current.next is not null, i.e. if current is not equal to rear. E next(). if current == null, reports an error and terminates the application; otherwise returns the data of the current node and moves current down the list, i.e. sets current equal to current.next.

91 LList<E> public class LList <E> implements ListInterface<E> { private class Node // an inner class private E data; private Node next; public Node() // default constructor data = null; next = null; } public Node(E x) // two argument constructor data = x; } // end

92 LList<E> private Node front, rear, current;
private int length; // the size of the list public LList() // default constructor { rear = front = current= null; length = 0; } public void add(E x) // adds x to the end of the list Node p = new Node(x); // instantiate a new node referenced by p if (rear == null) // if list is initially empty front =rear = p; // the list has just one node else rear.next = p; // places the Node referenced by p at the end rear = p; length++;

93 public void add(int index, E x) // adds x to list at position index
{ if (index > length ) // index out of range System.out.println("Out of range in add(int index, E x)"); System.exit(0); } Node p = new Node(x); // instantiate a new node referenced by p // add to the front of the list if (index == 0) p.next = front; // place the address of the first nod into the new node front = p; // front references the new node if (rear == null) // if list was initially empty rear = front; // front and rear reference the single node of the list length++; return;

94 // add to the end of the list
if (index == length) { add(x); return; } // addition is neither at front nor rear Node q = front; for (int i = 0; i < index-1; i++) // point q to the node at position index q = q.next; Node r = q.next; // r references the node following q (could be null) q.next = p; p.next = r; length++; public void clear() // makes the list empty front = rear = null; length = 0;

95 public boolean contains (E x)
public boolean contains (E x) // returns true if x is a member of the list { Node p = front; for (int i = 0; i < length; i++) // could also use “(while p.next != null)” if ( x.equals(p.data)) return true; p = p.next; } return false; // search unsuccessful public E get (int index) // returns data at position index if (index >= length) // if index is out of bounds System.out.println("Error in get (int index)"); System.exit(0); for (int i = 0 ; i < index; i++) p = p.next; // move through the list, node by node return p.data;

96 LList<E> public boolean isEmpty() // returns true if list is empty { return length == 0; } public boolean remove (E x) // removes first occurrence of x; // returns true if successful Node p = front; Node q = null; while (!(p == null) && !x.equals(p.data)) // look for x q = p; p = p.next; if (p == null) // not found return false; if (!(q == null)) // if x is in the first node q is null q.next = p.next; if (p == front) front= front.next; if ( p == rear) rear = q; length--; return true;

97 LList<E> public E remove (int index) // removes and returns data at position index { if (index >= length) // index out of bounds System.out.println("Error in remove (int index)"); System.exit(0); } Node p = front; Node q = null; for ( int i = 0; i < index; i++) // q follows p down the list q = p; p = p.next; if ( current ==p) // if removing the current node, move current to the next node current = p.next; if (!(q == null)) // if not removing the first node // q follows p, so q is null when p is the first node. q.next = p.next; if (p == front) front= front.next; if ( p == rear) rear = q; length--; return p.data;

98 LList<E> public E set (int index, E x) // sets data at position index to x { if (index >= length) // index out of bounds System.out.println("Error in get (int index)"); System.exit(0); } Node p = front; for ( int i = 0; i < index; i++) p = p.next; E temp = p.data; p.data = x; return temp; public int size() // returns the number of data on the list return length;

99 LList<E> { current = front; }
public void reset() // makes the first node the current node { current = front; } public boolean hasNext() // returns true if a call to next() will be successful if (current == null) return false; return true; public E next() // returns data of current node and moves current to the next node System.out.println("Error in hasNext() "); System.exit(0); E temp = current.data; current = current.next; return temp;

100 Lines : void add(E x) This method adds a node with data x to the rear of the list. Suppose that a list consists of three nodes: The method call add(8) results in the following actions.

101 Lines 25- 36: void add(E x) Line 27: Node p = new Node(8);
Line 33: rear.next = p; Line 33: rear = p;

102 Lines 123- 148: E remove(int index)
This method removes the node at a given index. For example, remove(0) removes the first node in the list and remove(2) removes the third node in the list. Trace a call to remove(2).

103 Lines 123- 148: E remove(int index)
Lines : for ( int i = 0; i < index; i++) { q = p; p = p.next; } For i = 0 and i = 1, set q equal to p, and move p down the list. Notice that q follows p.

104 Lines 123- 148: E remove(int index)
Lines : if ( current ==p) current = p.next; p references the node which is to be removed. If current references the same node as p, move current down the list

105 Lines 123- 148: E remove(int index)
Lines : if (!(q == null)) q.next = p.next; If q is null, then the node to be removed is the first node on the list. In thiscase, q is not null. Here, p holds the address of the node that is to be removed and q the address of the preceding node. Change the link in q.next from p to p.next.


Download ppt "Java Programming: From the Ground Up"

Similar presentations


Ads by Google