Singly Linked Lists Representation Space Analysis Creation and

  • Slides: 24
Download presentation
Singly Linked Lists • Representation • Space Analysis • Creation and Insertion • Traversal

Singly Linked Lists • Representation • Space Analysis • Creation and Insertion • Traversal • Search • Deletion

Representation • We are using a representation in which a linked list has both

Representation • We are using a representation in which a linked list has both head and tail references. public class My. Linked. List{ protected Element head; protected Element tail; public final class Element{ Object data; Element next; Element(Object obj, Element element){ data = obj; next = element; } public Object get. Data(){return data; } public Element get. Next(){return next; } } } list head tail

Representation: Space Analysis • Now, we can take a look at the space requirements:

Representation: Space Analysis • Now, we can take a look at the space requirements: S(n) = sizeof(My. Linked. List) + n sizeof(My. Linked. List. Element) = 2 sizeof(My. Linked. List. Element ref) + n [sizeof(Object ref) + sizeof(My. Linked. List. Element ref)] = (n + 2) sizeof(My. Linked. List. Element ref) + n sizeof(Object ref) Space Require Explanation sizeof(My. Linked. List) The list reference has two fields: head (type: Element) and tail (type: Element) = 2 sizeof(My. Linked. List. Element ref) n sizeof(My. Linked. List. Element) The list has n elements of type Element. Each element has two fields-- data (type Object) and next (type Element).

List Creation and Insertion • An empty list is created as follows: head My.

List Creation and Insertion • An empty list is created as follows: head My. Linked. List list = new My. Linked. List(); tail • Once created, elements can be inserted into the list using either the append or prepend methods for (int k = 0; k < 10; k++) list. append(new Integer(k)); • Also if we have reference to a node (an element), we can use insert. After or Insert. Before of the Element class.

