C-8.45 page 353 (each algorithm is 30 points and running time is 10 points) Add
ID: 3690014 • Letter: C
Question
C-8.45 page 353 (each algorithm is 30 points and running time is 10 points)
Add the running time as a comment inside your algorithms implementation.
Using the algorithms provided in the attached file, implement and test the following problem:
(Problem C-8.45, page 353 of the text)
• preorderNext(p): Return the position visited after p in a preorder traversal
of T (or null if p is the last node visited).
• inorderNext(p): Return the position visited after p in an inorder traversal
of T (or null if p is the last node visited).
• postorderNext(p): Return the position visited after p in a postorder traversal
of T (or null if p is the last node visited).
What are the worst-case running times of your algorithms?
Tree.java
/*
* Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser
*
* Developed for use with the book:
*
* Data Structures and Algorithms in Java, Sixth Edition
* Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
* John Wiley & Sons, 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//package net.datastructures;
import java.util.Iterator;
/**
* An interface for a tree where nodes can have an arbitrary number of children.
*
* @author Michael T. Goodrich
* @author Roberto Tamassia
* @author Michael H. Goldwasser
*/
public interface Tree<E> extends Iterable<E> {
/**
* Returns the root Position of the tree (or null if tree is empty).
* @return root Position of the tree (or null if tree is empty)
*/
Position<E> root();
/**
* Returns the Position of p's parent (or null if p is root).
*
* @param p A valid Position within the tree
* @return Position of p's parent (or null if p is root)
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
Position<E> parent(Position<E> p) throws IllegalArgumentException;
/**
* Returns an iterable collection of the Positions representing p's children.
*
* @param p A valid Position within the tree
* @return iterable collection of the Positions of p's children
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
Iterable<Position<E>> children(Position<E> p)
throws IllegalArgumentException;
/**
* Returns the number of children of Position p.
*
* @param p A valid Position within the tree
* @return number of children of Position p
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
int numChildren(Position<E> p) throws IllegalArgumentException;
/**
* Returns true if Position p has one or more children.
*
* @param p A valid Position within the tree
* @return true if p has at least one child, false otherwise
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
boolean isInternal(Position<E> p) throws IllegalArgumentException;
/**
* Returns true if Position p does not have any children.
*
* @param p A valid Position within the tree
* @return true if p has zero children, false otherwise
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
boolean isExternal(Position<E> p) throws IllegalArgumentException;
/**
* Returns true if Position p represents the root of the tree.
*
* @param p A valid Position within the tree
* @return true if p is the root of the tree, false otherwise
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
boolean isRoot(Position<E> p) throws IllegalArgumentException;
/**
* Returns the number of nodes in the tree.
* @return number of nodes in the tree
*/
int size();
/**
* Tests whether the tree is empty.
* @return true if the tree is empty, false otherwise
*/
boolean isEmpty();
/**
* Returns an iterator of the elements stored in the tree.
* @return iterator of the tree's elements
*/
Iterator<E> iterator();
/**
* Returns an iterable collection of the positions of the tree.
* @return iterable collection of the tree's positions
*/
Iterable<Position<E>> positions();
}
Position.java
/*
* Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser
*
* Developed for use with the book:
*
* Data Structures and Algorithms in Java, Sixth Edition
* Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
* John Wiley & Sons, 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//package net.datastructures;
/**
* An interface for a position which is an abstraction for the
* location at which a single element is stored in a positional
* container.
*
* @author Michael T. Goodrich
* @author Roberto Tamassia
* @author Michael H. Goldwasser
*/
public interface Position<E> {
/**
* Returns the element stored at this position.
*
* @return the stored element
* @throws IllegalStateException if position no longer valid
*/
E getElement() throws IllegalStateException;
}
LinkedBinaryTree.java
/*
* Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser
*
* Developed for use with the book:
*
* Data Structures and Algorithms in Java, Sixth Edition
* Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
* John Wiley & Sons, 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//package net.datastructures;
/**
* Concrete implementation of a binary tree using a node-based, linked structure.
*
* @author Michael T. Goodrich
* @author Roberto Tamassia
* @author Michael H. Goldwasser
*/
public class LinkedBinaryTree<E> extends AbstractBinaryTree<E> {
//---------------- nested Node class ----------------
/** Nested static class for a binary tree node. */
protected static class Node<E> implements Position<E> {
private E element; // an element stored at this node
private Node<E> parent; // a reference to the parent node (if any)
private Node<E> left; // a reference to the left child (if any)
private Node<E> right; // a reference to the right child (if any)
/**
* Constructs a node with the given element and neighbors.
*
* @param e the element to be stored
* @param above reference to a parent node
* @param leftChild reference to a left child node
* @param rightChild reference to a right child node
*/
public Node(E e, Node<E> above, Node<E> leftChild, Node<E> rightChild) {
element = e;
parent = above;
left = leftChild;
right = rightChild;
}
// accessor methods
public E getElement() { return element; }
public Node<E> getParent() { return parent; }
public Node<E> getLeft() { return left; }
public Node<E> getRight() { return right; }
// update methods
public void setElement(E e) { element = e; }
public void setParent(Node<E> parentNode) { parent = parentNode; }
public void setLeft(Node<E> leftChild) { left = leftChild; }
public void setRight(Node<E> rightChild) { right = rightChild; }
} //----------- end of nested Node class -----------
/** Factory function to create a new node storing element e. */
protected Node<E> createNode(E e, Node<E> parent,
Node<E> left, Node<E> right) {
return new Node<E>(e, parent, left, right);
}
// LinkedBinaryTree instance variables
/** The root of the binary tree */
protected Node<E> root = null; // root of the tree
/** The number of nodes in the binary tree */
private int size = 0; // number of nodes in the tree
// constructor
/** Construts an empty binary tree. */
public LinkedBinaryTree() { } // constructs an empty binary tree
// nonpublic utility
/**
* Verifies that a Position belongs to the appropriate class, and is
* not one that has been previously removed. Note that our current
* implementation does not actually verify that the position belongs
* to this particular list instance.
*
* @param p a Position (that should belong to this tree)
* @return the underlying Node instance for the position
* @throws IllegalArgumentException if an invalid position is detected
*/
protected Node<E> validate(Position<E> p) throws IllegalArgumentException {
if (!(p instanceof Node))
throw new IllegalArgumentException("Not valid position type");
Node<E> node = (Node<E>) p; // safe cast
if (node.getParent() == node) // our convention for defunct node
throw new IllegalArgumentException("p is no longer in the tree");
return node;
}
// accessor methods (not already implemented in AbstractBinaryTree)
/**
* Returns the number of nodes in the tree.
* @return number of nodes in the tree
*/
@Override
public int size() {
return size;
}
/**
* Returns the root Position of the tree (or null if tree is empty).
* @return root Position of the tree (or null if tree is empty)
*/
@Override
public Position<E> root() {
return root;
}
/**
* Returns the Position of p's parent (or null if p is root).
*
* @param p A valid Position within the tree
* @return Position of p's parent (or null if p is root)
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public Position<E> parent(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getParent();
}
/**
* Returns the Position of p's left child (or null if no child exists).
*
* @param p A valid Position within the tree
* @return the Position of the left child (or null if no child exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
@Override
public Position<E> left(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getLeft();
}
/**
* Returns the Position of p's right child (or null if no child exists).
*
* @param p A valid Position within the tree
* @return the Position of the right child (or null if no child exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
@Override
public Position<E> right(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getRight();
}
// update methods supported by this class
/**
* Places element e at the root of an empty tree and returns its new Position.
*
* @param e the new element
* @return the Position of the new element
* @throws IllegalStateException if the tree is not empty
*/
public Position<E> addRoot(E e) throws IllegalStateException {
if (!isEmpty()) throw new IllegalStateException("Tree is not empty");
root = createNode(e, null, null, null);
size = 1;
return root;
}
/**
* Creates a new left child of Position p storing element e and returns its Position.
*
* @param p the Position to the left of which the new element is inserted
* @param e the new element
* @return the Position of the new element
* @throws IllegalArgumentException if p is not a valid Position for this tree
* @throws IllegalArgumentException if p already has a left child
*/
public Position<E> addLeft(Position<E> p, E e)
throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getLeft() != null)
throw new IllegalArgumentException("p already has a left child");
Node<E> child = createNode(e, parent, null, null);
parent.setLeft(child);
size++;
return child;
}
/**
* Creates a new right child of Position p storing element e and returns its Position.
*
* @param p the Position to the right of which the new element is inserted
* @param e the new element
* @return the Position of the new element
* @throws IllegalArgumentException if p is not a valid Position for this tree.
* @throws IllegalArgumentException if p already has a right child
*/
public Position<E> addRight(Position<E> p, E e)
throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getRight() != null)
throw new IllegalArgumentException("p already has a right child");
Node<E> child = createNode(e, parent, null, null);
parent.setRight(child);
size++;
return child;
}
/**
* Replaces the element at Position p with element e and returns the replaced element.
*
* @param p the relevant Position
* @param e the new element
* @return the replaced element
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
public E set(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E temp = node.getElement();
node.setElement(e);
return temp;
}
/**
* Attaches trees t1 and t2, respectively, as the left and right subtree of the
* leaf Position p. As a side effect, t1 and t2 are set to empty trees.
*
* @param p a leaf of the tree
* @param t1 an independent tree whose structure becomes the left child of p
* @param t2 an independent tree whose structure becomes the right child of p
* @throws IllegalArgumentException if p is not a valid Position for this tree
* @throws IllegalArgumentException if p is not a leaf
*/
public void attach(Position<E> p, LinkedBinaryTree<E> t1,
LinkedBinaryTree<E> t2) throws IllegalArgumentException {
Node<E> node = validate(p);
if (isInternal(p)) throw new IllegalArgumentException("p must be a leaf");
size += t1.size() + t2.size();
if (!t1.isEmpty()) { // attach t1 as left subtree of node
t1.root.setParent(node);
node.setLeft(t1.root);
t1.root = null;
t1.size = 0;
}
if (!t2.isEmpty()) { // attach t2 as right subtree of node
t2.root.setParent(node);
node.setRight(t2.root);
t2.root = null;
t2.size = 0;
}
}
/**
* Removes the node at Position p and replaces it with its child, if any.
*
* @param p the relevant Position
* @return element that was removed
* @throws IllegalArgumentException if p is not a valid Position for this tree.
* @throws IllegalArgumentException if p has two children.
*/
public E remove(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
if (numChildren(p) == 2)
throw new IllegalArgumentException("p has two children");
Node<E> child = (node.getLeft() != null ? node.getLeft() : node.getRight() );
if (child != null)
child.setParent(node.getParent()); // child's grandparent becomes its parent
if (node == root)
root = child; // child becomes root
else {
Node<E> parent = node.getParent();
if (node == parent.getLeft())
parent.setLeft(child);
else
parent.setRight(child);
}
size--;
E temp = node.getElement();
node.setElement(null); // help garbage collection
node.setLeft(null);
node.setRight(null);
node.setParent(node); // our convention for defunct node
return temp;
}
} //----------- end of LinkedBinaryTree class -----------
BinaryTree.java
/*
* Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser
*
* Developed for use with the book:
*
* Data Structures and Algorithms in Java, Sixth Edition
* Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
* John Wiley & Sons, 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//package net.datastructures;
/**
* An interface for a binary tree, in which each node has at most two children.
*
* @author Michael T. Goodrich
* @author Roberto Tamassia
* @author Michael H. Goldwasser
*/
public interface BinaryTree<E> extends Tree<E> {
/**
* Returns the Position of p's left child (or null if no child exists).
*
* @param p A valid Position within the tree
* @return the Position of the left child (or null if no child exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
Position<E> left(Position<E> p) throws IllegalArgumentException;
/**
* Returns the Position of p's right child (or null if no child exists).
*
* @param p A valid Position within the tree
* @return the Position of the right child (or null if no child exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
Position<E> right(Position<E> p) throws IllegalArgumentException;
/**
* Returns the Position of p's sibling (or null if no sibling exists).
*
* @param p A valid Position within the tree
* @return the Position of the sibling (or null if no sibling exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
Position<E> sibling(Position<E> p) throws IllegalArgumentException;
}
AbstractTree.java
/*
* Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser
*
* Developed for use with the book:
*
* Data Structures and Algorithms in Java, Sixth Edition
* Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
* John Wiley & Sons, 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//package net.datastructures;
import java.util.Iterator;
import java.util.List; // for use as snapshot iterator
import java.util.ArrayList; // for use as snapshot iterator
/**
* An abstract base class providing some functionality of the Tree interface.
*
* The following three methods remain abstract, and must be
* implemented by a concrete subclass: root, parent, children. Other
* methods implemented in this class may be overridden to provide a
* more direct and efficient implementation.
*
* @author Michael T. Goodrich
* @author Roberto Tamassia
* @author Michael H. Goldwasser
*/
public abstract class AbstractTree<E> implements Tree<E> {
/**
* Returns true if Position p has one or more children.
*
* @param p A valid Position within the tree
* @return true if p has at least one child, false otherwise
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public boolean isInternal(Position<E> p) { return numChildren(p) > 0; }
/**
* Returns true if Position p does not have any children.
*
* @param p A valid Position within the tree
* @return true if p has zero children, false otherwise
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public boolean isExternal(Position<E> p) { return numChildren(p) == 0; }
/**
* Returns true if Position p represents the root of the tree.
*
* @param p A valid Position within the tree
* @return true if p is the root of the tree, false otherwise
*/
@Override
public boolean isRoot(Position<E> p) { return p == root(); }
/**
* Returns the number of children of Position p.
*
* @param p A valid Position within the tree
* @return number of children of Position p
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public int numChildren(Position<E> p) {
int count=0;
for (Position child : children(p)) count++;
return count;
}
/**
* Returns the number of nodes in the tree.
* @return number of nodes in the tree
*/
@Override
public int size() {
int count=0;
for (Position p : positions()) count++;
return count;
}
/**
* Tests whether the tree is empty.
* @return true if the tree is empty, false otherwise
*/
@Override
public boolean isEmpty() { return size() == 0; }
//---------- support for computing depth of nodes and height of (sub)trees ----------
/** Returns the number of levels separating Position p from the root.
*
* @param p A valid Position within the tree
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
public int depth(Position<E> p) throws IllegalArgumentException {
if (isRoot(p))
return 0;
else
return 1 + depth(parent(p));
}
/** Returns the height of the tree.
*
* Note: This implementation works, but runs in O(n^2) worst-case time.
*/
private int heightBad() { // works, but quadratic worst-case time
int h = 0;
for (Position<E> p : positions())
if (isExternal(p)) // only consider leaf positions
h = Math.max(h, depth(p));
return h;
}
/**
* Returns the height of the subtree rooted at Position p.
*
* @param p A valid Position within the tree
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
public int height(Position<E> p) throws IllegalArgumentException {
int h = 0; // base case if p is external
for (Position<E> c : children(p))
h = Math.max(h, 1 + height(c));
return h;
}
//---------- support for various iterations of a tree ----------
//---------------- nested ElementIterator class ----------------
/* This class adapts the iteration produced by positions() to return elements. */
private class ElementIterator implements Iterator<E> {
Iterator<Position<E>> posIterator = positions().iterator();
public boolean hasNext() { return posIterator.hasNext(); }
public E next() { return posIterator.next().getElement(); } // return element!
public void remove() { posIterator.remove(); }
}
/**
* Returns an iterator of the elements stored in the tree.
* @return iterator of the tree's elements
*/
@Override
public Iterator<E> iterator() { return new ElementIterator(); }
/**
* Returns an iterable collection of the positions of the tree.
* @return iterable collection of the tree's positions
*/
@Override
public Iterable<Position<E>> positions() { return preorder(); }
/**
* Adds positions of the subtree rooted at Position p to the given
* snapshot using a preorder traversal
* @param p Position serving as the root of a subtree
* @param snapshot a list to which results are appended
*/
private void preorderSubtree(Position<E> p, List<Position<E>> snapshot) {
snapshot.add(p); // for preorder, we add position p before exploring subtrees
for (Position<E> c : children(p))
preorderSubtree(c, snapshot);
}
/**
* Returns an iterable collection of positions of the tree, reported in preorder.
* @return iterable collection of the tree's positions in preorder
*/
public Iterable<Position<E>> preorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
preorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/**
* Adds positions of the subtree rooted at Position p to the given
* snapshot using a postorder traversal
* @param p Position serving as the root of a subtree
* @param snapshot a list to which results are appended
*/
private void postorderSubtree(Position<E> p, List<Position<E>> snapshot) {
for (Position<E> c : children(p))
postorderSubtree(c, snapshot);
snapshot.add(p); // for postorder, we add position p after exploring subtrees
}
/**
* Returns an iterable collection of positions of the tree, reported in postorder.
* @return iterable collection of the tree's positions in postorder
*/
public Iterable<Position<E>> postorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
postorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/**
* Returns an iterable collection of positions of the tree in breadth-first order.
* @return iterable collection of the tree's positions in breadth-first order
*/
public Iterable<Position<E>> breadthfirst() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty()) {
Queue<Position<E>> fringe = new LinkedQueue<>();
fringe.enqueue(root()); // start with the root
while (!fringe.isEmpty()) {
Position<E> p = fringe.dequeue(); // remove from front of the queue
snapshot.add(p); // report this position
for (Position<E> c : children(p))
fringe.enqueue(c); // add children to back of queue
}
}
return snapshot;
}
}
AbstractBinaryTree.java
/*
* Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser
*
* Developed for use with the book:
*
* Data Structures and Algorithms in Java, Sixth Edition
* Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
* John Wiley & Sons, 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//package net.datastructures;
import java.util.List;
import java.util.ArrayList;
/**
* An abstract base class providing some functionality of the BinaryTree interface.
*
* The following five methods remain abstract, and must be implemented
* by a concrete subclass: size, root, parent, left, right.
*
* @author Michael T. Goodrich
* @author Roberto Tamassia
* @author Michael H. Goldwasser
*/
public abstract class AbstractBinaryTree<E> extends AbstractTree<E>
implements BinaryTree<E> {
/**
* Returns the Position of p's sibling (or null if no sibling exists).
*
* @param p A valid Position within the tree
* @return the Position of the sibling (or null if no sibling exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
@Override
public Position<E> sibling(Position<E> p) {
Position<E> parent = parent(p);
if (parent == null) return null; // p must be the root
if (p == left(parent)) // p is a left child
return right(parent); // (right child might be null)
else // p is a right child
return left(parent); // (left child might be null)
}
/**
* Returns the number of children of Position p.
*
* @param p A valid Position within the tree
* @return number of children of Position p
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public int numChildren(Position<E> p) {
int count=0;
if (left(p) != null)
count++;
if (right(p) != null)
count++;
return count;
}
/**
* Returns an iterable collection of the Positions representing p's children.
*
* @param p A valid Position within the tree
* @return iterable collection of the Positions of p's children
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public Iterable<Position<E>> children(Position<E> p) {
List<Position<E>> snapshot = new ArrayList<>(2); // max capacity of 2
if (left(p) != null)
snapshot.add(left(p));
if (right(p) != null)
snapshot.add(right(p));
return snapshot;
}
/**
* Adds positions of the subtree rooted at Position p to the given
* snapshot using an inorder traversal
* @param p Position serving as the root of a subtree
* @param snapshot a list to which results are appended
*/
private void inorderSubtree(Position<E> p, List<Position<E>> snapshot) {
if (left(p) != null)
inorderSubtree(left(p), snapshot);
snapshot.add(p);
if (right(p) != null)
inorderSubtree(right(p), snapshot);
}
/**
* Returns an iterable collection of positions of the tree, reported in inorder.
* @return iterable collection of the tree's positions reported in inorder
*/
public Iterable<Position<E>> inorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
inorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/**
* Returns an iterable collection of the positions of the tree using inorder traversal
* @return iterable collection of the tree's positions using inorder traversal
*/
@Override
public Iterable<Position<E>> positions() {
return inorder();
}
}
Explanation / Answer
code for :
• preorderNext(p): Return the position visited after p in a preorder traversal
of T (or null if p is the last node visited).
Linked binary tree :
public class LinkedBinaryTree<E> extends AbstractBinaryTree<E> {
//---------------- nested Node class ----------------
/** Nested static class for a binary tree node. */
protected static class Node<E> implements Position<E> {
private E element; // an element stored at this node
private Node<E> parent; // a reference to the parent node (if any)
private Node<E> left; // a reference to the left child (if any)
private Node<E> right; // a reference to the right child (if any)
/**
* Constructs a node with the given element and neighbors.
*
* @param e the element to be stored
* @param above reference to a parent node
* @param leftChild reference to a left child node
* @param rightChild reference to a right child node
*/
public Node(E e, Node<E> above, Node<E> leftChild, Node<E> rightChild) {
element = e;
parent = above;
left = leftChild;
right = rightChild;
}
// accessor methods
public E getElement() { return element; }
public Node<E> getParent() { return parent; }
public Node<E> getLeft() { return left; }
public Node<E> getRight() { return right; }
// update methods
public void setElement(E e) { element = e; }
public void setParent(Node<E> parentNode) { parent = parentNode; }
public void setLeft(Node<E> leftChild) { left = leftChild; }
public void setRight(Node<E> rightChild) { right = rightChild; }
} //----------- end of nested Node class -----------
/** Factory function to create a new node storing element e. */
protected Node<E> createNode(E e, Node<E> parent,
Node<E> left, Node<E> right) {
return new Node<E>(e, parent, left, right);
}
// LinkedBinaryTree instance variables
/** The root of the binary tree */
protected Node<E> root = null; // root of the tree
/** The number of nodes in the binary tree */
private int size = 0; // number of nodes in the tree
// constructor
/** Construts an empty binary tree. */
public LinkedBinaryTree() { } // constructs an empty binary tree
// nonpublic utility
/**
* Verifies that a Position belongs to the appropriate class, and is
* not one that has been previously removed. Note that our current
* implementation does not actually verify that the position belongs
* to this particular list instance.
*
* @param p a Position (that should belong to this tree)
* @return the underlying Node instance for the position
* @throws IllegalArgumentException if an invalid position is detected
*/
protected Node<E> validate(Position<E> p) throws IllegalArgumentException {
if (!(p instanceof Node))
throw new IllegalArgumentException("Not valid position type");
Node<E> node = (Node<E>) p; // safe cast
if (node.getParent() == node) // our convention for defunct node
throw new IllegalArgumentException("p is no longer in the tree");
return node;
}
// accessor methods (not already implemented in AbstractBinaryTree)
/**
* Returns the number of nodes in the tree.
* @return number of nodes in the tree
*/
@Override
public int size() {
return size;
}
/**
* Returns the root Position of the tree (or null if tree is empty).
* @return root Position of the tree (or null if tree is empty)
*/
@Override
public Position<E> root() {
return root;
}
/**
* Returns the Position of p's parent (or null if p is root).
*
* @param p A valid Position within the tree
* @return Position of p's parent (or null if p is root)
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
@Override
public Position<E> parent(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getParent();
}
/**
* Returns the Position of p's left child (or null if no child exists).
*
* @param p A valid Position within the tree
* @return the Position of the left child (or null if no child exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
@Override
public Position<E> left(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getLeft();
}
/**
* Returns the Position of p's right child (or null if no child exists).
*
* @param p A valid Position within the tree
* @return the Position of the right child (or null if no child exists)
* @throws IllegalArgumentException if p is not a valid Position for this tree
*/
@Override
public Position<E> right(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getRight();
}
// update methods supported by this class
/**
* Places element e at the root of an empty tree and returns its new Position.
*
* @param e the new element
* @return the Position of the new element
* @throws IllegalStateException if the tree is not empty
*/
public Position<E> addRoot(E e) throws IllegalStateException {
if (!isEmpty()) throw new IllegalStateException("Tree is not empty");
root = createNode(e, null, null, null);
size = 1;
return root;
}
/**
* Creates a new left child of Position p storing element e and returns its Position.
*
* @param p the Position to the left of which the new element is inserted
* @param e the new element
* @return the Position of the new element
* @throws IllegalArgumentException if p is not a valid Position for this tree
* @throws IllegalArgumentException if p already has a left child
*/
public Position<E> addLeft(Position<E> p, E e)
throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getLeft() != null)
throw new IllegalArgumentException("p already has a left child");
Node<E> child = createNode(e, parent, null, null);
parent.setLeft(child);
size++;
return child;
}
/**
* Creates a new right child of Position p storing element e and returns its Position.
*
* @param p the Position to the right of which the new element is inserted
* @param e the new element
* @return the Position of the new element
* @throws IllegalArgumentException if p is not a valid Position for this tree.
* @throws IllegalArgumentException if p already has a right child
*/
public Position<E> addRight(Position<E> p, E e)
throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getRight() != null)
throw new IllegalArgumentException("p already has a right child");
Node<E> child = createNode(e, parent, null, null);
parent.setRight(child);
size++;
return child;
}
/**
* Replaces the element at Position p with element e and returns the replaced element.
*
* @param p the relevant Position
* @param e the new element
* @return the replaced element
* @throws IllegalArgumentException if p is not a valid Position for this tree.
*/
public E set(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E temp = node.getElement();
node.setElement(e);
return temp;
}
/**
* Attaches trees t1 and t2, respectively, as the left and right subtree of the
* leaf Position p. As a side effect, t1 and t2 are set to empty trees.
*
* @param p a leaf of the tree
* @param t1 an independent tree whose structure becomes the left child of p
* @param t2 an independent tree whose structure becomes the right child of p
* @throws IllegalArgumentException if p is not a valid Position for this tree
* @throws IllegalArgumentException if p is not a leaf
*/
public void attach(Position<E> p, LinkedBinaryTree<E> t1,
LinkedBinaryTree<E> t2) throws IllegalArgumentException {
Node<E> node = validate(p);
if (isInternal(p)) throw new IllegalArgumentException("p must be a leaf");
size += t1.size() + t2.size();
if (!t1.isEmpty()) { // attach t1 as left subtree of node
t1.root.setParent(node);
node.setLeft(t1.root);
t1.root = null;
t1.size = 0;
}
if (!t2.isEmpty()) { // attach t2 as right subtree of node
t2.root.setParent(node);
node.setRight(t2.root);
t2.root = null;
t2.size = 0;
}
}
/**
* Removes the node at Position p and replaces it with its child, if any.
*
* @param p the relevant Position
* @return element that was removed
* @throws IllegalArgumentException if p is not a valid Position for this tree.
* @throws IllegalArgumentException if p has two children.
*/
public E remove(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
if (numChildren(p) == 2)
throw new IllegalArgumentException("p has two children");
Node<E> child = (node.getLeft() != null ? node.getLeft() : node.getRight() );
if (child != null)
child.setParent(node.getParent()); // child's grandparent becomes its parent
if (node == root)
root = child; // child becomes root
else {
Node<E> parent = node.getParent();
if (node == parent.getLeft())
parent.setLeft(child);
else
parent.setRight(child);
}
size--;
E temp = node.getElement();
node.setElement(null); // help garbage collection
node.setLeft(null);
node.setRight(null);
node.setParent(node); // our convention for defunct node
return temp;
}
public Position<E> PreorderNext(Position<E> v)
{
if(isInternal(v))
{
return left(v);
}
else
{
Position<E> p = parent(v);
if( v.equals(left(p)))
{
return right(p);
}
else
{
while(!v.equals(left(p)))
{
v = p;
p = parent(p);
}
return right(p);
}
}
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.