Sie sind auf Seite 1von 6

/** DList.

java */
public class DList <E>{
private Node<E> mHead; // sentinels
private Node<E> mTail;
private int mSize; // num of elements
public DList() { setHead(null); setTail(null); setSize(0); }
public DList(E pData) { // ctor sets pData only
Node<E> newNode = new Node<>(pData);
setHead(newNode); setTail(newNode); setSize(1);
}

return data; }
/** removes an interior node pNode from this DList. Does not check the
* empty list condition. Returns the data stored in pNode. */
protected E removeInterior(Node<E> pNode) {
E data = (E) pNode.getData();
pNode.getPrev().setNext(pNode.getNext());
pNode.getNext().setPrev(pNode.getPrev());
setSize(getSize() - 1);
return data; }

public void add( int pIndex, E pData ) throws IndexOutOfBoundsException {


if( pIndex < 0 || pIndex > getSize() ) throw new
IndexOutOfBoundsException();
if ( pIndex == 0 ) addHead( pData ); // add new Node as DList head
else if ( pIndex == getSize() ) addTail( pData ); // add new Node as DList
tail
// get reference to Node at pIndex, pass to addInterior()
else addInterior( pData, getNodeAt( pIndex ) ); }
/** adds newNode storing pData as the new head of this DList. */
protected void addHead(E pData) {
Node<E> newNode = new Node<>(pData, null, getHead());
if (getHead() == null) { // if DList is empty
setTail(newNode); // set newNode as new tail
} else { // there's an existing head
// set mPrev of prior head node to point to newNode as new head
getHead().setPrev(newNode);
}
setHead(newNode); // mHead -> newNode
setSize(getSize() + 1); } // DList has one more Node
/** adds newNode storing pData to be the predecessor to pNode,
* an existing Node that may currently be head or tail Node */
protected void addInterior(E pData, Node<E> pNode) {
if (pNode == getHead()) { addHead(pData); }
else {
// set newNode mPrev to pNode mPrev, mNext = pNode passed in
Node<E> newNode = new Node<E>(pData, pNode.getPrev(), pNode);
// set pNode's predecessor mNext field to point to newNode
pNode.getPrev().setNext(newNode);
// set pNode mPrev field to point to newNode
pNode.setPrev(newNode);
setSize(getSize() + 1);
}
}
/** adds newNode storing pData to be the new tail of this DList. */
protected void addTail(E pData) {
Node<E> newNode = new Node<>(pData, getTail(), null);
if (getTail() == null) { setHead(newNode); }
else { getTail().setNext(newNode); }
setTail(newNode); // newNode is new tail
setSize(getSize() + 1); }
public
public
pData
public
pData
public
elements

boolean isEmpty() { return getSize() == 0; }


void prepend(E pData) { addHead( pData); } // prepends new Node w/
void append(E pData) { addTail( pData ); } // appends new Node w/
void clear() { while (!isEmpty()) { remove(0); } } // removes all

/** returns the element at index pIndex. */