Insertion at the end (Append) public void append(Object obj){ Element element = new Element(obj,

Insertion at the end (Append) public void append(Object obj){ Element element = new Element(obj, null); if(head == null) head = element; else tail. next = element; tail = element; } Complexity is O(1)

Insertion at the beginning (Prepend) public void prepend(Object obj) { Element element = new

Insertion at the beginning (Prepend) public void prepend(Object obj) { Element element = new Element(obj, head); if(head == null) tail = element; head = element; Complexity is O(1) }

Insertion before and after an element public void insert. Before(Object obj) { Element element

Insertion before and after an element public void insert. Before(Object obj) { Element element = new Element(obj, this); if(this == head) { head = element; return; } Complexity is O(n) Element previous = head; while (previous. next != this) { previous = previous. next; } previous. next = element; } public void insert. After(Object obj) { next = new Element(obj, next); if(this == tail) tail = next; Complexity is O(1) }

Traversal To move a reference e from one node to the next: e =

Traversal To move a reference e from one node to the next: e = e. next; Example: Count the number of nodes in a linked list. public int count. Nodes(){ int count = 0; Element e = head; while(e != null){ count++; e = e. next; Complexity is } return count; } O(n)

Searching • To search for an element, we traverse from head until we locate

Searching • To search for an element, we traverse from head until we locate the object. Example: Count the number of nodes with data field equal to a given object. public int count. Nodes(Object obj){ int count = 0; Element e = head; while(e != null){ if(e. data. equals(obj)) count++; Complexity is …. e = e. next; } return count; }

Deletion • To delete an element, we use either the extract method of My.

Deletion • To delete an element, we use either the extract method of My. Linked. List or that of the Element inner class. public void extract(Object obj) { Element element = head; Element previous = null; while(element != null && ! element. data. equals(obj)) { previous = element; element = element. next; Complexity } if(element == null) throw new Illegal. Argument. Exception("item not found"); if(element == head) head = element. next; else previous. next = element. next; if(element == tail) tail = previous; } is …

Deletion - Difference between the My. Linked. List and the Element extracts • To

Deletion - Difference between the My. Linked. List and the Element extracts • To delete an element, we use either the extract method of My. Linked. List or that of the Element inner class. try{ list. extract(obj 1); } catch(Illegal. Argument. Exception e){ System. out. println("Element not found"); } My. Linked. List. Element e = list. find(obj 1); if(e != null) e. extract(); else System. out. println("Element not found");

Deletion – Deleting First and Last Element public void extract. First() { if(head ==

Deletion – Deleting First and Last Element public void extract. First() { if(head == null) throw new Illegal. Argument. Exception("item not found"); head = head. next; if(head == null) tail = null; Complexity } public void extract. Last() { if(tail == null) throw new Illegal. Argument. Exception("item not found"); if (head == tail) head = tail = null; else { Element previous = head; Complexity while (previous. next != tail) previous = previous. next; previous. next = null; tail = previous; } } is …

Exercises • For the My. Linked. List class, Implement each of the following methods:

Exercises • For the My. Linked. List class, Implement each of the following methods: – String to. String() – Element find(Object obj) – void insert. At(int n) //counting the nodes from 1. State the complexity of each method. • Which methods are affected if we do not use the tail reference in My. Linked. List class.

Doubly Linked Lists • Representation • Space Analysis • Creation and Insertion • Traversal

Doubly Linked Lists • Representation • Space Analysis • Creation and Insertion • Traversal • Deletion

Representation public class Doubly. Linked. List{ protected Element head, tail; //. . . public

Representation public class Doubly. Linked. List{ protected Element head, tail; //. . . public class Element { Object data; Element next, previous; Element(Object obj, Element next, Element previous){ data = obj; this. next = next; this. previous = previous; } public Object get. Data(){return data; } public Element get. Next(){return next; } public Element get. Previous(){return previous; } //. . . } } list head tail

Doubly Linked Lists : Space Analysis • The space requirements of our representation of

Doubly Linked Lists : Space Analysis • The space requirements of our representation of the doubly linked lists is as follows: S(n) = sizeof(Doubly. Linked. List) + n sizeof(Doubly. Linked. List. Element) = 2 sizeof(Doubly. Linked. List. Element ref) + n [sizeof(Object ref) + 2 sizeof(Doubly. Linked. List. Element ref)] = (2 n + 2) sizeof(Doubly. Linked. List. Element ref) + n sizeof(Object ref) Required space sizeof(Doubly. Linked. List) n sizeof(Doubly. Linked. List. Element) Explanation The list reference has two fields: head (type: Element) and tail (type: Element) = 2 sizeof(Doubly. Linked. List. Element ref) The list has n elements of type Element. Each element has three fields-- previous (type Element), data (type Object), and next (type Element)

List Creation and Insertion head • An empty doubly linked list is created as

List Creation and Insertion head • An empty doubly linked list is created as follows: Doubly. Linked. List list = new Doubly. Linked. List(); b) tail • Like singly link list, once created, elements can be inserted into the list using either the append or prepend methods for (int k = 0; k < 10; k++) list. append(new Int(k)); • Also if we have reference to a node (an element), we can use insert. After or Insert. Before of the Element class. .

Insertion at the end (append) public void append(Object obj){ Element element = new Element(obj,

Insertion at the end (append) public void append(Object obj){ Element element = new Element(obj, null, tail); if(head == null) head = tail = element; else { tail. next = element; tail = element; Complexity is … } }

Insertion at the beginning (prepend) public void prepend(Object obj){ Element element = new Element(obj,

Insertion at the beginning (prepend) public void prepend(Object obj){ Element element = new Element(obj, head, null); if(head == null) head = tail = element; else { Complexity is … head. previous = element; head = element; } }

Insertion before an element • Inserting before the current node (this) that is neither

Insertion before an element • Inserting before the current node (this) that is neither the first nor the last node: Element element = new Element(obj, this. previous); this. previous. next = element; this. previous = element; Complexity is …

Traversal For Doubly. Linked list, traversal can be done in either direction. Forward, starting

Traversal For Doubly. Linked list, traversal can be done in either direction. Forward, starting from head, or backward starting from tail. Element e = head; while (e != null) { //do something e = e. next; } Element e = tail; while (e != null) { //do something e = e. previous; } Example: Count the number of nodes in a linked list. public int count. Nodes(){ int count = 0; Element e = head; while(e != null){ count++; Complexity is … e = e. next; } return count; }

Traversal Example: The following computes the sum of the last n nodes: public int

Traversal Example: The following computes the sum of the last n nodes: public int sum. Last. Nnodes(int n){ if(n <= 0) throw new Illegal. Argument. Exception("Wrong: " + n); if(head == null) throw new List. Empty. Exception(); int count = 0, sum = 0; Element e = tail; Complexity is … while(e != null && count < n){ sum += ((Integer)e. data). int. Value(); count++; e = e. previous; } if(count < n) throw new Illegal. Argument. Exception(“No. of nodes < "+n); return sum; }

Deletion • To delete an element, we use either the extract method of Doubly.

Deletion • To delete an element, we use either the extract method of Doubly. Linked. List or that of the Element inner class. public void extract(Object obj){ Element element = head; while((element != null) && (!element. data. equals(obj))) element = element. next; Complexity is … if(element == null) throw new Illegal. Argument. Exception("item not found"); if(element == head) { head = element. next; if(element. next != null) element. next. previous = null; }else{ element. previous. next = element. next; if(element. next != null) element. next. previous = element. previous; } if(element == tail) tail = element. previous; }

Exercises • For the Doubly. Linked. List class, Implement each of the following methods

Exercises • For the Doubly. Linked. List class, Implement each of the following methods and state its complexity. – – – String to. String() Element find(Object obj) void Extract. Last() void Extract. First() void Extract. Last. N(int n) • For the Doubly. Linked. List. Element inner class, implement each of the following methods and state its complexity. – void insert. Before() – void insert. After() – void extract() • What are the methods of Doubly. Linked. List and its Element inner class are more efficient than those of My. Linked. List class?