variations on linked lists ellen walker cpsc 201 data structures hiram college

23
Variations on Linked Lists Ellen Walker CPSC 201 Data Structures Hiram College

Upload: treyton-baron

Post on 16-Dec-2015

220 views

Category:

Documents


2 download

TRANSCRIPT

Variations on Linked Lists

Ellen Walker

CPSC 201 Data Structures

Hiram College

Linked List (review)

• Each element contains two parts:– Value of this element– Pointer to the next element

class string_node {

Private:

string val;

string_node *next;

}

Inserting into a Linked List (Review)

BarryAnn

Carol

Ellen

/* Assume item is a reference to the node that contains “Barry”*/

Node<string> newNode = new Node<string> (“Carol”);

newNode.next = aNode.next;

aNode.next = newitem;

Printing a Linked List (Review)

//print elements, starting at the node called head;

// Uses a for loop

for(Node<String> current=head; current!=null; current=current.next){

System.out.println(current.data);

}

Printing Using Iterator (Review)

//prints the list, one item per line

//returns iterator pointing before the list…

Iterator<String> itr = aList.iterator();

while(itr.hasNext()){

String name = itr.next();

System.out.println(name);

}

LinkedList Implementation (Review)

public class LinkedList<E>{ private Node<E> head; //first element or null private int size; //list length … private static class Node<E>{ //inner class private E data; private node<E> next;

}

//methods go here}

Implementing toString

• Writes elements of list into a string• Use either traversal from before (iterator version

shown)String toString(){ StringBuilder result = new StringBuilder(); Iterator<E> itr = iterator(); while(itr.hasNext()){ result.append(itr.next());

result.append(‘\n’); }}

Dummy Nodes simplify implementation

• An empty list has one node (the dummy node)• There is no longer a special case for adding the first

element of the node!• What changes need to be made to…

– Constructor?– Find / Retrieve ?– Insert / Delete?

• Sometimes a dummy node can have a useful value (e.g. smallest possible element for sorted list)

Changes to the implementation for a dummy node

• Constructor– Head is a new (dummy) node instead of NULL

• indexOf / get– indexOf is unchanged (assume value not

otherwise in list)– get(k) will return value at node (k+1)

• Insert / Delete– Begin by locating the predecessor node– No special cases for first node (it has a

predecessor)

Circular List

• Circular List: The tail of the list points back to the head

• There is no NULL pointer to “end” the list.

Issues with circular list

• How do you know when you’re done?– Make sure you save the head pointer.– When (cur.next == head) you’ve reached the end

• How are insertion and deletion handled?– No special cases!– Predecessor to head node is the last node in the

list.

The Josephus Problem

• (One of many variations…)The founder of a startup is forced to lay off all but one employee. Not having any better way to decide, he arranges all employees in a circle and has them count off. The 10th employee in the circle is laid off, and the count begins again. The last person is not laid off.

• If there are N employees, where should you sit to avoid being laid off?

Solution

• Model the circle of employees as a circular linked list

• Implement the counting off process, and delete the 10th employee each time

• After N-1 people are deleted, there should be only one employee left.

• That employee’s original position number is the solution to the problem.

Doubly Linked List

• Each node has prev and next pointer• List can be traversed forward or backward• To insert a node after “cur”

– Node<E> tmp = new Node<E>(newItem);– tmp.next = cur.next;– cur.next=tmp;– tmp.prev=cur;– tmp.next.prev = tmp;

• Reverse the process to delete!

Which list implementation?

• Array– Can jump into the middle easily (random access)– Inserting & deleting can require time-consuming shifting– Must allocate block of memory at once (can resize later with new)

• Linked– No random access– Insert & delete are fixed cost, once you decide where.– Nodes allocated one at a time.

Linked List Choices

• Plain vanilla– Simple, small

• Dummy header– Eliminates special cases (chance for error)

• Circular– No defined start position in sequence– Can find the node before, though it takes N steps

• Doubly linked– Easy to find the node before– Larger Node; twice as many special cases

• Circular and doubly linked

Linked Lists and Recursion

• Recursive definition of a list– Null (empty list) is a list (base case)– A list consists of one item (the head) followed by a

list (next)

• Example:– A->B->C-| is a list– Head = A, next = B->C-|

Recursive Function on Lists

• Base case for the recursive function is the empty list (base case for the definition)

• Other cases -– “Take a step” = do something to the head– Recurse = call function for the rest of the list– May or may not build up a solution

Recursive List Search

Node<E> recFind (Node<E> head, E x){//x is not in an empty list!

If (head == null) return null;

//x is found at the beginning

Else if (head.item == x) return head;

//Recursive case: search the rest of the list

Return recFind(head.next, x);

}

Recursive functions are private!

• A recursive function uses Node references.• Node references are private

– Implementation detail– Not every implementation of List has Nodes

• Most recursive functions have a public “starter” and a private internal function

Public Caller for recFind

boolean isIn(E x){

//call Find on the head of the list

//if Find does not return null, the item is in

// the list.

return (recFind(head,x) != null);

}

Recursive CountItem

• This function counts the number of occurrences of the item x in the list

Int CountItem (Node * head, ItemType x){

}

Public Caller for CountItem

int List::howMany(ListItemType x){

}