public E get(int pIndex) throws IndexOutOfBoundsException {
return (E) getNodeAt(pIndex).getData();
}
/** returns a reference to the Node at index pIndex. */
protected Node<E> getNodeAt(int pIndex) throws
IndexOutOfBoundsException {
// Check for pIndex out of bounds and throw exception is necessary.
if (pIndex < 0 || pIndex >= getSize()) throw new
IndexOutOfBoundsException();
// Accessing head / tail nodes is a common operation so check for those
cases first.
if (pIndex == 0) return getHead();
else if (pIndex == getSize() - 1) return getTail();
// Otherwise, start at the node at index 1 and walk forward until the node
at index pIndex
// is reached and then return it.
Node<E> node = getHead().getNext();
for (int index = 1; index < pIndex; ++index) node = node.getNext();
return node; } // end getNodeAt()
public E remove(int pIndex) throws IndexOutOfBoundsException {
Node<E> node = getNodeAt(pIndex); // make reference
if ( isEmpty() ) return null; // check for empty list
if( pIndex == 0 ) return removeHead(); // remove head node, return data
else if( pIndex == getSize() - 1 ) return removeTail(); // remove tail node,
return data
else
// removing interior node, return data from
removed node
return removeInterior(node);
} // end remove()
/** removes the head node pNode from this DList. Does not check the
* empty list condition. Returns the data stored in the head node. */
protected E removeHead() {
E data = getHead().getData();
if (getSize() == 1) {
setHead(null);
setTail(null);
} else {
getHead().getNext().setPrev(null);
setHead(getHead().getNext());
}
setSize(getSize() - 1);

/** removes the tail node pNode from this DList. Does not check the
* empty list condition. Returns the data stored in pNode. */
protected E removeTail() {
E data = getTail().getData();
if (getSize() == 1) {
setHead(null); setTail(null);
} else {
getTail().getPrev().setNext(null);
setTail(getTail().getPrev());
}
setSize(getSize() - 1);
return data; }

//

//

//

/** removes all occurrences of nodes with specified pData from this DList */
public void removeAll( Integer pData ) {
Node<E> node = getHead(); // create Node reference to current head
if( node == null ) return; // empty; node -> nothing - this is base case
while ( node.getData().equals( pData ) ) { // current head has pData?
while ( node.getData() == pData ) { // current head has pData?
removeHead(); // pData match @ head, so remove head
node = getHead();
} // all head Nodes w/ pData have been removed at this point
node = getHead().getNext(); // move reference to next node
while ( node != getTail() ) { // loop until reach tail node
if( node.getData().equals( pData ) ) {
if( node.getData() == pData ) {
// System.out.println("interior match"); // debug only
removeInterior( node ); // current interior node has pData?
}
node = node.getNext(); // move reference to next node
} // all interior nodes w/ pData have been scanned, so next must be tail
if( node.getData().equals( pData ) ) { // if pData in tail node, remove tail
if( node.getData() == pData ) { // if pData in tail node, remove tail
removeTail(); return;
} }
/** splits DList into sublists pLeft / pRight. pLeft: indices 0, 1, 2, ..., pIndex -

1;
* pRight: indices pIndex, pIndex + 1, ..., getSize() - 1. */
public void split(int pIndex, DList<E> pLeft, DList<E> pRight)
throws IndexOutOfBoundsException {
if( pIndex < 0 || pIndex > getSize() )
throw new IndexOutOfBoundsException();
/** if pIndex == 0 all list elements will appear in pRight, none in pLeft
* if pIndex == getSize() all list elements will appear in pLeft */
Node<E> node = getHead(); // create reference to existing list
for ( int i = 0; i < pIndex; i++ ) { // build pLeft
pLeft.append( node.getData() );
node = node.getNext();
}
for ( int i = pIndex; i < getSize(); i++ ) { // build pRight
pRight.append( node.getData() );
node = node.getNext();
}
}
public E set(int pIndex, E pData) throws IndexOutOfBoundsException {
Node<E> node = getNodeAt(pIndex);
E original = node.getData(); // fetch original value
node.setData(pData); // sets mData field
return original; // Returns element previously stored at pIndex
}
/** methods for the mHead / mTail / mSize fields */
protected void setHead(Node<E> pHead) { mHead = pHead; }
protected void setTail(Node<E> pTail) { mTail = pTail; }
protected void setSize(int pSize) { mSize = pSize; }
protected Node<E> getHead() { return mHead; }
protected Node<E> getTail() { return mTail; }
public int getSize() { return mSize; }
@Override public String toString() { // string rep of DList
String string = "";
for (int i = 0; i < getSize(); ++i) string += get(i) + " ";
return string;
}
/** Static Nested Class: Node */
protected static class Node<E> {
E mData; Node<E> mNext; Node<E> mPrev;
public Node() { this(null); } // ctor mData, mNext, mPrev all null
public Node(E pData) { setData(pData); setNext(null); setPrev(null); }
public Node(E pData, Node<E> pPrev, Node<E> pNext) {
setData(pData); // ctor sets mData, mNext & mPrev
setPrev(pPrev); setNext(pNext);
}
@Override public boolean equals(Object pNode) {
Node<E> node = (Node<E>)pNode;
if (node == null) return false;
if (this == node) return true; // both point to same object
if (getData() == node.getData() && getNext() == node.getNext() &&
getPrev() == node.getPrev()) return true; // all fields match
return false;
}
/** methods for mData, mNext, mPrev variables */
public E getData() { return mData; }
public Node<E> getNext() { return mNext; }

public
public
public
public

Node<E> getPrev() { return mPrev; }


void setData(E pData) { mData = pData; }
void setNext(Node<E> pNext) { mNext = pNext; }
void setPrev(Node<E> pPrev) { mPrev = pPrev; }

@Override public String toString() { return "" + getData(); }


} // end class Node
} // end class Dlist

/** recursive linear search algorithm */


public int recLinearSearch(ArrayList<String> pList, String pKey, int pBeginIdx, int
pEndIdx) {
if( pList.size() == 0 ) return -1; // empty list ??
if( pList.get( pBeginIdx ) == pKey ) return pBeginIdx; // pointing to pKey?
if ( ( pBeginIdx + 1 ) <= pEndIdx )
return recLinearSearch( pList, pKey, pBeginIdx + 1, pEndIdx ); // call again
with next index
return -1; // pKey not found in range
}
SORT
/** Insertion Sort: ascending (pOrd = 0 ) or descending order */
public ArrayList<Integer> insertionSort(ArrayList<Integer> pList, int pOrd) {
if( pList == null ) return null;
ArrayList<Integer> arr = pList;
for (int i = 1; i < arr.size(); ++i)
for (int j = i; keepMoving(arr, j, pOrd); --j) swap(arr, j, j - 1);
return arr;
}
/** Return true if need to continue moving the element at pIndex */
private boolean keepMoving(ArrayList<Integer> pList, int pIndex, int pOrd) {
if (pIndex < 1) return false;
Integer curr = pList.get(pIndex);
Integer prev = pList.get(pIndex - 1);
return (pOrd == A) ? curr.compareTo(prev) < 0 : curr.compareTo(prev) > 0;
}
/** Swaps the elements in pList at pIndex1 and pIndex2. */
private void swap(ArrayList<Integer> pList, int pIndex1, int pIndex2) {
Integer temp = pList.get(pIndex1);
pList.set(pIndex1, pList.get(pIndex2));
pList.set(pIndex2, temp);
}
// ascending selection sort for Integers
public ArrayList<Integer> asSelectionSort(ArrayList<Integer> array) {
if ( array == null || array.size() == 0 || array.size() == 1 ) return null;
ArrayList<Integer> arr = array; // create new arraylist for return
int minIdx; // index for element with min value
int min; // min value for each outer loop iteration
for (int curIdx = 0; curIdx < arr.size(); curIdx++) {
/* find the index at which the element has min value */
min = arr.get(curIdx); // assign current min to current index
minIdx = curIdx; // save index to current min
for (int i = curIdx + 1; i < arr.size(); i++) {
if (min > arr.get(i)) {
min = arr.get(i); // update min
minIdx = i;
System.out.print("\nshift: ");
}
}
if (minIdx != curIdx) { // do nothing if curIdx points to min value
Integer tmp = arr.get(curIdx); // otherwise swap values
arr.set(curIdx, arr.get(minIdx));
arr.set(minIdx, tmp);
}
}
return arr;
} // end asSelectionSort()

Static nested class methods


do not have access to
enclosing instance variables
or methods (not an inner
class).

SEARCH
/** trace binary search: pL, pH, mid, pL>pH? */
/** recursive binary search algorithm; 'a' for ascending list */
public int recBinarySearch(ArrayList<Integer> pList, Integer pKey, char a, int
pLow, int pHigh ) {
if ( pLow > pHigh ) return -1; // key not found
int middle = ( pLow + pHigh ) / 2;
if ( pKey.equals( pList.get( middle ) ) ) return middle; // found it @ middle
else if ( pKey.compareTo( pList.get( middle ) ) < 0 )
return ( a == 'a' ) ?
recBinarySearch(pList, pKey, a, pLow, middle - 1) : //
ascending
recBinarySearch( pList, pKey, a, middle + 1, pHigh );
else
return ( a == 'a' ) ?
recBinarySearch(pList, pKey, a, middle + 1, pHigh) : // ascending
recBinarySearch(pList, pKey, a, pLow, middle-1 );
} // end recBinarySearch()
/** iterative binary search for ArrayList<> */
public int search( ArrayList<Integer> list, int key, int from, int to ) {
int pos = 0;
boolean found = false;
while (from <= to && !found) {
pos = (from + to) / 2; // Midpoint of the subsequence
if ( list.get(pos) == key) { found = true; }
else if (list.get(pos) < key) { from = pos + 1; } // Look in upper half
else { to = pos - 1; } // Look in lower half
}
return found ? pos : -1;
}

// recursive quick sort algorithm O(n*lg(n)), but bad pivot choice can lead to
O(n^2) like insertion;
// also, w/c is input that's already ascending order
public void quickSort( ArrayList<Integer> pList, int pFromIdx, int pToIdx ) {
/** Base case is reached when the list has only one element - when pFromIdx is
* greater than or equal to pToIdx, at which point pList is trivially sorted, so return. */
if ( pFromIdx >= pToIdx ) return;
/** Otherwise, partition the list into left / right halves such that all left half elements
* are less than elements in the right half. */
int partitionIndex = partition( pList, pFromIdx, pToIdx );
/** now recursively sort the left and right halves */
quickSort(pList, pFromIdx, partitionIndex );
quickSort(pList, partitionIndex + 1, pToIdx);
} // end quickSort()
/** while ( leftIdx < rightIdx ):
*
move > leftIdx > until element greater than or equal to pivot is found
*
move < rightIdx < until element less than or equal to pivot is found
* then, if leftIdx < rightIdx, swap elements
* when leftIdx and rightIdx "cross", partition terminates, return rightIdx */
private int partition( ArrayList<Integer> pList, int pFromIdx, int pToIdx ) {
Integer pivot = pList.get(pFromIdx);
/** leftIdx and rightIdx move toward each other as partitioning proceeds.
* leftIndex starts at left end of sublist, rightIndex starts at right end. */
int leftIdx = pFromIdx - 1;
int rightIdx = pToIdx + 1;
// Partitioning ends when leftIdx and rightIdx "cross".
while ( leftIdx < rightIdx ) {
leftIdx++;
// move leftIdx >> until element greater than or equal to pivot is found
while ( pList.get( leftIdx ).compareTo( pivot ) < 0 ) leftIdx++;
rightIdx--;
// move rightIdx << until element less than or equal to pivot is found
while ( pList.get( rightIdx ).compareTo( pivot ) > 0 ) rightIdx--;
/** When while loops above terminate, if leftIdx / rightIdx have not
"crossed"
* leftIdx is index of element that belongs in right half of the partition and
* rightIdx is index of element that belongs in left half. So swap elements.
*/
if( leftIdx < rightIdx ) swap( pList, leftIdx, rightIdx );
}
/** When outer while loop terminates elements in list[fromIndex..rightIdx - 1] are all
* less than elements in list[rightIdx..toIndex]. Partitioned into left / right halves. */
return rightIdx; // used in the main quick sort method
} // end partition()

/** swap() helper method swaps Student objects at indicies pIdx1 & pIdx2 */
private void swap( ArrayList<Student> pList, int pIdx1, int pIdx2 ) {
Student tmp = pList.get( pIdx2 ); // save Student at pIdx2 to Student tmp
pList.set( pIdx2, pList.get( pIdx1 ) ); // set Student at pIdx2 to Student at
pIdx1
pList.set( pIdx1, tmp); // set Student at pIdx1 to Student tmp
} // end swap()
Method recursiveMergeSort(InOut: List<T> list)
If list.size = 1 Then Return // The base case is reached when list size is 1.
// Otherwise, split list into left / right halves, merge sort each
listL list[0 .. list.size / 2 - 1] // if size is odd, listL smaller
listR list[list.size / 2 .. list.size - 1]
recursiveMergeSort(listL); recursiveMergeSort(listR)
// on return from method calls above listL and listR will be sorted.
// now merge them to form a sorted list.
merge(listL, listR, list)
End Method recursiveMergeSort
Method merge(In: List<T> listL; In: List<T> listR; Out: List<T> list)
leftIndex 0; rightIndex 0; listIndex 0
While ( leftIndex < listL.size && rightIndex < listR.size )
If listL[leftIndex] listR[rightIndex] Then
list[listIndex] listL[leftIndex]
leftIndex leftIndex + 1
Else
list[listIndex] listR[rightIndex]
rightIndex rightIndex + 1
End If
listIndex listIndex + 1
End While
If leftIndex < listL.size Then
copyRest(listL, leftIndex, list, listIndex)
Else
copyRest(listR, rightIndex, list, listIndex)
End If;
End Method merge
/** primary recursive routine that merge sorts pList. */
public static void mergeSort(ArrayList<Integer> pList) {
if (pList.size() < 2) return; // base case is when size of pList is 1
// Otherwise, split the list into two halves: a left and a right half. Recursively
// merge sort each half.
ArrayList<Integer> listL = arrListCopy(pList, 0, pList.size() / 2);
ArrayList<Integer> listR = arrListCopy(pList, pList.size() / 2, pList.size());
mergeSort(listL); mergeSort(listR);
// On return from the two calls above both listL and listR will be sorted.
merge(listL, listR, pList); // Merge them to form a sorted list.
} // end method mergeSort()
private static void merge
// Merges pListL and pListR into pList
(ArrayList<Integer> pListL, ArrayList<Integer> pListR, ArrayList<Integer>
pList) {
int leftIdx = 0, rightIdx = 0, listIdx = 0;
while (leftIdx < pListL.size() && rightIdx < pListR.size()) {
if (pListL.get(leftIdx).compareTo(pListR.get(rightIdx)) <= 0) {
pList.set(listIdx, pListL.get(leftIdx));
++leftIdx;
}
else {
pList.set(listIdx, pListR.get(rightIdx));
++rightIdx;
}
++listIdx;
}
if (leftIdx < pListL.size()) copyRest(pListL, leftIdx, pList, listIdx);
else copyRest(pListR, rightIdx, pList, listIdx);
} // end merge()

When sublist.size() = 1, a(1) = 0 (base case), so 1 = n/2 k, so k = lgn; a(n) = 5nlgn


+ 2lgna(n/2lgn); a(n) = 5nlgn or O(n*lg(n)) avg and w/c performance.
QuickSort time complexity dominated by partitioning; avg. O(n*lg(n)), w/c is O(n 2)
(occurs if list already sorted with pivot at first/last position.
DList complexity add(), get(), remove(), getNodeAt() at head and tail is O(1);
on an interior element (random access) is O(n). Iterating over the elements in
sequence is O(1); good data structure for dynamic data, where elements are
primarily accessed at beginning and ends of list, a/o elements are accessed in a
linear sequence. Get() & getNodeAt() iterations max @ mSize 1

An interface type is similar to a class, but there are several important differences:
(1) methods in an interface type are abstract (ie dont have an implementation);
(2) methods in an interface type are automatically public; (3) interface type
cannot have instance variables or static methods.
Abstract class - declared with abstract keyword. Abstract classes may not be
instantiated, and exist to support inheritance of instance variables / methods by
subclasses. Methods declared in abstract classes are headers (no code block or
method body). Logic is implemented in subclasses of an abstract class. A class
must be declared abstract if any methods in that class are abstract.
A concrete class is a subclass that extends an abstract class and implements all
abstract methods. Subclasses must override methods that are declared abstract
in the superclass.
Inner class - Non-static nested class. An inner class has access to outer class
variables and methods (even those declared private) and may refer to them
directly in the same way that other non-static members of the outer class do, but
the reverse mechanism is not valid. Members of the inner class are known only
within the scope of the inner class and may not be used by the outer class.
Local class - declared inside a code block (for loop, or an if clause) or method
body. Local classes are similar to inner classes - neither can define or declare any
static members. Like an inner class, a local class has access to the members of its
enclosing scope. However, the local class only has access to local variables within
the enclosing class that are declared final or that are effectively final.
Anonymous inner class - no name to reference, initialized once at the point of
need. Unlike local classes and inner classes, anonymous inner classes are
nameless, may only be instantiated once, and do not have constructors. Like local
classes, they are usually declared inside a method or a code block, but the
anonymous class is accessible only at the point of definition. Also like local
classes, anonymous classes may not be declared static.
Polymorphism - When invoking an instance method from a reference variable, the
actual type of the variable determines which implementation of the method is
used at runtime (dynamic binding). It is always possible to cast an instance of a
subclass to a variable of a superclass, because an instance of a subclass is always

/** returns ArrayList from pList @ indices pFromIndex (inclusive) to pToIndex


(exclusive) */
private static ArrayList<Integer>
arrListCopy(ArrayList<Integer> pList, int pFromIdx, int pToIdx) {
ArrayList<Integer> pCopy = new ArrayList<>();
for (int i = pFromIdx; i < pToIdx; ++i)
pCopy.add(pList.get(i));
return pCopy;
}
/** Copies elements from pSrcList[pSrcIndex .. pSrcList.size - 1] to pDstList
* starting at index pDstIndex. */
private static void copyRest(ArrayList<Integer> pSrcList, int pSrcIdx,
ArrayList<Integer> pDstList, int pDstIdx) {
while (pSrcIdx < pSrcList.size()) {
pDstList.set(pDstIdx, pSrcList.get(pSrcIdx));
++pSrcIdx; ++pDstIdx;
}
}
Recursive solution: (1) problem size must be reducible to a smaller, equivalent
sub, simpler to solve than larger problem; (2) original problem requires
repetition; (3) base case; (4) solution to base case is straightforward; (5) solution
to smaller sub must be returned and used in solving larger problem; (6) solution
to the original problem results from solving all of the subproblems.
Algorithm complexity: (1), lg(n), n, n*lg(n), n2, n3, 2n
Selection & insertion sorts: O(n2)
insertion sort c(n) = outer loop(n) + swap(n) + = (n 2)/2 + n/2 -1 = O(n2)
selection sort c(n) = outer loop(n) + inner loop(n) = same
MergeSort time complexity
merge(): assume listL and listR size n/2. While loops n/2 times, 3 list accesses
per pass.
a(n) = 3(n/2). copyRest(): n/2 loops, 2 accesses each. a(n) = 2(n/2). So merge()
a(n) = 2.5n ~ 3n.
recursiveMergeSort() sublist splits: 2 lists, size n/2, each accessed once to form
sublists. So a(n) ~ 3n + 2n. Now include accesses by 2 recursiveMergeSort()
(each n/2 list size), a(n) = 5n + a(n/2) + a(n/2) = 5n + 2a(n/2) = 5nk + 2 ka(n/2k).

an instance of its superclass. When casting an instance of a superclass to a


variable of its subclass, explicit casting must be used with the (SubName)
notation.
Descendants of (8): nodes 5, 6, 2, 9
Ancestors of (1): are on path connecting the node to root node; nodes: 3, 7
Leaf nodes - w/ no child nodes: 5, 9, 1, 4
Internal nodes. Nodes that are not leaves are internal: 2, 3, 6, 7, 8
Levels of nodes 3, 1, and 9? L2, L3, L4
Height of the tree? Height of a tree is the maximum of the levels of each
subtree, so 4.
Height of the subtree rooted at 6? 2
Full binary tree? No. A full binary tree: each node is either a leaf or has 2
children. Nodes 4 and 5 have one child node, so this condition violates the
either 0 or 2 rule. It can't be converted to a full binary tree. Original has 9
nodes; full 2 or 3 level trees would have 7 or 15 nodes.
Complete binary tree? No. A binary tree of height h is complete if all levels are
full, with exception of the last level, which may have single nodes if they're on the
left branch.
Level order traversal: 7, 8, 3, 5, 6, 1, 4, 2, 9
Inorder traversal: left sub, then root, then right sub: 5, 8, 9, 2, 6, 7, 1, 3, 4
Preorder traversal: root, then left sub, then right sub: 7, 8, 5, 6, 2, 9, 3, 1, 4
Postorder traversal: left sub, right sub, root: 5, 9, 2, 6, 8, 1, 4, 3, 7

}
/** method getSize() includes inner class Counter */
public int getSize() {
class Counter implements BinaryTreeVisit<E> {
private int mCount;
public Counter() { } /** Counter ctor */
/** Counter methods */
public int getCount() { return mCount; }
public void visit( E pData ) { mCount++; }
}
Counter counter = new Counter();
traverse(LEVEL_ORDER, counter);
return counter.getCount();
} // end getSize()

Preorder:
1. Visit the root node
2. preorder of subtree rooted at left
child
3. preorder of subtree rooted at right
child
Postorder:
1. postorder of subtree rooted at left
child
2. postorder of subtree rooted at right
child
3. Visit the root node
Inorder:
Breadth
First
Traversal
1. inorder
of subtree
rooted at left
levelOrderTraversal(In:
Node pRoot, In:
child
pVisitor)
// Create a queue of Nodes named nodeQ
// Add pRoot to queue - the first Node
visited
nodeQ.enqueue(pRoot)
// loop while there are still more Nodes to
visit
While nodeQ is not empty Do
// visit the next Node from front of
queue
root nodeQ.dequeue()
pVisitor.visit(root.data)
// If it exists, add the left child to nodeQ
nodeQ.enqueue(root.leftChild)
// If it exists, add the right child to
BinaryTree<Integer> tree = new BinaryTree<>(1);
BinaryTree.Iterator<Integer> it = tree.iterator();

/** Removes all Nodes in this BinaryTree.*/


public void clear() {
prune(getRoot());
setRoot(null);
}
/** Searches the tree rooted at pRoot for a node containing pData. Returns a
reference
* to the node or null if pData is not contained within the tree. */
protected Node<E> findNode(Node<E> pRoot, E pData) {
if (pRoot == null) return null;
if (pRoot.getData().equals(pData)) return pRoot;
Node<E> node = findNode(pRoot.getLeft(), pData);
if (node != null) return node;
return findNode(pRoot.getRight(), pData);
}
/** Returns the height of this BinaryTree. */
public int getHeight() { return getHeight(getRoot()); }
/** Returns the height of the subtree rooted at pRoot; height is the maximum
* of the heights of the left and right subtrees of pRoot. */
protected int getHeight(Node<E> pRoot) {
int heightLeft = 0, heightRight = 0;
if (pRoot == null) return 0;
if (pRoot.hasLeft()) heightLeft = getHeight(pRoot.getLeft()) + 1;
if (pRoot.hasRight()) heightRight = getHeight(pRoot.getRight()) + 1;
return Math.max(heightLeft, heightRight);
}
/** Accessor method for mRoot returns Node mRoot reference */
protected Node<E> getRoot() { return mRoot; }
/** Returns true if this BinaryTree is an empty tree. */
public boolean isEmpty() { return getRoot() == null; }
/** Returns true if this BinaryTree is full. */
protected boolean isFull() { return isFull(getRoot()); }
/** Returns true if the subtree rooted at pRoot is a full binary tree. */
protected boolean isFull(Node<E> pRoot) {
if (pRoot.isLeaf()) return true;
boolean leftFull = pRoot.hasLeft() ? isFull(pRoot.getLeft()) : false;
boolean rightFull = pRoot.hasRight() ? isFull(pRoot.getRight()) : false;
return leftFull && rightFull;
}
/** Creates a new Iterator over this BinaryTree. The current node of the
returned
* Iterator will be the root node of this BinaryTree. */
public Iterator<E> iterator() { return new Iterator<>(this); }

BinaryTree<Integer> tree0 = new BinaryTree <>();


BinaryTree <Integer> tree1 = new BinaryTree <>(1);
BinaryTree <Integer> tree2 = new BinaryTree <>(2);
BinaryTree <Integer> tree3 = new BinaryTree <>(3, tree1, tree2);
tree3.traverse(BinaryTree.LEVEL_ORDER, this);
/** BinaryTree.java implements a generic binary tree data structure */
public class BinaryTree<E> {
public static final int INORDER = 0; public static final int LEVEL_ORDER = 1;
public static final int POSTORDER = 2; public static final int PREORDER = 3;
/** A BinaryTree consists of a Node which is the root of the tree. Node objects
* contain references to the left and right child nodes of mRoot. */
private Node<E> mRoot;
/** Create a new empty BinaryTree storing no data. */
public BinaryTree() { this(null); }
/** New BinaryTree with root storing pData. Left and right subtrees set to
null. */
public BinaryTree(E pData) { this(pData, null, null); }
/** New BinaryTree with the root storing pData. pLeft will be the left subtree
of the root of
this tree unless pLeft is null; pRight is handled in a similar
manner. */
public BinaryTree(E pData, BinaryTree<E> pLeft, BinaryTree<E> pRight) {
Node<E> leftChild = pLeft == null ? null : pLeft.getRoot();
Node<E> rightChild = pRight == null ? null : pRight.getRoot();
setRoot(new Node<E>( pData, leftChild, rightChild, null ));
if (leftChild != null) leftChild.setParent(getRoot());
if (rightChild != null) rightChild.setParent(getRoot());

/**
* Prunes the left and right subtrees rooted at pTree by setting left / right
references of root
* node to null. Note: this method does not delete data
stored in root node of pTree, nor does
* it set root node of pTree to null. */
protected void prune(Node<E> pRoot) {
if (pRoot == null) return;
prune(pRoot.getLeft());
pRoot.setLeft(null);
prune(pRoot.getRight());
pRoot.setRight(null);
}
/** Prunes only the left subtree of this BinaryTree. */
protected void pruneLeft(Node<E> pRoot) {
prune(pRoot.getLeft());
pRoot.setLeft(null);
}
/** Prunes only the right subtree of this BinaryTree. */
protected void pruneRight(Node<E> pRoot) {
prune(pRoot.getRight());
pRoot.setRight(null);
}
/** Mutator method sets mRoot reference to point to pRoot */
protected void setRoot(Node<E> pRoot) { mRoot = pRoot; }
/**
* Performs a traversal specified by pVer (one of the constants INORDER,
* LEVEL_ORDER, POSTORDER, or PREORDER) on this BinaryTree. pVisit
* implements the BinaryTreeVisit interface. As each Node is visited during
* traversal the visit(E data) method will be called on pVisit.
*/
public void traverse(int pVer, BinaryTreeVisit<E> pVisit) {
if (pVer == LEVEL_ORDER) traverseLevelOrder(getRoot(), pVisit);
traverse(pVer, getRoot(), pVisit);
}

/** See traverse(int, BinaryTreeVisit). */


protected void traverse(int pVer, Node<E> pRoot, BinaryTreeVisit<E> pVisit)

/** A reference to the BinaryTree over which this Iterator iterates. */


private BinaryTree<E> mTree;

{
if (pRoot == null) return;
switch (pVer) {
case INORDER:
traverse(pVer, pRoot.getLeft(), pVisit);
pVisit.visit(pRoot.getData());
traverse(pVer, pRoot.getRight(), pVisit); break;
case POSTORDER:
traverse(pVer, pRoot.getLeft(), pVisit);
traverse(pVer, pRoot.getRight(), pVisit);
pVisit.visit(pRoot.getData()); break;
case PREORDER:
pVisit.visit(pRoot.getData());
traverse(pVer, pRoot.getLeft(), pVisit);
traverse(pVer, pRoot.getRight(), pVisit); break;
}

/** Create an Iterator to iterate over the BinaryTree pTree. */


public Iterator(BinaryTree<E> pTree) {
setTree(pTree);
setCurrent(getTree().getRoot());
}
/** new Node containing pData to be left child of current Node. */
public void addLeft(E pData) throws EmptyTreeException {
if (getTree().isEmpty()) throw new EmptyTreeException();
pruneLeft();
getCurrent().setLeft(new Node<E>(pData, getCurrent() ));
}

/** new Node containing pData to be right child of current Node. */


public void addRight(E pData) throws EmptyTreeException {
if (getTree().isEmpty()) throw new EmptyTreeException();
pruneRight();
getCurrent().setRight(new Node<E>(pData, getCurrent() ));
}

/** Make a level order traversal of pTree. */


protected void traverseLevelOrder(Node<E> pRoot, BinaryTreeVisit<E>
pVisit) {
Queue<Node<E>> nodeQueue = new Queue<Node<E>>();
nodeQueue.enqueue(pRoot);
while (!nodeQueue.isEmpty()) {
Node<E> root = nodeQueue.dequeue();
pVisit.visit(root.getData());
if (root.hasLeft()) nodeQueue.enqueue(root.getLeft());
if (root.hasRight()) nodeQueue.enqueue(root.getRight());
}
}

/** Searches tree rooted at current node for pData. If found, current
* Node is changed to Node containing pData, return true. If not
* found, current node will not be changed, returns false */
public boolean find(E pData) {
Node<E> node = getTree().findNode(getCurrent(), pData);
if (node != null) setCurrent(node);
return node != null;
}

protected static class Node<E> { /** Static Nested Class: Node */


E mData;
Node<E>
Node<E>
Node<E>

// data stored in this Node


mLeft; // reference to left child of this Node
mRight; // reference to right child of this Node
mParent; // reference to parent of this Node

/** Returns the data stored in the current Node. */


public E get() { return (E)mCurrent.getData(); }
/** Protected accessor method for mCurrent. */
protected Node<E> getCurrent() { return mCurrent; }

/** Creates a new Node storing no data, mLeft and mRight set to null. */
public Node() { this(null, null); }
/** Creates a new Node storing pData, mLeft and mRight set to null. */
public Node(E pData, Node<E>pParent) { this(pData, null, null, pParent);

/** Protected accessor method for mStack. */


protected Stack<Node<E>> getStack() { return mStack; }

/**Creates a new Node storing pData, mLeft initialized to pLeft, and

/** Protected accessor method for mTree. */


protected BinaryTree<E> getTree() { return mTree; }

}
mRight
* initialized to pRight. */
public Node(E pData, Node<E> pLeft, Node<E> pRight, Node<E>pParent)

/** Returns the height of the subtree rooted at the current Node. */
public int getHeight() { return getTree().getHeight(getCurrent()); }

{
setData(pData);
setLeft(pLeft);
setRight(pRight);
setParent(pParent);

/** Return true if subtree rooted at current Node is full binary tree. */
public boolean isFull() { return getTree().isFull(getCurrent()); }

}
/** Accessor methods for mData / mLeft / mRight / mParent */
public E getData() { return mData; }
public Node<E> getLeft() { return mLeft; }
public Node<E> getRight() { return mRight; }
public Node<E> getParent() { return mParent; }
/** Mutator methods for mData / mLeft / mRight / mParent */
public void setData(E pData) { mData = pData; }
public void setLeft(Node<E> pLeft) { mLeft = pLeft; }
public void setRight(Node<E> pRight) { mRight = pRight; }
public void setParent(Node<E> pParent) { mParent = pParent; }
/** Returns the number of children of this Node. */
public int getNumChildren() {
int num = 0;
if (hasLeft()) ++num;
if (hasRight()) ++ num;
return num;
}
/** Returns true if this Node has a left child Node. */
public boolean hasLeft() { return getLeft() != null; }
/** Returns true if this Node has a right child Node. */
public boolean hasRight() { return getRight() != null; }
/** Returns true if this Node is a leaf node. */
public boolean isLeaf() { return !hasLeft() && !hasRight(); }
@Override public String toString() { return "" + getData(); }
} // end class Node
public static class Iterator<E> {
/** reference to the current Node of the Iterator. */
Node<E> mCurrent;
/** stack stores references to parent Nodes. As Iterator moves left and
right
* downward, parent Nodes are pushed on stack. When moveUp() is called

/** Moves this Iterator to the left child of the current Node. */
public void moveLeft() {
if (getCurrent().hasLeft()) { setCurrent(getCurrent().getLeft());
}
}
/** Moves this Iterator to the right child of the current Node. */
public void moveRight() {
if (getCurrent().hasRight()) { setCurrent(getCurrent().getRight());
}

/** Moves this Iterator to the root Node of the tree. */


public void moveToRoot() { setCurrent(getTree().getRoot()); }
/** Moves iterator up to the parent Node of the current Node. */
public void moveUp() {
if (getCurrent().getParent() != null) {
setCurrent(getCurrent().getParent());
}
}
/** Prunes left and right subtrees of the current Node. */
public void prune() { pruneLeft(); pruneRight(); }
/** Prunes the left subtree of the current Node. */
public void pruneLeft() { getTree().pruneLeft(getCurrent()); }
/** Prunes the right subtree of the current Node. */
public void pruneRight() { getTree().pruneRight(getCurrent()); }
/** Changes the data stored in the current Node. */
public void set(E pData) { getCurrent().setData(pData); }
/** Protected mutator method for mCurrent. */
protected void setCurrent(Node<E> pCurrent) { mCurrent = pCurrent; }
/** Protected mutator method for mTree. */
protected void setTree(BinaryTree<E> pTree) {mTree = pTree; }

parent
* of current Node will be on top of stack. Note: when moveToRoot() is
called the
* stack must be emptied. */
Stack<Node<E>> mStack;

/** Protected mutator method for mStack. */


protected void setStack(Stack<Node<E>> pStack) { mStack = pStack; }
/** Performs traversal specified by pVer. pVisit implements
BinaryTreeVisit interface. As
each Node is visited during traversal

the visit(E data) method will be called on pVisit. */


public void traverse(int pVer, <E> pVisit) {
getTree().traverse(pVer, getCurrent(), pVisit);
} // end traverse()
} // end static class Iterator
} // end class BinaryTree

/** CLASS: BinaryTreeVisitor.java */


public interface BinaryTreeVisit<E> { void visit(E pData); }

Das könnte Ihnen auch gefallen