Adapted from the Goodrich and Tamassia lecture on Sequences.
Interface Container
Interface java.util.Iterator
- The ranked sequence S (with n elements) supports the following methods:
- elemAtRank(r):
- replaceElemAtRank(r, e):
- insertElemAtRank(r, e):
- removeElemAtRank(r):
Ranked Sequence Inheritance Diagram
- Some pseudo-code:
for i = n-1, n-2, …, r do
S[i + 1] <---- S[i]
S[r] ¬ e
n <----n + 1 Algorithm removeElemAtRank(r):
e <----S[r]
for i = r, r+1, … , n-2 do
S[i] <---- S[i+1]
n <----n – 1
S[i+1] ¬ null
return e
O(n – r + 1)
= O(n) in the worst case of r = 0
= O(1) in the best case of r = n – 1 for removeMinElement or r = n for insertElemAtRank.
- A graphical representation
Implementation with a Doubly Linked List
- The list before insertion:
prev = next.getPrev();
- Creating a new node for insertion:
prev.setNext(newNode);
newNode.setPrev(prev);
newNode.setNext(next);
next.setPrev(newNode);
Implementation with a Doubly Linked List (cont.)
- The list after insertion and before deletion:
- Deleting a node: Let's say we call removeAtRank(2)
prev = node.getPrev();
next = node.getNext();
- after deletion
Ranked Sequence Inheritance Diagram
Java Implementation
public Object elemAtRank (int rank) {
checkRank(rank);
return nodeAtRank(rank).getElement();
}
public Object replaceElemAtRank (int rank, Object newElement)
throws BoundaryViolationException {
checkRank(rank);
DLNode node = nodeAtRank(rank);
Object oldElement = node.getElement();
node.setElement(newElement);
return oldElement;
}
Java Implementation (cont.)
throws BoundaryViolationException {
if (rank != size()) // rank size() is OK for insertion
checkRank(rank);
DLNode next = nodeAtRank(rank); // the new node //will be right before this
DLNode prev = next.getPrev(); // the new node will //be right after this
DLNode node = new DLNode(element, prev, next);
next.setPrev(node);
prev.setNext(node);
size++;
}
Java Implementation (cont.)
checkRank(rank);
DLNode node = nodeAtRank(rank); // node to be //removed
DLNode next = node.getNext(); // node after it
DLNode prev = node.getPrev(); // node before it
prev.setNext(next);
next.setPrev(prev);
size--;
return node.getElement();
}
Java Implementation (cont.)
// auxiliary method to find the node of the element //with the given rank
DLNode node;
if (rank <= size()/2) { // scan forward from the head
node = header.getNext();
for (int i=0; i < rank; i++)
node = node.getNext();
}
else { // scan backward from the tail
node = trailer;
for (int i=0; i < size()-rank ; i++)
node = node.getPrev();
}
return node;
}
private void checkRank (int rank) throws BoundaryViolationException {
if (rank < 0 || rank > size()-1)
throw new BoundaryViolationException("Invalid rank.");
}
}
Complexity of RankedSequence Methods
- Comparison of array-based vs. doubly linked-list implementation of RankedSequence methods.
Method |
|
|
|
|
|
size |
|
|
isEmpty |
|
|
elemAtRank |
|
|
replaceElemAtRank |
|
|
insertElemAtRank |
|
|
removeElemAtRank |
|
|
space |
|
|
- Node-based operations:
- Advantage: Node-specific methods, e.g. removeAtNode(Node v) and insertAfterNode(Node v, Object e) would be O(1).
- Disadvantage: Node-based operations are not meaningful in an array-based implementation because there are no nodes in an array.
- Dilemma:
- If we do not include the node-based operations in the generic sequence ADT, we are not taking full advantage of doubly linked lists.
- If we do include them, we violate the generality of object-oriented design.
- Positions:
- Intuitive notion of "place" of an element.
- This concept allows us to enjoy doubly linked list without violating object-oriented design principles.
- The Position ADT has two methods:
Input: none; Output: Object
throw an UnsupportedOperationException.
Input: none; Output: Container
- Positions are defined relatively, i.e., in terms of their neighbors.
- Positions are not tied to an element or rank.
- A Sequence is a Container of elements that are each stored in a Position.
Interface PositionalContainer
PositionalSequence Inheritance Diagram
Sequence Inheritance Diagram
Array Implementation of Sequence
- It is not sufficient to merely store elements in the array, since the cells would have no way of accessing their corresponding positions.
- Store Position references as array elements.
- If implemented with a linear array, methods insertFirst, insertBefore, insertAfter, removeFirst, and remove would require O(n) operations because the position objects need to be shifted. The worst case would occur when removing or inserting to the front position. The methods insertLast and removeLast are O(1).
- If implemented with a circular array, methods insertFirst and removeFirst are O(1). Methods insertBefore, insertAfter, and remove are O(n) but worst case occurs when .
Class NodeSequence
Doubly Linked-List Implementation of Sequence – class NSNode
private NSNode prev, next; //# References to the //nodes before and after
private Object element; //# Element stored in this //position
private Container cont; //# Container of this position
NSNode(NSNode newPrev, NSNode newNext, Container container, Object elem) {
//# Initialize //the node
prev = newPrev;
next = newNext;
cont = container;
element = elem;
}
// Methods from interface Position
public Container container() throws InvalidPositionException {
if (cont == null)
throw new InvalidPositionException("Position has no container!");
return cont;
}
if (cont == null) throw new InvalidPositionException("Position has no container!");
return element;
}
// Accesor methods
NSNode getNext() { return next; }
NSNode getPrev() { return prev; }
void setNext(NSNode newNext) { next = newNext; }
// Update methods
void setPrev(NSNode newPrev) { prev = newPrev; }
void setElement(Object newElement){ element = newElement; }
void setContainer(Container newCont){ cont = newCont; }
}
NSNode.java
throws BoundaryViolationException { //# Thrown if rank<0 or rank > numElts-1
checkRank(rank);
// loop until find element at this rank
NSNode current = head.getNext();
for (int i = 0; i < rank; i++) {
current = current.getNext();
}
return current;
}
public Position before (Position p) //# Return position before this one
throws InvalidPositionException, BoundaryViolationException {
NSNode n = checkPosition(p);
NSNode prev = n.getPrev();
if (prev == head)throw new BoundaryViolationException
("Cannot advance past the beginning of the sequence");
return prev;
}
NSNode n = checkPosition(p);
numElts++;
NSNode newNode = new NSNode(n, n.getNext(), this, element);
n.getNext().setPrev(newNode);
n.setNext(newNode);
return newNode;
}
public Position first() //# Return the first position in the sequence
throws EmptyContainerException { //# Thrown if the sequence is empty
if(isEmpty())
throw new EmptyContainerException("Sequence is empty");
return head.getNext();
}
Doubly Linked-List Implementation of Sequence – Class NodeSequence (cont.)
throws InvalidPositionException {
NSNode n = checkPosition(p);
numElts--;
NSNode nPrev = n.getPrev();
NSNode nNext = n.getNext();
nPrev.setNext(nNext);
nNext.setPrev(nPrev);
Object nElem = n.element();
// unlink the position from the list and make it invalid
n.setNext(null);
n.setPrev(null);
n.setContainer(null);
return nElem;
}
NodeSequence.java
Method(s) |
|
|
|
|
|
size, isEmpty |
|
|
atRank, rankOf, elemAtRank |
|
|
first, last |
|
|
before, after |
|
|
replace, swap |
|
|
insertElemAtRank, removeElemAtRank |
|
|
insertFirst, insertLast |
|
|
insertAfter, insertBefore |
|
|
remove |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
Lafore Bubble-Sort Applet
- Here is an implementation of bubble-sort for an array-based sequence
public void static bubbleSort1(IntegerSequence s)
{
int n = s.size();
for(int i = 0; i < n; i++)
for(int j = 0; j < n-i-1; j++)
if(s.atRank(j).element.intValue() > s.atRank(j+1).element().intValue())
swap(s.positionAtRank(j), s.positionAtRank(j+1));
}
- This implementation is designed for a sequence based on a doubly linked list.
- public void
static
bubbleSort2(IntegerSequence s)
{
int n = s.size();
IntegerSequencePosition prec, succ;
for(int i = 0; i < n; i++) // ith pass
{
prec = s.firstPosition();
for(int j = 0; j < n-i-1; j++)
{
succ = s.after(prec);
if(prec.element().intValue() > (succ.element().intValue())
swap(prec,succ);
else
prec = succ;
}
}
}
- Assume that accesses to sequence elements and swaps are O(1).
- Bubble-sort requires n passes. Designate i as the current pass number. i = 1,…,n.
- In the ith pass, only the first n-i+1 elements of the sequence are considered.
- Cost of all n passes = .
- Recall that .
- Thus the overall cost of bubble-sort is
No comments:
Post a Comment