Implementing an ADT Having the JCFs is great – most of the significant data structures are already available But you still may need to implement your own.

Slides:



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

COMP171 Fall 2005 Lists.
Singly Linked Lists What is a singly-linked list? Why linked lists?
Stacks, Queues, and Linked Lists
DATA STRUCTURES USING C++ Chapter 5
Chapter 24 Lists, Stacks, and Queues
Chapter 3 – Lists A list is just what the name implies, a finite, ordered sequence of items. Order indicates each item has a position. A list of size 0.
Data Structures A data structure is a collection of data organized in some fashion that permits access to individual elements stored in the structure This.
Introduction to Linked Lists In your previous programming course, you saw how data is organized and processed sequentially using an array. You probably.
Chapter 4: Trees Part II - AVL Tree
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 7 Queues. Copyright © 2004 Pearson Addison-Wesley. All rights reserved.1-2 Chapter Objectives Examine queue processing Define a queue abstract.
Searching Kruse and Ryba Ch and 9.6. Problem: Search We are given a list of records. Each record has an associated key. Give efficient algorithm.
Lecture 8 CS203. Implementation of Data Structures 2 In the last couple of weeks, we have covered various data structures that are implemented in the.
1 Chapter 24 Lists Stacks and Queues. 2 Objectives F To design list with interface and abstract class (§24.2). F To design and implement a dynamic list.
C++ Programming: Program Design Including Data Structures, Third Edition Chapter 17: Linked Lists.
1 Data Structures Data Structures Topic #2. 2 Today’s Agenda Data Abstraction –Given what we talked about last time, we need to step through an example.
Data Structures Topic #3. Today’s Agenda Ordered List ADTs –What are they –Discuss two different interpretations of an “ordered list” –Are manipulated.
C++ Programming: Program Design Including Data Structures, Fifth Edition Chapter 17: Linked Lists.
Chapter 3: Arrays, Linked Lists, and Recursion
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
Data Structures Using C++ 2E
Iterators CS 367 – Introduction to Data Structures.
Data Structures Introduction Phil Tayco Slide version 1.0 Jan 26, 2015.
JAVA: An Introduction to Problem Solving & Programming, 5 th Ed. By Walter Savitch and Frank Carrano. ISBN © 2008 Pearson Education, Inc., Upper.
C++ Classes and Data Structures Jeffrey S. Childs
Arrays and Linked Lists "All the kids who did great in high school writing pong games in BASIC for their Apple II would get to college, take CompSci 101,
1 CSE 1342 Programming Concepts Lists. 2 Basic Terminology A list is a finite sequence of zero or more elements. –For example, (1,3,5,7) is a list of.
CSC 211 Data Structures Lecture 13
Lists II. List ADT When using an array-based implementation of the List ADT we encounter two problems; 1. Overflow 2. Wasted Space These limitations are.
A first look an ADTs Solving a problem involves processing data, and an important part of the solution is the careful organization of the data In order.
Data Structures Trees Phil Tayco Slide version 1.0 Apr. 23, 2015.
CS 307 Fundamentals of Computer ScienceLinked Lists 1 Topic 14 Linked Lists "All the kids who did great in high school writing pong games in BASIC for.
4-1 Topic 6 Linked Data Structures. 4-2 Objectives Describe linked structures Compare linked structures to array- based structures Explore the techniques.
Dynamic Data Structures and Generics Chapter 10. Outline Vectors Linked Data Structures Introduction to Generics.
Linked List. Iterators Operation to find a link, deleting, and inserting before or after a specified link, also involve searching through the list to.
1 Linked-list, stack and queue. 2 Outline Abstract Data Type (ADT)‏ Linked list Stack Queue.
(c) University of Washington16-1 CSC 143 Java Linked Lists Reading: Ch. 20.
Comp 249 Programming Methodology Chapter 15 Linked Data Structure – Part A Dr. Aiman Hanna Department of Computer Science & Software Engineering Concordia.
Linked List by Chapter 5 Linked List by
Chapter 15 Linked Data Structures Slides prepared by Rose Williams, Binghamton University Kenrick Mock University of Alaska Anchorage Copyright © 2008.
Linked Lists Chapter 4. Linked Structures: Motivations Arrays have fixed size –Problematic for data structures of arbitrary size Arrays order items physically.
Data Design and Implementation. Definitions Atomic or primitive type A data type whose elements are single, non-decomposable data items Composite type.
List Interface and Linked List Mrs. Furman March 25, 2010.
Chapter 5 Linked List by Before you learn Linked List 3 rd level of Data Structures Intermediate Level of Understanding for C++ Please.
JAVA: An Introduction to Problem Solving & Programming, 6 th Ed. By Walter Savitch ISBN © 2012 Pearson Education, Inc., Upper Saddle River,
Chapter 17: Linked Lists. Objectives In this chapter, you will: – Learn about linked lists – Learn the basic properties of linked lists – Explore insertion.
1 Chapter 4 Unordered List. 2 Learning Objectives ● Describe the properties of an unordered list. ● Study sequential search and analyze its worst- case.
Lists List Implementations. 2 Linked List Review Recall from CMSC 201 –“A linked list is a linear collection of self- referential structures, called nodes,
CHAPTER 51 LINKED LISTS. Introduction link list is a linear array collection of data elements called nodes, where the linear order is given by means of.
Linked Lists A formal data structure. Linked Lists Collections of data items “lined up in a row” Inserts and deletes can be done anywhere in the list.
Data Structures and Algorithm Analysis Dr. Ken Cosh Linked Lists.
LINKED LISTS.
C++ Programming:. Program Design Including
CSC 222: Object-Oriented Programming
Top Ten Words that Almost Rhyme with “Peas”
Prof. Neary Adapted from slides by Dr. Katherine Gibson
Stacks, Queues, and Deques
Stacks, Queues, and Deques
Linked Lists.
CS2013 Lecture 4 John Hurley Cal State LA.
Dynamic Data Structures and Generics
Dynamic Data Structures and Generics
Lists.
Intro to OOP with Java, C. Thomas Wu By : Zanariah Idrus
Programming II (CS300) Chapter 07: Linked Lists
Stacks, Queues, and Deques
Presentation transcript:

