* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Data Structures and Other Objects Using C++
Survey
Document related concepts
Transcript
Linked Lists in Action This chapter introduces linked lists. This presentation shows how to implement the most common operations on linked lists. LINKED LISTS Collection Classes - LINKED LIST The Java 2 platform contains a Collections API This group of classes represent various data structures that store and manage objects It includes classes such as ArrayList and LinkedList 2 Abstract Data Types – A Review An abstract data type (ADT) is : an organized collection of information containing a set of operations used to manage that information The set of operations includes methods such as add, delete , find etc.. The set of operations/methods define the interface to the ADT 3 Abstract Data Types A List ADT, for instance would define the operations that be used with the list, such as add, delete. We have looked an array implementation of a list, now we will look at a Linked List. 4 Static vs. Dynamic Structures A static data structure has a fixed size Arrays are static; once you define the number of elements it can hold, it doesn’t change. 5 DRAWBACKS OF ARRAYS The array implementation of our collection has one serious drawback: you must know the maximum number of items in your collection when you create it. 6 Linked Lists WHAT IF YOU DON’T KNOW THE NUMBER OF ITEMS BEFOREHAND????? WHAT IF THE NUMBER OF ITEMS WILL VARY OVER TIME? We need a dynamic data structure that grows and shrinks as necessary 7 Array Limitations Arrays Simple, Fast but Must specify size at construction time WHICH GIVES RISE TO “Murphy’s law” Construct an array with space for n n = twice your estimate of largest collection Tomorrow you’ll need n+1 8 Linked Lists - it is never full A linked list is a very flexible, dynamic data structure: no preset size required items may be added to it or deleted from it at will. No need to increase capacity when full it is never full 9 Object References Recall that an object reference is a variable that stores the address of an object in memory. A reference can also be called a pointer (to an object in memory) and they are often depicted graphically: student John Smith 40725 3.57 10 References as Links Object references can be used to create links between objects Suppose a Person class contains a reference to another Person object John Smith 40725 3.57 Person Jane Jane Jones 58821 3.72 11 Self-Referential Objects A Person object, for instance, could contain a reference variable to another Person object: public class Person { private String name; private String address; private Person next; // a link to another Person object // whatever else } 12 Intermediate Nodes Problem: Objects should not have to deal with the details of the structure in which they are stored E.g., the person class stored a link to the next person object in the list 13 Linked Lists Instead, we can use a separate node class that : holds a reference to the stored object and a link to the next node in the list This type of reference can be used to form a Linked List. 14 A Linked List of Persons So by having a separate structure to contain the list of persons: One object(object 1) is not dependent for its existence on another object (object 2) And removing object2 would not require removing object1. 15 Object References - ListNode class Consider an object that contains a reference to another object of the same type: class ListNode<T> { T data; // object stored in data– e.g. Client object ListNode next; // reference to the next node } data = Client next = refers to next listnode 16 Two objects of this class can be instantiated and chained together. The next reference of one Node object refers to the next node in the list. The second object’s next reference refers to a third Node object, and so on, creating a linked list of Node objects. Client 1 next Client2 next 17 NODE S IN THE LIST Each node will contain some data as specified by the programmer. This constitutes a linked list 18 Linked Nodes In a linked list, each item is allocated space as it is added to the list. (called dynamically) A link (next) is kept within each item to the next Client in the list. Client 1 next Client2 next 19 Each node of the list has two elements : 1. the object being stored in the list, e.g. a client and 2. a reference to the next node in the list (next) The next reference in the last node in the list contains a NULL pointer to indicate that it is the end or tail of the list. Client 1 next Client2 next = null 20 Linked Lists As items are added to a list, memory for a node is dynamically allocated. (Allocated as needed) Thus the number of items that may be added to a list is limited only by the amount of memory available. head client 21 HEAD OF THE LIST The variable (or handle) which holds on to the list is simply a pointer(reference) to the node at the head of the list. Client next = null It is called head Head holds the memory address of the first node 22 Linked List -Flexible space use Dynamically allocate space for each element as needed Includes a pointer to the next item Linked list Each ListNode of the list contains the data item (e.g. a Client) next - a reference to the next node Data Next object 23 Linked Lists - WHAT IS HEAD? Let’s implement a Collection structure – a linked list which has a reference to the first node called HEAD Head is initially NULL Head = null 24 Linked Lists The Linked List structure has a reference to the list: head which is initially NULL TO Add first item to the head of the list Allocate memory for the ListNode Set its data reference to some object Set next to NULL Set head to reference the new node Head ListNode Data Next object 25 Add second item to the head of the list Allocate memory for the node - NewNode Set its data reference to some object (object2) Set new node .next to point to the node Head is pointing to Set Head to point to (reference) the new node Head NewNode Data Next object2 FIRST node Data Next object1 26 Linked Lists Add second item to the head of the list Allocate memory for the node Set its data pointer to an object Set new node next to point to the node Head is pointing to Set Head to point to new node Head New node Data Next object2 node Data Next object1 27 Constructors of a ListNode class ListNode {amine the constructor for the class. // This is one of the constructors in the ListNode class public ListNode(T initialData) { data = initialData; // data for the node next = null; // reference to next node } where : data - is the initial data of a new node e.g. a client , next - a reference to the next node in the list. 28 How to start the linked list Declare a head node to point to the first node in the list . To create the first node ListNode head = null; // initialize head // now create the first node head = new ListNode (“dan”); Head now refers to a one-node linked list. The data is “dan” and next is equal to null. See previous slide constructor 29 Declarations for linked Lists We will use Strings as data . // Constructor ListNode public class ListNode { private String data; private ListNode next; // constructors } Create the first Node: Head ListNode dan null head = new ListNode (“dan”); data next 30 Declarations for linked Lists For this example, each node in the linked list is an object of the class ListNode, as shown here with String data jay Head public class ListNode { private String data; private ListNode next; ... // Constructor sets next to null initally } data next dan data next nat data null next 31 Declarations for linked Lists Each ListNode also contains a next reference which refers to the next ListNode in the list. Head public class ListNode { private String data; private ListNode next; ... } jay data next dan data next nat data null 32 A program keeps track of the FIRST node by STORING ITS ADDRESS IN HEAD. 52 is the address of the second node Head is a reference to a ListNode. It holds the address of the first node. Head and next both refer to list nodes They store the address of the next node 52 jay next =60 next 50 Head head 50 50 is the address of the 50 first node dan data next =52 data 60 nat data next null 33 NEXT holds an address In the previous slide, the head node holds the address of the first node which is 50 The second node’ next reference holds the address of the next node which is 52. The third node’ next reference holds the address of the next node which is 60. 34 Declarations for Linked Lists We represent the empty list by storing null in the head reference. ListNode head = null; head null 35 The null reference The null reference is a special JAVA constant. It means the reference has no address so it does not refer to anything. 36 Null references Null references are used in several instances. When a object is declared but not instantiated. Client client; Client is initially null For the next part of the final node in a linked list. When we have an empty list, the head and tail reference variables are null. 37 Null Pointer Exceptions When a reference variable is null, you cannot call any of the methods associated with variables’s class. E.g.; ListNode head = null; // head is a null referemce head.next; // error - no next reference yet exists. The second line will result in a NullPointerException. 38 Inserting Nodes at the front of the list. To add to front of list, we create a reference to the head node and call it head. Remember head is initially null. The code to create the head node is: ListNode head = null; 39 Inserting an Node at the Front We could use this code if the list is initially empty: ListNode head = null; // create the node -- uses constructor ListNode newnode = new ListNode(data1, null); head = newnode; //Point head to it OR Below is a shorter version of the previous two lines: ListNode head = new ListNode(data1, null) head data1 null 40 INSERTING A NODE This is a constructor IN THE Linkedlist class: public ListNode ( T data, ListNode nxt) { data = initialData; next = nxt; } Does the constructor work correctly for the first node on a new list ? head = new ListNode(data1, null); //Where head is initially null 41 Creating the first node in a list - Review head = new ListNode( data1, null) creates a new node with data1 as the data and null is stored in next. Head now holds the address of the node with data1 : Head = 50 50 data1 null 42 Inserting an Node at the Front Create a new node…red boxes are addresses of nodes. A new node Head holds the address of the first node - 50 head 50 data1 null 50 Let’s add another node to the front of the list 43 Inserting an Node at the Front We want to add a new entry, data2, to the front of the linked list shown here. New node head 50 50 data1 null 44 Inserting an Node at the Front Create a new node... Place the data in the new node's data field – this is data2. Create the new node: ListNode newnode = new ListNode( data2, null) newnode head data2 Next = null 50 50 data1 null 45 Inserting an Node at the Front of the list, reassign head to it Connect the next (50) reference of newnode to the node head is currently pointing to. newnode So now head and newnode.next point to the same node data2 newnode.next next = 50 head 50 ListNode newnode = new ListNode( data2, null) newnode.next = head 50 data1 null newnode.next refers to the same node as head 46 Inserting an Node at the Front ListNode newnode = new Listnode(data2, null) newnode.next = head; head = newnode ; // we store address 84 in head data2 is now the new first node of the linked list – its address is 84 Newnode’s address is 84 Finally, we point head to the newnode head = newnode; Head holds address of the newnode - 84 head 84 84 data2 NEXT = 50 50 data1 null 47 The brute force way to insert the node at the head of the list would be: public void insertFirst(T data) { // create a node ListNode newnode = new ListNode(data, null); if(isEmpty()) // is the list is empty head = newnode; // point head to the new node else // list is not empty { // set the next pointer of newnode to what head is pointing to newnode.next = head ; head = newnode // point head to newnode } } 48 CHALLENGE For homework, extra credit pts on your quiz if you can do the insertion code in the previous slide in one line of code. You may assume that head has been set to null. 49 Adding to a list This strategy is fast and efficient, but each item is added to the head of the list. An alternative is a list which contains both head and tail pointers: The code for Add is modified to make a list in which new nodes are added to the list at the end. 50 Caution! Always make sure that your linked list methods work correctly with an empty list. EMPTY LIST Linked Lists Add time Constant - independent of n – no loops Search time Worst case - n Collection Head node node Data Next object2 Data Next object 52 Pseudocode for Inserting ListNodes Nodes are often inserted at places other than the front of a linked list. There is a general pseudocode that you can follow for any insertion function. . . First determine if the node is the first node , if so, call method insertFirst(data) 53 Pseudocode for Inserting Nodes Otherwise (if the new node will not be first): then a reference named current must be placed on the list This special node is called the selected node and the new node is inserted right after the selected node. 54 Pseudocode for Inserting ListNodes Otherwise (if the new node will not be first): Start by setting a reference named current to refer to the node before the new node. THE NEW NODE WILL BE INSERTED AFTER THE NODE CURRENT IS POINTING TO current jay dan next head nat null 55 Pseudocode for Inserting ListNodes Otherwise (if the new node will not be first): Start by setting a reference named current to refer to the node just before the new node's position. atlink(next) the link which LookLook at the in the node is is which in the is node current pointingprevious to current jay dan next head nat null What is the name of this link? 56 Pseudocode for Inserting ListNodes Otherwise (if the new node will not be first): Start by setting a reference named current to refer to the node which is just before the new node's position current What is the name of this link ? jay This link is called current.next Or current.getNext() dan next head nat null 57 Pseudocode for Inserting Nodes Otherwise (if the new node will not be first): Start by setting a reference named current to refer to the node which is just before the new node's position current Current refers to the head of a small linked list, with jay and nat jay dan next head nat null 58 Pseudocode for Inserting ListNodes Otherwise (if the new node will not be first): Let’s insert a new node after the node containing dan jay next current current 10 next dan next head nat null 59 These are the contructors for the Listnode public ListNode() // NO PARAMETERS { data = null; // data for the node next = null; // reference to next node } ///************************************************************ public ListNode(T initialData) // with THE DATA PARAMETER { data = initialData; // data for the node next = null; // reference to next node } ///************************************************************ public ListNode(T initialData, Listnode nextnode) // both paramters { data = initialData; // data for the node next = nextNode; // reference to next node } 60 InsertAfter Let create the new node and put Fred in it NEWNODE current fred next jay next dan head next ListNode newnode = new ListNode(); newnode.data = “Fred”; newnode.next = current.next; current.next = newnode; nat next sam null 61 61 InsertAfter We use constructor with one parameter public void insertAfter(T newData) { // where newData = “Fred” ListNode newnode = new ListNode(); newnode.data = newData; // Now we have to attach newnode.next to the list newnode.next = current.next; current.next = newnode; } 62 Then : Store the address in current.next into newnode.next so they both refer to ‘jay’ NEWNODE current fred next jay next dan head next nat next pvoid insertAfter(String newData) { ListNode newnode = new ListNode(); sam null newnode.data = newData; newnode.next = current.next; current.next = newnode; } 63 Now, point current.next to newnode NEWNODE current fred next jay next dan head next nat next pvoid insertAfter(String newData) { ListNode newnode = new ListNode(); sam null newnode.data = newData; newnode.next = current.next; current.next = newnode; } 64 64 Reduce number of lines public void insertAfter(String newData) { ListNode newnode = new ListNode(); newnode.data = newData; newnode.next = current.next; current.next = newnode; } Can we reduce the first three lines of code in this method to one line? 65 InsertAfter Then : Reduce the first three lines to one line current current dan head head jay NEWNODE fred next next nat next next 20 public void insertAfter(String newData) { // first three lines in one line sam null ListNode newnode = new ListNode(newData, current.next) current.next = newnode; } 66 InsertAfter - a shorter version Then : Set the current.next to refer to the new node current current dan head head jay NEWNODE fred next next nat next next // Let’s compact the code all to one line: public void insertAfter(String newData) sam null { ListNode newnode = new ListNode(newData, current.next) current.next = newnode; } 67 Pseudocode for Removing ListNodes Nodes often need to be removed from a linked list. As with insertion, we can remove a node from the front of a list, remove a node from elsewhere. We’ll look at the technique for removing a node from the front of a linked list. 68 Removing the Head Node head = head.next; head dan next Draw the change that this statement will make to the linked list. fred next nat next sam null 69 Removing the Head Node head = head.next; This points head to node after the first Node dan head next fred next nat next sam null 70 Removing the Head Node head = head.next; or head = head.getNext();// if node class is separate Now the node is deleted from the head of the list. fred head nat sam null dan 71 Summary It is easy to insert or remove a node at the front of a list. You also need a technique for inserting or removing a node elsewhere. We will now provide an implementation that will delete at the head node and also elsewhere on the list. 72 Deleting a node not at the head Deleting a node not at the head is similar to adding a node to the middle of the list. current will point to the node to be deleted. WE also need another reference to the node that is just before current. This reference is called previous : 73 Deleting from the middle calls find(target) method first Previous refers to the node before the one to be deleted - Current refers to node to be deleted deleteNode() current previous head dan fred next This arrow is previous.next sam jay next null This arrow is current.next 74 Deleting a Node The method remove{T data} requires that current refer to the node to be deleted. Remove calls Find(T data) which assigns current to refer to the node to be deleted. It also places previous on the node behind current 75 Deleting Anywhere on the List We call the method with: Remove(T data) previous.next points to the node current refers to. current.next points to the node after the node to be deleted (“sam”). previous head dan current fred nat next next This arrow is previous. next sam null This arrow is current.next 76 Deleting from the middle The next portion of previous now points(refers) to the node after current. We must also advance current to the next node previous head dan next fred next current. nat next sam null previous.next = current.next; current = current.next; 77 Deleting anywhere on the list 1) previous.next now contains the address of the node (Sam) . 2) Current is advanced to refer to the node which contains “Sam” NOW previous.next and current refer to same node current. previous nat fred next sam next null previous.next = current.next; current = current.next; 78 Removing a node The Find method puts previous and current on the list where the node is to be deleted public void remove(T data) { // remove first calls the find method find(data); if(current != null && previous != null) { previous.next = current.next; current = current.next; } } 79 Remove() The remove(T data) method works even if the node is a tail node. In this case, the next of the previous node will be assigned the null value. 80 Deleting from the list at the tail The next portion of previous now points to what current.next points, and current points to null. head previous dan fred nat next current sam null null previous.next = current.next; current = current.next; 81 Pseudo-code for Removing a node public void remove() { // if current and previous are not null // point previous.next to what current.next is pointing to // Point current to what current.next is pointing to // else if at the head node – point head to what //current.next is pointing to and set current // equal to head Always check for the Empty List FIRST } 82 Traversing a Linked List To traverse a linked list, we must first assign a next variable - such as cur - to some node. To traverse the list, we move cur to the next node by using the code: cur = cur.next // advance cur to the next node This assignment says “move cur to point to what cur.next points to” - which advances cur to next node. Or we can use: cur = cur.getNext{} // uses getter method for ‘next’ 83 Searching a linked list To find a particular node in a list, we create a method that returns the node that contains the element. The method: public ListNode Find(T target) { } searches for a node containing the target (the data) It returns a reference to the first node that contains the target data. To call the method , use: ListNode node = Find(target) 84 onList() Because Find( target) returns a ListNode, we need to write another method that will return a boolean. Our application class should not have to deal with ListNodes. Our methods should be implementation independent. The user does not have to know if we used an ArrayList of Linked List So returning a boolean can be done in any class 85 The Find (target ) method returns a ListNode public ListNode find (target) This is necessary for some methods that use it. However, outside classes will not know what a Listnode is. SO We write another Find method for the outside classes that returns a boolean public boolean find (target) 86 Searching / traversing a list. public boolean Find(T target) { // this is how you traverse a linked list boolean found = false; ListNode curr; // declare variable to traverse the list for(curr = head; curr!= null; curr= curr.getNext()) { // put in code to find target and return true if found } // close loop return found ; }// close method 87 Doubly Linked Lists Doubly linked lists have a pointer to the preceding item as well as one to the next. They permit scanning or searching of the list in both directions. (To go backwards in a simple list, it is necessary to go back to the start and scan forwards.) Many applications require searching backwards and forwards through sections of a list: 88 Linked Lists - Doubly linked Doubly linked lists Can be scanned in both directions public ListNode(T initialData,) { data = initialData; Listnode previous, next; } head prev next prev prev tail 89 Doubly Linked Lists In this case, the node structure is altered to have two links: class ListNode { T data; ListNode previous, next; // link to node before } // and after 90 Circularly Linked Lists By ensuring that the tail of the list is always pointing to the head, we can build a circularly linked list. A circularly linked list would more likely be used in an application which required "round-robin" scheduling or processing. 91 Analysis of Linked Operations Since the order is irrelevant, and there is no capacity to expand adding an element to the List is O(1) Removing a particular element, because it must be found, is O(n) Removing any item, can be done at the head or tail and thus is O(1); 92 Linked List The linked list implementation has exchanged flexibility for efficiency – On some systems, the need to allocate memory can be relatively expensive. Pre-allocation in the array-based implementation is generally more efficient. BUT, there are circumstances where Linked List is needed. 93 LINKED LIST VS ARRAY However, there are many situations where a linked list is more efficient e.g. Applications that are unsorted - WHY? Applications where the size is relatively small . WHY? More examples of such trade-offs will be found later. 94 Free Memory Memory is just an array of data. Each entry has an address and a value After a series of memory allocations and de-allocations, there are blocks of free memory scattered throughout the available heap space. 95 Memory allocation In order to be able to re-use this memory, memory allocators will link freed blocks together in a free memory list The computer keeps references to blocks of free memory 96 Free Memory An external pointer(head) points to the first block in the free list. When a new block of memory is requested, the allocator scans the free list looking for a suitable block It will delete the block from the free list (re-linking the free list around the deleted block). 97 Free Memory Many variations of memory allocators have been proposed: Refer to a text on operating systems or implementation of functional languages for more details. The entry in the index under garbage collection will address it. 98 Abstract Data Types An abstract data type defines a type of structure that stores data ( e.g. an array) It stores the data in a class along with the operations that can be performed on that data e.g. An ArrayList, A LinkedList, a Stack, A Graph etc. 99 Abstract Data TYPE The Abstract Data Type lists a set of abstract methods Each class that implements the ADT must implement all these methods. E.g. in the List interface has methods like: add, delete etc. 100 Cohesion Well- designed ADT’s have strong relationships between the parts of a class so Cohesion is a goal that you should seek in designing your ADT’s 101 Well-designed ADT’s have little or no coupling To create our Abstract Data Type we need to be sure that the methods are cohesive. Coupling measures the strength of the relationship between two components. It represents the glue that holds two separate components together. This should be minimal in an object- oriented program 102 Coupling and Cohesion We want to minimize the degree of coupling between any two classes of our system so they can operate as independently as possible. Thus any changes we make will only effect a small portion of the program. ALL the methods for the Linked List should be in the Linked List class. 103 CLASS INDEPENDENCE FROM OTHER CLASsES This makes errors easier to track and less likely to affect another part of our system. 104 Coupling and Cohesion We want to maximize the cohesion in a class Cohesion means that the more tightly related the parts of an item are the more logical its operations are. Coupling means that an object depends on another class for some of its operations or data This creates systems that are very difficult to debug 105 ADT’s Cohesion is the strength of the relationships among the parts of one component so that the parts of the component can be thought of as one piece. E.g. in a Client class, we would have a firstname and lastname etc. but not have a reference to another client defined inside it. 106 Objectives Your goals are: 1. a method should only accomplish one logical function 2. an object should represent a single concept or entity. A Student , A Client An ADT by its definition minimizes the coupling between objects. 107