18
Linked Lists – Part II CS 367 – Introduction to Data Structures

Linked Lists – Part II

Embed Size (px)

DESCRIPTION

Linked Lists – Part II. CS 367 – Introduction to Data Structures. Adding a Tail Reference. Up to now, we have only considered our lists to have a head reference having a tail reference makes adding to the end of the list much more efficient constant time: O(1) - PowerPoint PPT Presentation

Citation preview

Page 1: Linked Lists – Part II

Linked Lists – Part II

CS 367 – Introduction to Data Structures

Page 2: Linked Lists – Part II

Adding a Tail Reference• Up to now, we have only considered our

lists to have a head reference– having a tail reference makes adding to the

end of the list much more efficient• constant time: O(1)

– however, a tail reference makes things more complex

• must make sure that head and tail refer to null when the list is empty

• must make sure head and tail point to the same node when only one node in the list

Page 3: Linked Lists – Part II

Add/Delete Tailpublic void addTail(Object data) {

Node tmp = new Node(data, null);// empty list?if(tail == null) { head = tail = tmp; }else { tail.next = tmp; tail = tmp; }

}

public Object deleteTail() {if(tail == null) { return null; } // empty list.// get the tail and a reference to the previous nodeNode cur, prev = null;for(Node cur = head; cur != tail; prev = cur, cur = cur.next);tail = prev;if(tail == null) { head = null; } // list is now emptyelse { tail.next = null; }return cur;

}

Page 4: Linked Lists – Part II

Problem

• Adding to tail: O(1)

• Deleteing from tail: O(n)– this is because the list can only be searched

in one direction• from head to tail

– have to search entire list to find the node prior to the tail so that its next reference can be adjusted

Page 5: Linked Lists – Part II

Doubly Linked List

• Solution is to include a previous and a next pointer in a node– previous: refers to node immediately prior– next: refers to node immediately after– this is called a doubly linked list

• Now it is possible to search in both directions– also makes removing the tail O(1)

Page 6: Linked Lists – Part II

Doubly Linked List

John Smith

87.45

Jane Doe

87.45

Pat Thomas

87.45

Head Tail

next next next

previous previous previous

Page 7: Linked Lists – Part II

Doubly Linked List Node

• A node now looks slightly differentclass Node {

public Object data;

public Node previous;

public Node next;

public Node(Object data, Node previous, Node next) {

this.data = data;

this.previous = previous;

this.next = next;

}

• The linked list we will consider will have a head and a tail pointer

Page 8: Linked Lists – Part II

Inserting at the tail

• Inserting at the tail is almost identical– it is slightly more complicated

• one more reference to deal with

public void insertTail(Object data) {

tail = new Node(data, tail, null);

// is this the only node in the list?

if(tail.previous == null) { head = tail; }

else { tail.previous.next = tail; }

}

Page 9: Linked Lists – Part II

Removing Tail of List

• Removing a node at the tail is now quick

public Object deleteTail() {

if(tail == null) { return null; } // empty list

Node tmp = tail;

tail = tail.previous;

if(tail != null) { tail.next = null; }

else { head = null; }

return tmp.data;

}

– Notice that this operation is O(1) now

Page 10: Linked Lists – Part II

Adding a Nodepublic void add(Object data) {

Node tmp = new Node(data, null, null);if(head == null) { head = tail = tmp; } // list was empty

// find where the node goeselse {

Node cur;while((cur != null) && (((Comparable)cur.getData()).compareTo(data) <= 0))

cur = cur.next;tmp.setNext(cur);if(cur != null) {

tmp.setPrev(cur.getPrev());cur.setPrev(tmp);if(tmp.getPrev() != null)

{ tmp.getPrev().setNext(tmp); }else { head = tmp; }

}else { tmp.setPrev(tail); tail.setNext(tmp); tail = tmp; }

}

Page 11: Linked Lists – Part II

Adding a Node

• Remember, must consider the following cases– empty list– adding to head– adding to tail– adding to middle of the list

• Obviously, adding to the middle of a doubly linked list is more sophisticated

Page 12: Linked Lists – Part II

Appropriateness

• When should you use a doubly linked list?– depends on your application

• if you are routinely deleting from tail• if you know where the desired node is

– may be faster to search from the rear

• Anything you can do with a singly linked list can be done with a doubly linked list– reverse is not true

Page 13: Linked Lists – Part II

Circular Lists

• May want a list to form a ring (why?)– every node has a successor

• if it is a doubly linked circular list, every node has a successor and a predecessor

– no head or tail• only need to keep track of current node

– if only one node in the list, its successor is itself

• current.next = current

– if the list is empty, current refers to null

Page 14: Linked Lists – Part II

Circular List

current

data

next

current

current

data

next

data

next

data

next

Empty list.

One node in list.

Multiple nodes in list.

Page 15: Linked Lists – Part II

Inserting a Node

• While there is no head or tail, we do have a concept of the beginning and end of list– beginning: what current is referencing– end: node immediately prior to current

• When using a circular list, usually does not matter much about the ordering– so usually insert immediately after or before

the current node

Page 16: Linked Lists – Part II

Inserting a Node After Current

public void insert(Object data) {Node tmp = new Node(data, null);

// check if this is the only node in the listif(current == null) {

tmp.setNext(tmp);current = tmp;

}else {

tmp.setNext(current.getNext());current.setNext(tmp);

}}

Page 17: Linked Lists – Part II

Inserting Node Before Current

• In a singly linked list, this is more difficult– either need to keep track of the tail and do the

insert– or you need to search from current to the end

of the list• how do you know when a complete loop has been

made around the list?• what is the problem with this method?

Page 18: Linked Lists – Part II

Removing the Current Node

• When doing a remove, usually removing the current node– why?

• This can cause some problems if a singly linked list is used to implement circular list– have to find and update tail of list– requires a search all the way through the list

• O(n)

– problem easily solved by using a doubly linked list