Lec1-2-Linked_List.pdf
Document Details
Uploaded by CrisperPulsar
Full Transcript
1 © 2014 Goodrich, Tamassia, Goldwasser WHAT IS DATA STRUCTURE? Data Structure can be defined as the group of data elements which provides an efficient way of storing and organizing data in the computer so that it can be used efficiently Some examples of Data Struc...
1 © 2014 Goodrich, Tamassia, Goldwasser WHAT IS DATA STRUCTURE? Data Structure can be defined as the group of data elements which provides an efficient way of storing and organizing data in the computer so that it can be used efficiently Some examples of Data Structures are arrays, Linked List, Stack, Queue, etc. Data Structures are widely used in almost every aspect of Computer Science i.e. Operating System, Compiler Design, Artificial intelligence, Graphics and many more. Data Structures are the main part of many computer science algorithms as they enable the programmers to handle the data in an efficient way. It plays a vital role in enhancing the performance of a software or a program as the main function of the software is to store and retrieve the user's data as fast as possible © 2014 Goodrich, Tamassia, Goldwasser NEED FOR DATA STRUCTURES As applications are getting complex and data-rich, there are three common problems that apps face nowadays Processor speed: To handle very large amount of data, high speed processing is required, but as the data is growing day by day to the billions of files per entity, processor may fail to deal with that much amount of data. Data Search: Consider an inventory size of 100 items in a store, If our application needs to search for a particular item, it needs to traverse 100 items every time, results in slowing down the search process. Multiple requests: If thousands of users are searching the data simultaneously on a web server, then there are the chances that a very large server can be failed during that process © 2014 Goodrich, Tamassia, Goldwasser TO SOLVE THE PREVIOUS-MENTIONED PROBLEMS: Data can be organized in a data structure in such a way that all items may not be required to be searched, and the required data can be searched almost instantly. Reference: © 2014 Goodrich, Tamassia, Goldwasser https://www.tutorialspoint.com/data_structures_algorithms/data_structure_overview.htm ADVANTAGES OF DATA STRUCTURES Efficiency: Efficiency of a program depends upon the choice of data structures. For example: suppose, we have some data and we need to perform the search for a particular record. In that case, if we organize our data in an array, we will have to search sequentially element by element. hence, using array may not be very efficient here. There are better data structures which can make the search process efficient like ordered array, binary search tree or hash tables. © 2014 Goodrich, Tamassia, Goldwasser ADVANTAGES OF DATA STRUCTURES (CON.) Reusability: Data structures are reusable, i.e. once we have implemented a particular data structure, we can use it at any other place. Implementation of data structures can be compiled into libraries which can be used by different clients. Abstraction: Data structure is specified by the ADT which provides a level of abstraction. The client program uses the data structure through interface only, without getting into the implementation details. © 2014 Goodrich, Tamassia, Goldwasser DATA STRUCTURE CLASSIFICATION © 2014 Goodrich, Tamassia, Goldwasser DATA STRUCTURE CLASSIFICATION Linear Data Structures Non-Linear Data Structures © 2014 Goodrich, Tamassia, Goldwasser LINEAR DATA STRUCTURES A data structure is called linear if all its elements are arranged in the linear order. In linear data structures, the elements are stored in non- hierarchical way where each element has the successors and predecessors except the first and last element. Types of Linear Data Structures are: Arrays LinkedList Stack Queue © 2014 Goodrich, Tamassia, Goldwasser NON-LINEAR DATA STRUCTURES This data structure does not form a sequence i.e., each item or element is connected with two or more other items in a non-linear arrangement. The data elements are not arranged in sequential structure. Types of Non-Linear Data Structures are: Trees Graphs © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON DATA STRUCTURE Traversing: Every data structure contains the set of data elements. Traversing the data structure means visiting each element of the data structure in order to perform some specific operation like searching or sorting. Insertion: Insertion can be defined as the process of adding the elements to the data structure at any location. Deletion: The process of removing an element from the data structure is called Deletion. We can delete an element from the data structure at any random location. © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON DATA STRUCTURE (CON.) Searching: The process of finding the location of an element within the data structure is called Searching. There are two algorithms to perform searching, Linear Search and Binary Search. Sorting: The process of arranging the data structure in a specific order is known as Sorting. There are many algorithms that can be used to perform sorting, for example, insertion sort, selection sort, bubble sort, etc. Merging: When two lists List A and List B of size M and N respectively, of similar type of elements, clubbed or joined to produce the third list, List C of size (M+N), then this process is called merging © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST © 2014 Goodrich, Tamassia, Goldwasser TOPICS ❑ Linked List : ◼ Singly Linked List ◼ Circular Linked List ◼ Doubly Linked List 14 © 2014 Goodrich, Tamassia, Goldwasser INTRODUCTION Static arrays are used when we know before implementation how many items we need to store, because we need to allocate a block of memory where the elements are stored in continuous locations. For example, asking the user to input 20 numbers to sort: A static array is used. We know the user will input 20 numbers. If we do not know how many elements we need, for example asking the user to enter some numbers to sort, then array is not a suitable data structure to be used, instead we might use the following: A dynamic array(ArrayList or Vector). A linked list. 15 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST DATA STRUCTURE ▪ A Linked List is a linear data structure that looks like a chain of nodes, where each node is a different element. ▪ Unlike Arrays, Linked List elements are not stored at a contiguous location → the nodes are randomly stored in the memory. Singly Linked Lists 16 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST DATA STRUCTURE THERE ARE MAINLY THREE TYPES OF LINKED LISTS: 1- Singly linked list 2- Circularly linked list 3- Doubly linked list Singly Linked Lists 17 © 2014 Goodrich, Tamassia, Goldwasser SINGLY LINKED LIST ▪ A singly linked list consisting of a sequence of nodes, starting from a head pointer ▪ A singly linked list contains a link called head, points to the beginning of the list. ▪ It also contains a link called tail, points to the end of the list. ▪ Each node stores ▪ element next element ▪ link to the next node (address) node head A B C D tail 18 © 2014 Goodrich, Tamassia, Goldwasser SINGLY LINKED LIST 19 © 2014 Goodrich, Tamassia, Goldwasser SINGLY LINKED LIST ▪ The Linked list is not required to be contiguously present in the memory. ▪ It can be allocated dynamically where the nodes can reside any where in the memory and linked together via pointers to make a list. This achieves optimized utilization of space. ▪ The list size is limited to the available memory size and doesn't need to be declared in advance. ▪ Empty node can not be present in the linked list. ▪ We can store values of primitive types or objects in the singly linked list. ▪ One way chain or singly linked list can be traversed only in one direction. In other words, we can say that each node contains only next pointer, therefore we can not traverse the list in the reverse direction. Dynamic means the size changes at runtime, NOTE example: linked list Static means the size needs to be determined at compile time and never changed later, example: 20 © 2014 Goodrich, Tamassia, arrayGoldwasser SINGLY Node.java LINKED LIST IMPLEMENTATION(1) SinglyLinkedList.java It is common for a linked list instance to keep a count of the total number of nodes that comprise the list, to avoid traversing the list to count the NOTE nodes. In our implementation, we keep the total number of nodes in the Singly Linked Lists 21 © 2014 Goodrich, Tamassia, variable Goldwasser size. LINKED LIST OPERATIONS: 1. Traverse. 2. Insertion: ▪ Inserting at the beginning of the list ▪ Inserting at the end of the list ▪ Inserting at specific location in the list 3. Deletion: ▪ Deleting from the beginning of the list ▪ Deleting from the end of the list ▪ Deleting a specific node Singly Linked Lists 22 © 2014 Goodrich, Tamassia, Goldwasser SINGLY LINKED LIST OPERATIONS- TRAVERSE The algorithm will traverse the linked from the first node until finishing it. It will print the data inside it on the screen. Algorithm Traverse (head): // Initialize a traversing pointer to the head c head // While we didn’t reach the null. The list is not finished yet WHILE c != NULL: PRINT c.data // Update the traversing pointer to the next node // its address is in link part of the current node c c.next 23 © 2014 Goodrich, Tamassia, Goldwasser SINGLY LINKED LIST OPERATIONS- TRAVERSE The algorithm will traverse the linked from the first node until finishing it. It will print the data inside it on the screen. SinglyLinkedList.java 24 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING AT THE BEGINNING (HEAD) Allocate new node Insert new element Have new node point to old head Update head to point to new node 25 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING AT THE BEGINNING (HEAD) Algorithm addFirst (e): newest Node(e) // create new node instance and store reference to element e newest.next head //set new node’s next to reference the old head head newest //set variable head to reference the new node IF (size = 0) THEN tail = head; //update the tail size size +1 // increment the node count 26 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING AT THE BEGINNING (HEAD) SinglyLinkedList.java 27 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING AT THE END (TAIL) Allocate a new node Insert new element Have new node point to null Have old last node point to new node Update tail to point to new node 28 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING AT THE END (TAIL) Algorithm addLast (e): newest Node(e) // create new node instance and store reference to element e newest.next Null //set new node’s next to reference the null object IF (head = Null) THEN // we can say also IF (size = 0) head newest // set variable head to reference the new node ELSE tail.next newest //Make tail node’s next point to new node tail newest // set variable tail to reference the new node size = size +1 // increment the node count 29 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING AT THE END (TAIL) SinglyLinkedList.java 30 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING IN THE MIDDLE ▪ This algorithm will insert one node in the middle of the linked list. ▪ The insertion point depends on the relation of the data in the new node with the other data in the list. ▪ It may be used in sorted insert. ▪ This algorithm will include the previous addFirst. 31 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING IN THE MIDDLE newest C head 7 2 6 8 9 ∅ head C 2 6 8 9 ∅ C 7 newes head t 2 6 8 9 ∅ head 2 6 7 8 9 ∅ 32 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: INSERTING IN THE MIDDLE Algorithm addMiddle(e): newest Node(e) // create new node instance and store the reference to element e IF (head = Null) THEN // Check if the list is empty, we can say also IF (size = 0) head newest // If true, put the address of the new node in the head. ELSE // if not empty IF (newest.data < head.data) THEN // check if new node must be inserted before the head node addFirst() ELSE // If not, Traverse until the last node, or until find the node before the wanted one c head WHILE ( c.next != NULL) IF (newest.data > c.next.data) c c.next // insertion point Newest.next c.next // Put the address of the next node in the next of the new node. c.next newest // Put theSingly address of new node in the link of the node before the Linked Lists 33 insertion point. © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: REMOVING AT THE BEGINNING (HEAD) Update head to point to next node in the list Allow garbage collector to reclaim the former first node 34 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: REMOVING AT THE BEGINNING (HEAD) Algorithm removeFirst (): IF (head = NULL) THEN // check if the list is empty, we can say also IF (size = 0) RETURN NULL head head.next // make head point to next node (or null if the removed node is the only one in the list) size size -1 // decrement the node count IF size=0 THEN // check after the decrement tail = null; 35 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: REMOVING AT THE BEGINNING (HEAD) 36 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: REMOVING AT THE TAIL Removing at the tail of a singly linked list is not efficient!. There is no constant-time way to update the tail to point to the previous node Algorithm removeLast (): IF (head = NULL) THEN // check if the list is empty, we can say also IF (size = 0) RETURN NULL Update Tail=4 But how to get to 4 c head We don’t have pointer from Node to 4 we have from 4 to node which doesn’t help g head.next We got to start from the head WHILE (g.next != NULL) THEN c c.next g g.next c.next NULL tail c © 2014 Goodrich, Tamassia, Goldwasser 37 LINKED LIST OPERATIONS: REMOVING FROM THE MIDDLE This algorithm will delete one node from the middle of the linked list. The choosing of the deleted node depends on a specific condition. This algorithm will include the previous removFirst and Traverse. Singly Linked Lists 38 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: REMOVING FROM THE MIDDLE key C head 8 2 6 8 9 ∅ head C 2 6 8 9 ∅ head C temp 2 6 8 9 ∅ head C temp 2 6 8 9 ∅ c.next=temp.next 39 © 2014 Goodrich, Tamassia, Goldwasser LINKED LIST OPERATIONS: REMOVING FROM THE MIDDLE Algorithm deleteMiddle(e): IF (head != Null) THEN // Check if the list is empty, we can say also IF (size = 0) IF (head.data = e) // the node is the first node deleteFirst() ELSE c head WHILE (c.next.data !=e || c.next !=NULL) c c.next // move to the next node IF c.next != NULL // if found temp c.next // let temp point to the wanted node c.next temp.next // let the link of the node before temp point to the node after temp // the garbage collector will reclaim temp (the wanted node) 40 © 2014 Goodrich, Tamassia, Goldwasser ADVANTAGES AND DISADVANTAGES OF LINKED LISTS Advantages of using linked lists: o Very flexible: ▪ We don’t need to worry about allocating space in advance, can use any free space in memory. We only run out of space when the whole memory is full. ▪ When doing insertion and deletion no shifting is required. o More efficient for moving large records (leave data in same place in memory, just change some pointers). Disadvantages of using linked lists: o Wasted space: we store both pointers and data. o To access the ith item, we must start at the beginning and follow pointers until we get there. In the worst case, if there are n items in a list and we want the last one, we have to traverse n elements. 41 © 2014 Goodrich, Tamassia, Goldwasser ARRAYS VS. LINKED LISTS COMMANDS Singly Linked Lists 42 © 2014 Goodrich, Tamassia, Goldwasser ARRAY VS LINKED LIST array A B C D 0 1 2 3 4 5 head Linked list A B C D tail © 2014 Goodrich, Tamassia, Goldwasser ARRAY VS LINKED LIST 44 © 2014 Goodrich, Tamassia, Goldwasser IMPLEMENTING A SINGLY LINKED LIST CLASS IN JAVA size( ): Returns the number of elements in the list. isEmpty( ): Returns true if the list is empty, and false otherwise. first( ): Returns (but does not remove) the first element in the list. last( ): Returns (but does not remove) the last element in the list. addFirst(e): Adds a new element to the front of the list. addLast(e): Adds a new element to the end of the list. removeFirst( ): Removes and returns the first element of the list. © 2014 45 © 2014 Goodrich, Tamassia, Goldwasser A NESTED NODE CLASS 46 © 2014 Goodrich, Tamassia, Goldwasser ACCESSOR METHODS 47 © 2014 Goodrich, Tamassia, Goldwasser JAVA METHODS: ADD 48 © 2014 Goodrich, Tamassia, Goldwasser JAVA METHOD: REMOVE 49 © 2014 Goodrich, Tamassia, Goldwasser CIRCULAR LINKED LIST “Circular linked list is a linked list where all nodes are connected to form a circle. There is no NULL at the end. A circular linked list can be a singly circular linked list or doubly circular linked list”. It has the following properties: The last node of the list contains a pointer to the first node of the list. We traverse a circular linked list until we reach the same node where we started. The circular linked list has no beginning and no ending. There is no null value present in the next part of any of the nodes. 50 © 2014 Goodrich, Tamassia, Goldwasser CIRCULAR LINKED LIST Circularly linked list supports all the public behaviors of the Singly Linked List class and one additional operation which is rotate. Rotate is about moving the first element to the end of the list. The real life application where the circular linked list is used is our Personal Computers, where multiple applications are running. All the running applications are kept in a circular linked list and the OS gives a fixed time slot to all for running. The Operating System keeps on iterating over the linked list until all the applications are completed. Another example can be Multiplayer games. All the Players are kept in a Circular Linked List and the pointer keeps on moving forward as a player's chance ends. 51 © 2014 Goodrich, Tamassia, Goldwasser CIRCULAR LINKED LIST ADVANTAGES Any node can be a starting point. We can traverse the whole list by starting from any point. We just need to stop when the first visited node is visited again. We don’t need to maintain two pointers for head and tail if we use circular linked list. We can maintain a pointer (tail) to the last inserted node and the head (front) can always be obtained as next of last(next of tail). Maintaining only the tail reference not only saves a bit on memory usage, it makes the code simpler and more efficient, as it removes the need to perform additional operations to keep a head reference current. Circular lists are useful in applications that repeatedly go around the list. 52 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST Traversal Inset at the beginning Insert at the end Remove at the beginning Rotate 53 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST - TRAVERSAL In a conventional linked list, we traverse the list from the head node and stop the traversal when we reach NULL. In a circular linked list, we stop traversal when we reach the first node again. Algorithm Traverse (tail): c tail.next IF (tail != NULL) THEN //check if empty DO // keep printing nodes till we reach the first node again print c.data c c.next WHILE c != tail.next 54 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST -INSERT AT THE BEGINNING We can add a new element at the front of the list by creating a new node and linking it just after the tail of the list. 55 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST -INSERT AT THE BEGINNING We can add a new element at the front of the list by creating a new node and linking it just after the tail of the list. Algorithm addFirst (e): newest = Node(e) IF (size=0) // empty list newest.next=NULL tail newest tail.next tail ELSE newest.next tail.next tail.next newest size size+1 56 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST - INSERT AT THE END We can rely on the use of a call to addFirst and then immediately advance the tail reference so that the newest node becomes the last. 57 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST - INSERT AT THE END We can rely on the use of a call to addFirst and then immediately advance the tail reference so that the newest node becomes the last. Algorithm addLast (e): addFirst(e) tail tail.next 58 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST – DELETE FROM THE BEGINNING Removing the first node from a circularly linked list can be accomplished by simply updating the next field of the tail node to bypass the implicit head. Note different notations Of pseudocode 59 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST – ROTATE We do not move any nodes or elements, we simply advance the tail reference to point to the node that follows it (the implicit head of the list). 60 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A CIRCULAR LINKED LIST – ROTATE We do not move any nodes or elements, we simply advance the tail reference to point to the node that follows it (the implicit head of the list). 61 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST ▪ A doubly linked list can be traversed forward and backward ▪ Nodes store: prev next ▪ element ▪ link to the previous node ▪ link to the next node ▪ Special trailer and header nodes element node header nodes/positions trailer elements 62 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST ▪ In singly linked list we were unable to efficiently delete a node at the tail or any arbitrary node from an interior position if only given a reference to that Node (also add before an element if we have a reference to it): O (n) ▪ The problem in singly linked list is that there is a way to get from a previous element to the next element, but no way to get back. ▪ Doubly linked list solves the problem with next/prev pointers: delete a node at the tail or add before an element become O (1) operations. singly linked list To delete Node we update Tail->4 But how to get to 4 We don’t have pointer from Node to 4 we have one from 4 to Node which doesn’t help We have to start from the head 63 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST ▪ To avoid some special cases when operating near the boundaries: add a header node at the beginning of the list, and a trailer node at the end of the list. ▪ Header/ trailer are “dummy” nodes known as sentinels (or guards), they do not store elements of the primary sequence. header nodes/positions trailer elements 64 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST ▪ When using sentinel nodes, an empty list is initialized so that the next field of the header points to the trailer, and the prev field of the trailer points to the header. The remaining fields of the sentinels are irrelevant (presumably null, in Java). header trailer Empty doubly linked list 65 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST ▪ We could implement a doubly linked list without sentinel nodes, but the sentinels greatly simplifies the logic of our operations. ▪ The header and trailer nodes never change—only the nodes between them change. ▪ We can treat all insertions in a unified manner, because a new node will always be placed between a pair of existing nodes. ▪ Every element that is to be deleted is guaranteed to be stored in a node that has neighbors on each side. 66 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST - INSERTION ▪ Every insertion into our doubly linked list representation will take place between a pair of existing nodes. ▪ when a new element is inserted at the front of the sequence, we will simply add the new node between the header and the node that is currently after the header. 67 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST -INSERTION ▪ Insert a new node, q, at the front. A B C q A B C X q x A B C 68 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST -INSERTION Insert a new node, q, between p and its successor. ▪ p A B C p A B q C X p q A B X C Doubly Linked Lists 69 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST -INSERTION ▪ Using sentinels nodes, we will always insert a new node between 2 nodes, its successor & predecessor. Algorithm addBetween (e, predecessor, successor): newest Node(e) newest.prev predecessor newest.next successor predecessor.next newest successor.prev newest size size+1 70 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST -INSERTION ▪ Insert a new node at the begging of the doubly linked list. Algorithm addFirst(e): addBetween(e, header, header.getNext) // place just after the header 71 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST -INSERTION ▪ Insert a new node at the end of the doubly linked list. Algorithm addLast(e): addBetween(e, trailer.getPrev(), trailer) // place just before the trailer 72 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST -DELETION ▪ To delete a node, the two neighbors of the node to be deleted are linked directly to each other, thereby bypassing the original node. ▪ As a result, that node will no longer be considered part of the list and it can be reclaimed by the system. ▪ Because of our use of sentinels, the same implementation can be used when deleting the first or the last element of a sequence, because even such an element will be stored at a node that lies between two others. 73 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST - DELETION ▪ Remove a node, p, from a doubly linked list. p A B C D A B C p D A B C 74 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST - DELETION ▪ Remove a node, p, from a doubly linked list. Algorithm remove (p): predecessor p.prev successor p.next predecessor.next successor successor.prev predecessor size size-1 75 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST - DELETION ▪ Remove first from a doubly linked list. Algorithm removeFirst (): remove(header.next) 76 © 2014 Goodrich, Tamassia, Goldwasser OPERATIONS ON A DOUBLY LINKED LIST - DELETION ▪ Remove last node from a doubly linked list. Algorithm removeLast (): remove(trailer.prev) 77 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY-LINKED LIST IN JAVA size( ): Returns the number of elements in the list. isEmpty( ): Returns true if the list is empty, and false otherwise. first( ): Returns (but does not remove) the first element in the list. last( ): Returns (but does not remove) the last element in the list. addFirst(e): Adds a new element to the front of the list. addLast(e): Adds a new element to the end of the list. removeFirst( ): Removes and returns the first element of the list. removeLast(): Removes and returns the last element of the list. 78 © 2014 Goodrich, Tamassia, Goldwasser NODE PRIVATE CLASS 79 © 2014 Goodrich, Tamassia, Goldwasser NODE PRIVATE CLASS We use the generics framework to accept any type of element. The nested Node class for the doubly linked list is similar to that of the singly linked list, except with support for an additional prev reference to the preceding node. 80 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST FIELDS AND CONSTRUCTOR 81 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST FIELDS AND CONSTRUCTOR Our use of sentinel nodes, header and trailer, impacts the implementation in several ways. We create and link the sentinels when constructing an empty list (lines 25–29). We also keep in mind that the first element of a nonempty list is stored in the node just after the header (not in the header itself). Similarly that the last element is stored in the node just before the trailer. 82 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST METHODS 83 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST METHODS The sentinels greatly ease our implementation of the various update methods. We will provide a private method, addBetween, to handle the general case of an insertion, and then we will rely on that utility as a straightforward method to implement both addFirst and addLast. In similar fashion, we will define a private remove method that can be used to easily implement both removeFirst and removeLast. 84 © 2014 Goodrich, Tamassia, Goldwasser DOUBLY LINKED LIST METHODS 85 © 2014 Goodrich, Tamassia, Goldwasser