Download presentation
Presentation is loading. Please wait.
1
1 Lists
2
2 Overview Arrays –Random access: –Fixed size: cannot grow on demand after creation: Characteristics of some applications: –do not need random access –require a data structure that can grow and shrink dynamically to accommodate different amounts of data (Linked) Lists satisfy this requirement. We study –list creation –accessing elements in a list –inserting elements into a list –deleting elements from a list
3
3 List: a sequence of cells in which each cell contains –a data item of type Object –a reference to the next cell in the sequence (null if this is last cell in the sequence) –empty list: null List is a sequential-access data structure –to access data in position n of sequence, we must access cells 0..n-1 We will define a class ListCell from which we will build lists. 24 -7 87 78 Array: lc 0123 0 2 our symbol for null a0 a List a1 24 a6 a1 -7 a8 a6 87 a2 a8 78 a2 1 3
4
4 Class ListCell /** An instance is a cell of a list, with a value and a name of another cell */ public class ListCell { protected Object datum; // value of cell protected ListCell next; // name of next cell //(null if none) /** Constructor: cell with value ob and next cell n */ public ListCell(Object ob, ListCell n){ … /** = the value in this cell */ public Object getDatum() {//sometimes called car} /** = name of next cell (none if none)*/ public ListCell getNext() {// … called cdr} /** Set value to ob */ public void setDatum(Object ob) {// … called rplaca } /** Set next cell to n public void setNext(ListCell n) {//… called rplacd} } This is how we draw ListCells 24 a6 a1 ListCell datum 24 next a6 ListCell(Object, ListCell) getDatum() getNext() setDatum(Object) setNext(ListCell)
5
5 Class ListCell /** Instance: a cell of list, with a value and a name of a cell */ public class ListCell { private Object datum; // value of cell private ListCell next; // name of next cell (null if none) /** Constructor: cell with value ob and next cell n */ public ListCell(Object ob, ListCell n) { datum= ob; next= n; } /** = the value in this cell */ public Object getDatum() { return datum; } /** = name of next cell (none if none)*/ public ListCell getNext() { return next; } /** Set value to ob */ public void setDatum(Object ob) { datum= ob; } /** Set next cell to n public void setNext(ListCell n) { next= n; } }
6
6 Building a list Integer t= new Integer(24); Integer s= new Integer(-7); Integer e= new Integer(87); ListCell p= new ListCell(e,null); p= new ListCell(s,p); p= new ListCell(t,p); // Store in p a list 24, -7, 87 Note: assignment of form p = new ListCell(s,p); does not create a circular list. p a5 87 a5 87 a5 p a6 87 a5 a6 87 a5 p a6 87 a5 a6 24 a6 a7
7
7 Building a list Integer t = new Integer(24); Integer s = new Integer(-7); Integer e = new Integer(87); // Store in p a list of 24, -7, 87 ListCell p = new ListCell(t, new ListCell(s, new ListCell(e,null))); Another way: 87 a5 -7 a5 a6 24 a6 a7 p
8
8 Accessing list elements Lists are sequential-access data structures. –to access the contents of cell n in sequence, you must access cells 0..n-1 Accessing data in first cell: p.getDatum() Accessing data in second cell: p.getNext().getDatum() Accessing next field in second cell: p.getNext().getNext() 87 a5 -7 a5 a6 24 a6 a7 p p.getDatum()p.getNext()
9
9 Accessing list elements Writing to fields in cells can be done the same way //update data field of first cell p.setDatum(new Integer(53)); )); //update field of second cell p.getNext().setDatum(new Integer(53)); //chop off third cell p.getNext().setNext(null); 87 a5 -7 a5 a6 24 a6 a7 p
10
10 Access example: linear search // = “ob is in list p” public static boolean search(Object ob, ListCell p) { // invariant: c is the name of a cell in list p (or null) // ob does not occur before cell c in list p for (ListCell c= p; ci != null; c= c.getNext()) if (c.getDatum().equals(ob)) return true; // { ob is not in the list } return false; } 87 a5 -7 a5 a6 24 a6 a7 p
11
11 Recursion on lists Recursion can be done on lists in a manner similar to recursion on integers. Almost always –base case: empty list –recursive case: assuming you can solve problem on (smaller) list obtained by eliminating first cell, write down solution for list Many list problems can be solved very simply by using this idea. –Some problems, though, are easier to solve iteratively.
12
12 Recursion example: linear search Base case: empty list –return false Recursive case: non-empty list –if data in first cell equals object ob, return true –else return result of doing linear search on rest of list // = “ob occurs in list p” */ public static boolean recSearch(Object ob, ListCell p) { if (p == null) return false; return p.getDatum().equals(ob) || recSearch(ob,p.getNext()); }
13
13 Some prefer to use a class List that is distinct from class ListCell. A List object is like a head element that always exists even if list itself is empty. /** An instance is a list with a header */ class List { private ListCell head; /** Constructor: an instance is a list p public List (ListCell p) {head= p; } /** = the first value of list (0 if none) public ListCell getHead() { … } /** Set list to p */ public void setHead(ListCell p) { … } 87 a5 -7 a5 a6 24 a6 a7 List with header p a1 head a1 a7
14
14 Variations of list with header Header can keep other info, e.g. –reference to last cell of list –number of elements in list –search/insertion/ deletion as instance methods 87 a5 -7 a5 a6 24 a6 a7 p1 a1 head a7 p2 b2 tail a5 head a7 p3 c3 size 3 head a7 search(ob) What you put in a header depends on the application.
15
15 Example of use of class List We write code to –insert object into unsorted list –delete the first occurrence of an object in an unsorted list. We use the class List to show how to use this class. –It is just as easy to write code without the header element. Methods for insertion/deletion will be instance methods in class List. // insert ob into front of this list public void insertHead(Object ob); // insert ob into front of this list public void insertTail(Object ob); // delete ob from this list (if it is there) public void delete(Object ob);
16
16 Insertion into tail of list public class List{ private ListCell head; public void insertHead(Object ob) { head= new ListCell(ob,head) } …} 87 a5 -7 a5 a6 24 a6 a7 p a1 head a1 a8 p.insertHead(new Integer(6)); 6 a7 a8
17
17 Insertion into Tail of list public class List{ private ListCell head; public void insertTail(Object ob) { if (head == null) head = new ListCell(ob, null) else { // Store in c the name of the tail of the list ListCell= head; while (c.getNext() != null) c= c.getNext(); c.setNext(new ListCell(ob, null)); } 87 87 a9 a5 -7 a5 a6 24 a6 a7 p a1 head a1 a7 p.insertTail(new Integer(6)); 6 a9
18
18 Example of use of insert methods List p= new List(null); //List p is empty p.insertHead(new Integer(-7)); //p contains -7 p.insertHead(new Integer(24)); //p contains 24, -7 p.insertTail(new Integer(87)); //p contains 24, -7, 87 …… 87 -7 a5 a6 24 a6 a7 p a1 head a1 a7 87 a5
19
19 Remove first item from list /** remove and return the first element of this list. Throw RuntimeException if this list is empty. */ public Object deleteFirst(){ if (head == null) { throw new RuntimeException(“List is empty”); } Object t= head.getDatum(); head= head.getNext(); return t; } -7 a5 a6 24 a6 a7 p head a1 a7 87 a5
20
20 Remove and return last item from list Cases: list is empty: throw an exception list contains one element: change head list contains >2 elements: change next-to-last element -7 a5 a6 24 a6 a7 p a1 head a1 a7 87 a5 p a1 head a1 null p a1 head a1 a7 24 a7
21
21 Finding penultimate element of list /** List size >= 2. Return name of penultimate element */ private Object getPenultimate() { ListCell c= head; ListCell scout= head.getNext(); /** invariant: c is name of a cell of the list, c.getNext() is not null, scout is the next cell following c */ while (scout.getNext() != null){ c= scout; scout= scout.getNext(); } return c; } -7 a5 a6 24 a6 a7 p a1 head a1 a7 87 a5 “penultimate” means “next to last”
22
22 Remove and return last item from list /** remove and return last element of list. Throw RuntimeException if list is empty */ public Object deleteLast(){ if (head == null) throw new RuntimeException(“list is empty”); if (head.getNext() == null) { Object t= head.getDatum(); head= null; return t; } // { list contains at least two elements } ListCell penultimate= getPenultimate; ListCell last= penultimate.getNext(); penultimate.setNext(null); return last.getDatum(); } -7 a5 a6 24 a6 a7 p a1 head a1 a7 87 a5
23
23 Delete object from list Delete first occurrence of an object ob from a list p. Idea of recursive code: –If list p is empty, return null. –If first element of p is ob, return rest of list p. –Otherwise, return list consisting of first element of p, and the list that results from deleting p from the rest of list p. -7 a5 a6 24 a6 a7 p a1 head a1 a7 87 a5
24
24 Recursive code for delete public class List{ private ListCell head; // Delete first occur. of ob from list (if it is there) public void delete(Object ob) { head= deleteRec(ob, head); } // = list lc but with first occur. of ob deleted (if there) private static ListCell deleteRec(Object ob, ListCell lc) { if (lc == null) return null; // handle empty list // { list lc is not empty } if (l.getDatum().equals(ob)) return lc.getNext(); // { first element of lc is not ob } lc.setNext(deleteRec(ob, lc.getNext())); return l; }
25
25 Finding elem element of list /** First element of list c is not ob. Return name of element that precedes ob (or null if none) */ private Object getOb(ListCell c, Object ob) { ListCell scout= head.getNext(); /** invariant: c is name of a cell of the list, c.getDatum() is not ob. scout is name of next element (null if none) */ while (scout != null && !scout.getDatum().equals(ob)){ c= scout; scout= scout.getNext(); } if (scout == null) return null; return c; } -7 a5 a6 24 a6 a7 p a1 head a1 a7 87 a5
26
26 Iterative code for delete // Delete ob from list, if there public void delete(Object ob) { if (head == null) return; // If first element is ob, remove it and return if (head.getDatum().equals(o)) { head= head.getNext(); return; } // { First element of list is not ob } ListCell preceding= getOb(head, ob); if (preceding == null) return; //splice out cell containing ob preceding.setNext(preceding.getNext()); }
27
27 Insertion and deletion with sorted lists Assume that we have a list of Comparables sorted in increasing order. We want to splice a new Comparable into this list, keeping new list in sorted order as shown in figure. Code shows recursive code for insertion and deletion. We show code that uses class ListCell directly. 24 a5 a6 -7 a6 a7 p a1 head a1 a7 87 a5
28
28 Recursive insertion Use notation [f,n] to denote ListCell whose datum is f next is n Pseudo-code: insert (Comparable c, ListCell l): if l is null return new ListCell(c,null); else suppose l is [f,n] if (c < f) return new ListCell(c,l); else return new ListCell(f, insert(c,n)); Compactly: insert(c,null) = [c,null] insert(c,[f,n]) = [c,[f,n]] if c < f [f, insert(c,n)] if c >= f
29
29 /** lc is a sorted list. Insert c into it */ public static ListCell insert(Comparable c, ListCell lc) { if (lc == null) return new ListCell(c, lc); // { list has at least one element } if (c.compareTo(lc.getDatum()) < 0) return new ListCell(c, lc); // { first element of list is > c } lc.setNext(insert(c,lc.getNext())); return lc; }
30
30 /** List lc is sorted. Delete first occ. of c from it (if there) */ public static ListCell delete(Comparable c, ListCell lc) { if ((l == null) return null; if (c.compareTo(lc.getDatum()) < 0) return lc; if (c.compareTo(lc.getDatum()) == 0) return lc.getNext(); lc.setNext(delete(c,lc.getNext())); return lc; }
31
31 Exercises 1.Write insert into a sorted list without recursion. 2.Write delete from a sorted list without recursion.
32
32 Doubly-linked lists In some applications, it is convenient to have a ListCell that references both its predecessor and its successor in the list. public class DLLCell { private Object datum; private DLLCell next; private DLLCell previous; ….. } -7 a6 a7 p a7 24 a5 a6 a6 8 a5
33
33 In general, it is easier to work with doubly-linked lists than with lists. For example, reversing a DLL can be done simply by swapping the previous and next fields of each cell. Trade-off: DLLs require more space than singly-linked lists.
34
34 Summary Lists are sequences of ListCell elements –recursive data structure –grow and shrink on demand –not random-access but sequential access data structures List operations: –create a list –access a list and update data –change structure of list by inserting/deleting cells cursors Recursion makes perfect sense on lists. Usually –base case: empty list, perhaps one-element list also –recursive case: non-empty list Sub-species of lists –list with header –doubly-linked lists
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.