Implementing an ADT Having the JCFs is great – most of the significant data structures are already available But you still may need to implement your own – the JCF implementation may not contain the methods you want – the JCF implementation may not be as efficient as what you can create – the JCF may not restrict access like you would like for instance, Queue is an interface, the implementations of Queue are LinkedList and PriorityQueue, neither of which presents a real Queue – or you are working in a language other than Java? As a CS student, you need to not only learn the JCFs but how to implement your own ADT – here, we focus on the List as an ADT

More It is important to understand how to use the JCFs because using them will save you work, why re- invent them? – It is also important to understand how to implement ADTs on your own for the reasons stated on the previous slide but is also furthers your understanding of OOP, implementing proper interfaces (not interface classes, but the interface of a class with a user class) and will also let you think about computational and space efficiency of a data structure There are usually 2 implementation ways to implement a given ADT, an array and a linked list – The array is already known by you – The linked list means that you create a node for each datum to be stored in the container and you link the nodes together

What is a Collection? Generically, a collection is just a group of objects that share the same type, each object is known as an element of the collection – In Java, the Collection is an Interface with three subtypes (Set, List, Queue) each of which is an Interface – Some of these collection types do not allow duplicate elements – Some collections allow you (or force you) to access elements based on a key value (e.g., access by ID number) – Some collections restrict access Location to insert Location to remove Inability to search the collection for a particular entry Inability to traverse the collection (without removing elements) We generally think of a Collection as a list of items – the question is how we access the list

Ordered List ADT The List JCF classes allow inserting anywhere Instead, we want an Ordered List ADT – insert only in the appropriate place based on ordering You can remove any element as long as its removal maintains the ordering of the list – removal will be done by item, not index Other methods are – traversal of the list (e.g., print all elements) – search for a particular element in the list – returning the element itself – destroy the list – obtain the list’s size – determine if the list is empty – determine if the list is full (for the array version) As stated earlier, we can implement this using an array or a linked list, we will examine both

Unordered List ADT Another way to represent a List is without ordering – Why? It is easy (less computationally expensive) to add elements to an unordered list – Also, some lists do not necessarily require ordering (consider a shopping list, you usually do not alphabetize the items) The problem with the unordered list is that search is expensive – We will see why later The unordered list ADT has the same methods as the ordered list but may be implemented differently: – insert (always insert at the beginning or end for convenience), search, remove, traverse, destroy, size, isEmpty, isFull

