From ac99c979616f6987f5d57373ee0d7e4172e130e7 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 4 Feb 2025 23:56:39 -0500 Subject: [PATCH] More --- traversal/src/traversal/Main.java | 253 ++++++++++++++++++++++++++---- 1 file changed, 223 insertions(+), 30 deletions(-) diff --git a/traversal/src/traversal/Main.java b/traversal/src/traversal/Main.java index 725c987..d61c80e 100644 --- a/traversal/src/traversal/Main.java +++ b/traversal/src/traversal/Main.java @@ -1,39 +1,47 @@ +package traversal; + +import java.sql.Array; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.NoSuchElementException; import java.util.Queue; +import tester.Tester; -// a non-empty binary tree +// A non-empty binary tree. abstract class BT { X value; BT(X value) { this.value = value; } - // produce an iterator for the left child, or an empty iterator if one does - // not exist + // Produce an iterator for the left child, or an empty iterator if one does + // not exist. abstract Iterator leftIterator(DFTIterator f); - // produce an iterator for the right child, or an empty iterator if one does - // not exist + // Produce an iterator for the right child, or an empty iterator if one does + // not exist. abstract Iterator rightIterator(DFTIterator f); - // add this node's children, if they exist, to the queue (left then right) + // Add this node's children, if they exist, to the queue (left then right). abstract void addChildrenToQueue(Queue> queue); } class Leaf extends BT { - Iterator leftIterator(DFTIterator f) { - throw new NoSuchElementException(); - } - - Iterator rigtIterator(DFTIterator f) { - throw new NoSuchElementException(); - } - - void addChildrenToQueue(Queue> queue) { queue.add(this); } Leaf(X value) { super(value); } + + Iterator leftIterator(DFTIterator f) { + return Collections.emptyIterator(); + } + + Iterator rightIterator(DFTIterator f) { + return Collections.emptyIterator(); + } + + void addChildrenToQueue(Queue> queue) { + // Leaves have no children. Nothing to do. + } } class Node extends BT { @@ -46,23 +54,21 @@ class Node extends BT { this.right = right; } - Iterator leftIterator(DFTIterator f) { - return this.left.leftIterator(f); - } + Iterator leftIterator(DFTIterator f) { return f.iterate(this.left); } Iterator rightIterator(DFTIterator f) { - return this.right.rightIterator(f); + return f.iterate(this.right); } void addChildrenToQueue(Queue> queue) { - this.left.addChildrenToQueue(queue); - this.right.addChildrenToQueue(queue); + queue.add(this.left); + queue.add(this.right); } } -// a depth first iterator for a BT +// A depth first iterator for a BT. interface DFTIterator extends Iterator { - // produce a depth first traversal iterator for the given BT + // Produce a depth first traversal iterator for the given BT. DFTIterator iterate(BT x); } @@ -70,7 +76,7 @@ abstract class DFT implements DFTIterator { BT bt; Iterator left; Iterator right; - // has the top-level value of bt been iterated over yet + // Whether the top-level value of the BT has been iterated over yet. boolean nodeGiven; DFT(BT bt) { @@ -83,13 +89,15 @@ abstract class DFT implements DFTIterator { return left.hasNext() || !nodeGiven || right.hasNext(); } - // check that there is a next element, wraps the getNext method + // Check that there's a next element, wraps getNext(). public X next() { - if (!this.hasNext()) { throw new NoSuchElementException(); } + if (!this.hasNext()) { + throw new NoSuchElementException("Nothing left in tree."); + } return this.getNext(); } - // actually get the next + // Get the next element. abstract X getNext(); } @@ -97,7 +105,17 @@ class InOrder extends DFT { InOrder(BT bt) { super(bt); } - public DFTIterator iterate(BT x) { return new InOrder(x); } + public DFTIterator iterate(BT x) { return new InOrder<>(x); } + + X getNext() { + // Left, root, right. + if (this.left.hasNext()) return this.left.next(); + else if (!this.nodeGiven) { + this.nodeGiven = true; + return this.bt.value; + } else if (this.right.hasNext()) return this.right.next(); + throw new NoSuchElementException("Nothing left in tree."); + } } class PreOrder extends DFT { @@ -105,6 +123,16 @@ class PreOrder extends DFT { PreOrder(BT bt) { super(bt); } public DFTIterator iterate(BT x) { return new PreOrder(x); } + + X getNext() { + // Root, left, right. + if (!this.nodeGiven) { + this.nodeGiven = true; + return this.bt.value; + } else if (this.left.hasNext()) return this.left.next(); + else if (this.right.hasNext()) return this.right.next(); + throw new NoSuchElementException("Nothing left in tree."); + } } class PostOrder extends DFT { @@ -112,12 +140,177 @@ class PostOrder extends DFT { PostOrder(BT bt) { super(bt); } public DFTIterator iterate(BT x) { return new PostOrder(x); } + + X getNext() { + // Left, right, root. + if (this.left.hasNext()) return this.left.next(); + else if (this.right.hasNext()) return this.right.next(); + else if (!this.nodeGiven) { + this.nodeGiven = true; + return this.bt.value; + } + + throw new NoSuchElementException("Nothing left in tree."); + } } -// a breadth first iterator for a BT +// A breadth first iterator for a BT. class BFT implements Iterator { - Queue> queue = new LinkedList>(); + Queue> queue = new LinkedList<>(); BFT(BT bt) { queue.add(bt); } + + public boolean hasNext() { return !queue.isEmpty(); } + + public X next() { + if (!this.hasNext()) + throw new NoSuchElementException("Nothing left in tree."); + + // Returns & removes the head of the queue. + BT current = queue.remove(); + + // Add the childred of the current node to the queue. + current.addChildrenToQueue(queue); + + // Return the value of the current node. + return current.value; + } +} + +class TreeFinder { + // Know the first element of the preorder list will be the root node of the + // tree. Assuming node values are unique, you can then locate that node in + // the inorder list. The nodes on the left of it will be on the left + // subtree, the ones to the right on the right. Repeat the process on the + // subtreees. + + // Learned you can do static methods with a type like this :). + static BT find(ArrayList inorder, ArrayList preorder) { + int inorderRootIdx = inorder.indexOf(preorder.getFirst()); + System.out.println(inorderRootIdx); + System.out.println(preorder); + System.out.println(inorder); + return findHelper(inorder, preorder, inorderRootIdx, 0); + } + + static BT findHelper( + ArrayList inorder, ArrayList preorder, int inorderRootIdx, + int preorderIdx + ) { + System.out.println(inorderRootIdx); + System.out.println(preorder); + System.out.println(inorder); + // If the lists are almost empty, it's a leaf. + if (inorder.size() == 1 && preorder.size() == 1) { + System.out.println("leaf"); + return new Leaf<>(inorder.getFirst()); + } + + T val = preorder.getFirst(); + System.out.println("Node " + val); + + // Get left side. + ArrayList leftInorder = + new ArrayList<>(inorder.subList(0, inorderRootIdx)); + ArrayList leftPreorder = + new ArrayList<>(preorder.subList(preorderIdx + 1, preorder.size())); + int leftInorderRootIdx = leftInorder.indexOf(leftPreorder.getFirst()); + + // Set left tree. + BT leftTree = findHelper( + leftInorder, leftPreorder, leftInorderRootIdx, preorderIdx + ); + + // Get right side. + ArrayList rightInorder = + new ArrayList<>(inorder.subList(inorderRootIdx + 1, inorder.size()) + ); + ArrayList rightPreorder = + new ArrayList<>(preorder.subList(preorderIdx + 1, preorder.size())); + int rightInorderRootIdx = + rightInorder.indexOf(rightPreorder.getFirst()); + + // Set right tree. + BT rightTree = + findHelper(rightInorder, rightPreorder, rightInorderRootIdx); + + return new Node<>(val, leftTree, rightTree); + } +} + +class Examples { + BT tree; + void init() { + tree = new Node<>( + 1, new Node<>(2, new Leaf<>(4), new Leaf<>(5)), new Leaf<>(3) + ); + } + + void testInorder(Tester t) { + init(); + Iterator inorder = new InOrder<>(tree); + t.checkExpect(inorder.hasNext(), true); + t.checkExpect(inorder.next(), 4); + t.checkExpect(inorder.next(), 2); + t.checkExpect(inorder.next(), 5); + t.checkExpect(inorder.next(), 1); + t.checkExpect(inorder.next(), 3); + t.checkExpect(inorder.hasNext(), false); + t.checkException( + new NoSuchElementException("Nothing left in tree."), inorder, "next" + ); + } + + void testPreorder(Tester t) { + init(); + Iterator preorder = new PreOrder<>(tree); + t.checkExpect(preorder.next(), 1); + t.checkExpect(preorder.next(), 2); + t.checkExpect(preorder.next(), 4); + t.checkExpect(preorder.next(), 5); + t.checkExpect(preorder.next(), 3); + } + + void testPostorder(Tester t) { + init(); + Iterator postorder = new PostOrder<>(tree); + t.checkExpect(postorder.next(), 4); + t.checkExpect(postorder.next(), 5); + t.checkExpect(postorder.next(), 2); + t.checkExpect(postorder.next(), 3); + t.checkExpect(postorder.next(), 1); + } + + void testBreadthFirst(Tester t) { + init(); + Iterator breadth = new BFT<>(tree); + t.checkExpect(breadth.hasNext(), true); + t.checkExpect(breadth.next(), 1); + t.checkExpect(breadth.next(), 2); + t.checkExpect(breadth.next(), 3); + t.checkExpect(breadth.next(), 4); + t.checkExpect(breadth.next(), 5); + t.checkExpect(breadth.hasNext(), false); + t.checkException( + new NoSuchElementException("Nothing left in tree."), breadth, "next" + ); + } + + void testTreeFinder(Tester t) { + init(); + + Iterator inorder = new InOrder<>(tree); + Iterator preorder = new PreOrder<>(tree); + + ArrayList inorderList = new ArrayList<>(); + ArrayList preorderList = new ArrayList<>(); + + while (inorder.hasNext()) inorderList.add(inorder.next()); + while (preorder.hasNext()) preorderList.add(preorder.next()); + + BT found = TreeFinder.find(inorderList, preorderList); + + t.checkExpect(found, tree); + } }