Array Implementation of Unordered List Although we might want to use Generics to implement our lists, we cannot if we are implementing an array – for simplicity, we will assume an array of int values We use the following three instance data –int[] list; // initialized to new int[100] –int size; // set to 100 –int number; // initialized to 0 And the following methods public boolean isFull( ) { return size==number;} public boolean isEmpty( ) {return number==0;} public void traverse( ) { for(int i=0;i<number;i++) System.out.println(list[i]); } public void destroy( ) {number=0;size=0;list=null;}

Insert Since this is an unordered list, we can insert the new value anywhere Where can we insert it that requires the least amount of work? If we insert it anywhere from 0 to number-1 (that is, in a position already occupied), we have to move elements around Instead, we will always insert at the end of the array at location number, and then increment number public void insert(int x) { if(number<size) { list[number]=x; number++; } else … } If the array is full, we can output an error message here, throw an exception (we would want to add throws ExceptionType to the header), or do array doubling

Search and Delete These methods will unfortunately require that we find the item through a sequential search We will implement search first and use it for delete public int search(int x) { int location=-1;// indicates not found for(int i=0;i<number&&location==-1;i++) if(list[i]==x) location=I; return location; } public void delete(int x) { int index=search(x); if(index!=-1) { list[index]=list[number-1]; number--; } else … } We delete by replacing the item at index with the last item in the array (at number-1) and then decrement number If not found, output error message or throw Exception

The Cost Of Sequential Search As the item we are searching for can be anywhere in the array (or not in the array at all), we have to look at every value until we find it – We will search from the beginning onward (or we could search from the end inward) – Once we find the item, we stop searching – In the worst case, the item we are looking for is literally the last item in the list based on the direction of our search, or is not in the array at all – If we have an array of n items in the best case, it takes 1 search in the worst case, it takes n searches in the average case, it takes (n+1)/2 searches, or roughly n/2 searches – Keep this in mind for later…

Array Implementation of Ordered List We will use the same instance data as with our Unordered List and the same initial methods –int[] list; // initialized to new int[100]; –int size; // set by constructor to 100 –int number; // initialized to 0 public boolean isFull( ) { return size==number;} public boolean isEmpty( ) {return number==0;} public void traverse( ) { for(int i=0;i<number;i++) System.out.println(list[i]); } public void destroy( ) {number=0;size=0;list=null;}

public void insert(int x) { boolean done=false; for(int i=number;i>0&&!done;i--) if(x<list[i-1]) list[i]=list[i-1]; else { list[i]=x; number++; done=true; } if(!done) { list[0]=x; number++; } We insert x into its proper location by finding the first element > x and move that and all other elements down by 1 Notice that we actually start from the right end of the array and shift while we search backward for the proper location

public int bsearch(int item) { int high=number-1,low=0,mid=(high+low)/2; while(low<=high&&list[mid]!=item) { if(list[mid]>item) high=mid-1; else if(list[mid]<item) low=mid+1; mid=(high+low)/2; } if(list[mid]==item) return mid; else return -9999; // use this to indicate item not found } We use binary search for searching which is much more efficient than sequential search Searching the Ordered List Why binary search? We could do sequential search which means on average we have to look at n/2 items to find what we are looking for Binary search will require looking at no more than log n items to find the item we are looking for (or determine it isn’t in the list) Is the difference between n/2 and log n significant? Depends on n If n = 100, then it is 50 versus 7, not a big difference, but if n = 1,000,000 then the difference is 500,000 versus 20!

Deletion public void delete(int x) { int temp=bsearch(x); if(temp==-9999) System.out.println("Item not found!"); else { for(int i=temp;i<number-;i++) list[i]=list[i+1]; number--; } We call upon binary search to find the location of the item to be deleted so that we don’t have to repeat the code here Deletion requires shifting to “cover up” the deleted item

Using Search for Delete Notice in both of our implementations (ordered and unordered array list) we used the search method to obtain the index of an item we want to delete Why should we use search for delete? – We don’t have to, but it saves us from having to re-implement the same code in another method Could we also use the search method to identify the location to insert into (for the ordered list)? – We wouldn’t need to do this for the unordered list because we are always adding at the end Notice in the ordered insert, we are searching from the end of the array forward until we find the proper insertion location – While we are searching, we are also shifting elements up the array to create a vacant spot – If we use the binary search to find a location for insert, we would still have to do all that shifting, so we may as well combine

Conclusions on Array Implementations We are familiar with arrays so it shouldn’t be challenging to implement The unordered list’s insert and delete are easy but the ordered insert and delete, requiring shifting, is harder Array doubling is necessary if we don’t want to arbitrarily limit the size of the collection – Array doubling is computationally expensive if you have to do it often – Without array doubling, we either have to resort to using a very large collection with the potential to waste space or limit the user program to a size that may be too small As we will see, an array for an unordered list is about the same computationally as an unordered linked list The savings in using an array over a linked list appears when we implement an ordered list

Linked Lists A linked list consists of nodes, one node per datum – Unlike the array where there may be many empty elements A linked list node will be defined as some (1 or more) data member(s) and a next member which will store the next node in the list – The next field will be a reference variable (pointer) – The data member(s) can be Generic, unlike our array implementation The linked list starts with a single front pointer (called head below) – We may or may not have a tail pointer The linked list will require that we create a new Node to insert into the list and attach the Node via references

The Node Before we define the Linked List more formally, let’s look at the Node – The Node will be defined as its own class (whether a stand- alone or nested class) Any Node needs at least two instance data – The value that the Node is storing a primitive datum like an int, an object like a String, an object that itself contains multiple values like a Student object, multiple data like a name, a major, a GPA, or a Generic type of Object – A reference to the next Node in the list we will usually refer to this member as next and it will be of the same type as the Node itself, e.g., Node next; this member is a pointer to the next Node but we don’t call them pointers in Java, so it is a reference to the next Node

Why a Linked List We will find that dealing with reference variables to insert and delete items from a list can be a challenge, so why bother? – We want an array of Integers, we declare Integer[ ] foo; – Later we do foo=new Integer[100]; what happens if we need 101 Integers? what happens if we only use 5 Integers? – The array stores a preset number of elements while the linked list contains 1 node for each element in the list so the linked list is more memory efficient (lower space complexity) – But the linked list suffers in search efficiency (time complexity) especially when we have a large list of items that are sorted Another advantage of the Linked List is that the Node can be defined as Generic while an array cannot (although we could use an ArrayList to implement a Generic OrderedList class)

Implementation Details of the LL First we implement the Node – This will either be a separate class or an inner class – We will need to implement getters and setters for the data and the next members – We need to get and set next when we are dealing with getting the next node pointer or changing pointers Note the use of to make this generic – We must include in our outer class > public class Node { private E datum; private Node next; public Node(E x, Node n) {datum=x;next=n;} public Node getNext() {return next;} public E getDatum() {return datum;} public void setNext(Node n) {next=n;} public void setDatum(E x) {datum=x;} }

Implementation Details of the LL To create a linked list, set front to null (also tail to null if we have tail) – If we are keeping track of the size, set size to 0 – A list is empty if size is 0 (or front==null), the list is never full To search an existing LL for some item temp, start at front and move through the list until we either find temp or reach null – Remember that E is Comparable public Node search(E x) { Node temp=front; while(temp!=null&&temp.getDatum().compareTo(x)!=0) temp=temp.getNext(); return temp; } public int search2(E x) { int index=0; Node temp=front; while(temp!=null&&temp.getDatum().compareTo(x)!=0) { temp=temp->next; index++; } if(temp==null) return -1; else return index; } Once found, we can either return the Node (search) or the index (search2)

Implementation Details of the LL public void traverse() { Node temp=front; while(temp!=null) { System.out.println(temp.getDatum()); temp=temp.getNext(); } public void insertFront(E x) { Node temp=new Node(x,front); front=temp; } Insert at the front of the list – we use this approach for our unordered list ADT only Traverse/print the list

Implementation Details of the LL Inserting in order requires finding the proper location to place the new Node 3 cases – Empty list – create a new node and set front to it – Insert at the beginning – see previous slide – Anywhere else – search the list for the first Node whose datum > new value For the third case, let’s assume we use the following code, is it correct? Node temp2=front; While(temp2!=null&&temp2.getDatum().compareTo(temp)<0) temp2=temp2.getNext(); temp.setNext(temp2); // but how do we attach temp to the list?

Let’s Take a Closer Look temp2 is pointing to the first Node whose datum > temp’s datum, so we know to insert temp before temp2 – We set temp’s next field to point at temp2, but we do not have a reference to temp2’s preceding node, how do we make the Node storing 63 point at temp? We use 2 pointers to traverse the list, we will call them, current and previous – before moving current onto the next node, we set previous to be current – now when we reach 70, current is pointing at 70 but previous is pointing at 63, so we can modify 63’s next pointer to point at temp

Implementing Ordered Insert public void insert(E x) { Node temp=new Node<>(x,null); if(front==null) front=temp; else if(front.getDatum().compareTo(x)>0) { temp.setNext(front); front=temp; } else { Node current=front, previous=null; while(current!=null&&current.getDatum().compareTo(x)<0) { previous=current; current=current.getNext(); } previous.setNext(temp); temp.setNext(current); } Case 1: empty list Case 2: insert at beginning Case 3: search for proper location to insert temp

previous.setNext(temp); temp.setNext(current); What if current is null? This occurs if the place to insert is after the last Node in the list – this is not a special case, the same two instructions work

Implementing Remove (Delete) We have several versions of a deletion – Delete first element if(front!=null) {front=front.getNext( );size--;} else … // output a message, throw an exception – Delete by index – Delete a specific element, x covered on the next slide for(current=front,i=0;current!=null&&i<n-1;i++) current=current.getNext( ); if(current!=null) current.setNext(current.getNext( ));

Implementing Remove (Delete) Again, we have three cases – If empty list, throw Exception or output error message – If item to be deleted is the first item in the list, redirect front to point at the second item – Otherwise, search the list using two pointers (we need to have a pointer to the previous Node) public void delete(E x) { if(front==null) // throw Exception or output message else if(front.getDatum().compareTo(x)==0) front=front.getNext(); // the first Node is no longer else {// pointed at, it will be Node current=front;// garbage collected Node previous=null; while(current!=null&&current.getDatum().compareTo(x)!=0) { previous=current; current=current.getNext(); } if(current!=null) previous.setNext(current.getNext()); }

Comments Notice the last if statement, we use this because if the item isn’t found, current will be null and we can’t perform a deletion – in the case of item not found or empty list, if we throw an Exception, we have to add throws Exception or use a try- catch block to handle the Exception We can improve the efficiency by using current.getDatum().compareTo(x)<0 – how does this help? – if the item isn’t found, we stop searching as soon as we find the first datum greater than x – imagine we have the list 10, 20, 30, 40, 50, 60, 70, 80 and are looking to delete 15, we can discover 15 is not in the list as soon as we hit the Node with 20, but using the code on the previous slide will have us continue searching through the entire list

Why Linked List Revisited We cannot use binary search on a linked list – To find some datum in an ordered array takes O(log n) operations (worst case) while in the linked list, O(n) – We already saw that this was a significant difference when we compared the ordered and unordered lists in an array To insert and delete in an ordered array, we have to shift elements up or down, as many as n elements In the linked list, we have to find the proper location to insert or delete, as many as n elements – So we see that for an ordered list, the array and linked list versions give us the same worst case performances The linked list gives us superior memory performance over the array because with the linked list, we do not need to use array doubling, nor do we waste memory space

Which Should We Use? If we know something about the use of the data, it might help us decide – How often are we inserting/deleting versus searching? – If searches are a minimum, the linked list might be better consider a list where we spend much time adding and removing items, and traversing the entire list, but we rarely actually have to search for a single element in the list, this might be the case for instance for a teacher maintaining a list of students – On the other hand, what if we need to create a list and once created, rarely change it but spend a lot of time searching for particular elements? You will learn alternate forms of lists in 364, notably trees and graphs – A tree typically is implemented using a linked structure and can be more efficient than either the ordered list as an array or linked list

Linked List Variations Dummy node – Create a linked list with a special dummy node (thus the list is never empty) where the dummy node is always first and contains a dummy value which will always be less than anything in the list – We will never insert before the first node so there are no special cases Circular linked list – Only need one pointer, tail – To get to head, use tail.getNext( ) Doubly linked list – Each node has two pointers, a previous and a next pointer – This requires modifying not only the linked list class but also the Node class – We no longer need a previous and a current pointer to work through the list, just current (we can get to previous by current.getPrevious( ) ) but it does require manipulating more pointers upon insert and delete

Variations Illustrated

Comparing Ordered Linked List vs Ordered Array O(log n)