I'm trying to implement iterator on AVL tree, I'm stuck at this specific function:
/**
* #return an iterator for the Avl Tree. The returned iterator iterates over the tree nodes.
* in an ascending order, and does NOT implement the remove() method.
*/
public Iterator<Integer> iterator(){
List myList=new ArrayList<>();
Node counter=root;
Node counter1=root.getChildernLeft();
if(counter1==null){
myList.add(counter1);
}
Node counter1=root.getChildernLeft();
}
I added my two classes:
full code, Node class:
public class Node {
private Node parent;
private Node childernRight;
private Node childernLeft;
private int data;
private int height;
/**
* constractor
*/
public Node(int data, Node childernLeft, Node childernRight) {
this.data = data;
this.childernLeft = childernLeft;
this.childernRight = childernRight;
this.childernRight.setParent(this);
this.childernLeft.setParent(this);
}
public Node(int data) {
this.data = data;
}
public Node getParent() {
return parent;
}
public Node getChildernRight() {
return childernRight;
}
public Node getChildernLeft() {
return childernLeft;
}
public void setParent(Node parent) {
this.parent = parent;
}
public void setChildernRight(Node childernRight) {
this.childernRight = childernRight;
this.childernRight.setParent(this);
}
public void setChildernLeft(Node childernLeft) {
this.childernLeft = childernLeft;
this.childernLeft.setParent(this);
}
public int getData() {
return data;
}
public String toString() {
if (this.childernLeft != null && this.getChildernRight() != null) {
return childernLeft.toString() + "," + this.data + "," + childernRight.toString();
} else if (this.childernLeft != null && this.getChildernRight() == null) {
return childernLeft.toString() + "," + this.data;
} else if (this.childernLeft == null && this.getChildernRight() != null) {
return this.data + "," + childernRight.toString();
} else {
return this.data + "";
}
}
public int balanceFactor() {
int balanceFactor = childernRight.height - childernLeft.height;
return balanceFactor;
}
public boolean hasChildrenRight() {
if (this.childernRight != null) {
return true;
}
else{
return false;
}
}
public boolean hasChildrenLeft() {
if (this.childernLeft != null) {
return true;
}
else{
return false;
}
}
/**
* if we have many children in the tree
*/
public void addNode(Node val){
if(hasChildrenRight()&&this.data>val.data){
this.setChildernRight(val);
}
if(!hasChildrenLeft()&&this.data<val.data){
this.setChildernLeft(val);
}
if(!hasChildrenLeft()&&!hasChildrenRight()){
if(this.data>val.data){
setChildernLeft(val);
}
else{
setChildernRight(val);
}
}
if(val.data>this.data){
childernRight.addNode(val);
}
else{
childernLeft.addNode(val);
}
}
}
full code for AvlTree:`
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class AvlTree {
private Node root;
private int size;
/**
* default constructor.
*/
public AvlTree() {
this.root = null;
this.size = 0;
}
/**
* A constructor that builds a new AVL tree containing all unique values in the input
* array
*
* #param data the values to add to tree
*/
public AvlTree(int[] data) {
for (int i = 0; i < data.length; i++) {
add(data[i]);
}
}
/**
* A copy constructor that creates a deep copy of the given oop.ex4.data_structures.AvlTree. The new tree
* contains all the values of the given tree, but not necessarily in the same structure.
*
* #param avlTree an AVL tree.
*/
public AvlTree(AvlTree avlTree) {
}
/**
* Add a new node with the given key to the tree.
*
* #param newValue the value of the new node to add.
* #return true if the value to add is not already in the tree and it was successfully added,
* false otherwise.
*/
public boolean add(int newValue) {
if (root == null) {
root = new Node(newValue);
size++;
return true;
}
Node current = root;
Node parent = null;
while (current != null) {
if (current.getData() == newValue) {
return false;
}
parent = current;
if (newValue < current.getData()) {
current = current.getChildernLeft();
} else {
current = current.getChildernRight();
}
}
size++;
// when we here the new NODE Need to be chiled of Node hashmor in parent.
// addHelper is adding the new Node.2
// addHelper(newNodeToAdd, current);
return true;
}
private void addHelper(Node newNodeToAdd, Node current) {
// if (newNodeToAdd.getData() > current.getData()) {
// if (current.getChildernRight() == null) {
// current.setChildernRight(newNodeToAdd);
// } else {
// addHelper(newNodeToAdd, current.getChildernRight());
// }
// } else {
// if (current.getChildernLeft() == null) {
// current.setChildernLeft(newNodeToAdd);
// } else {
// addHelper(newNodeToAdd, current.getChildernLeft());
// }
// }
}
/**
* Check whether the tree contains the given input value.
*
* #param searchVal the value to search for.
* #return the depth of the node (0 for the root) with the given value if it was found in the tree, −1 otherwise.
*/
public int contains(int searchVal) {
Node current = root;
int depth = 0;
while (current != null) {
if (current.getData() == searchVal) {
return depth;
}
depth++;
if (searchVal < current.getData()) {
current = current.getChildernLeft();
} else {
current = current.getChildernRight();
}
}
return -1;
}
/**
* Removes the node with the given value from the tree, if it exists.
*
* #param toDelete the value to remove from the tree.
* #return true if the given value was found and deleted, false otherwise.
*/
public boolean delete(int toDelete) {
size -= 1;
return true;
}
/**
* #return the number of nodes in the tree.
*/
public int size() {
return size;
}
/**
* #return an iterator for the Avl Tree. The returned iterator iterates over the tree nodes.
* in an ascending order, and does NOT implement the remove() method.
*/
public Iterator<Integer> iterator(){
List myList=new ArrayList<>();
Node counter=root;
Node counter1=root.getChildernLeft();
if(counter1==null){
myList.add(counter1);
}
Node counter1=root.getChildernLeft();
}
/**
* Calculates the minimum number of nodes in an AVL tree of height h
*
* #param h the height of the tree (a non−negative number) in question.
* #return the minimum number of nodes in an AVL tree of the given height.
*/
public static int findMinNodes(int h) {
// I SOVLE THIS WITH ROCKISA
int counterMin = 0;
if (h == 0) {
return counterMin = 1;
}
if (h == 1) {
return counterMin = 2;
}
return (findMinNodes(h - 1) + findMinNodes(h - 2) + 1);
}
/**
* Calculates the maximum number of nodes in an AVL tree of height h.
*
* #param h the height of the tree (a non−negative number) in question.
* #return the maximum number of nodes in an AVL tree of the given height.
*/
public static int findMaxNodes(int h) {
int counterMax = 0;
for (int i = 0; i < h; i++) {
counterMax += Math.pow(h, i);
}
return counterMax;
}
/**
* #return
*/
public String toString() {
if (root == null) {
return "";
}
return root.toString();
}
//THIS IS OK
public void RotationRr(Node valRotation) {
if (valRotation == root) {
Node keepRootChild = root.getChildernRight();
root.setChildernRight(null);
}
Node parent1 = valRotation.getParent();
Node keepRightChild = valRotation.getChildernRight();///4
valRotation.setChildernRight(null);
keepRightChild.setParent(parent1);
if (!keepRightChild.hasChildrenLeft()) {
keepRightChild.setChildernLeft(valRotation);
valRotation.setParent(keepRightChild);
} else {
keepRightChild.getChildernLeft().addNode(valRotation);
}
}
public void RotationLr(Node valRotation) {
RotationLl(valRotation);
}
/**
* ........CHECK.....!!!!TODO
*
* #param valRotation
*/
public void RotationLl(Node valRotation) {
Node parent2 = valRotation.getParent();
Node keepLeftChild = valRotation.getChildernLeft();
valRotation.setChildernLeft(null);
keepLeftChild.setParent(parent2);
if (!keepLeftChild.hasChildrenRight()) {
keepLeftChild.setParent(keepLeftChild);
} else {
keepLeftChild.getChildernRight().addNode(valRotation);
}
}
public void RotationRl(Node valRotation) {
RotationRr(valRotation);
}
public static void main(String[] args) {
AvlTree avlTree = new AvlTree();
avlTree.add(7);
avlTree.add(2);
System.out.println(avlTree.contains(2));
// System.out.println(avlTree.contains(5));
avlTree = new AvlTree();
avlTree.add(2);
avlTree.add(7);
System.out.println(avlTree.contains(2));
// System.out.println(avlTree);
}
}
`
You can implement a iterator using stack
public Iterator<V> iterator() {
return new Itr();
}
private class Itr<V> implements Iterator<V> {
TreeNode<V> localNode = (TreeNode<V>) root;
Stack<TreeNode<V>> stack;
public Itr() {
stack = new ArrayStack<TreeNode<V>>();
while (localNode != null) {
stack.push(localNode);
localNode = localNode.getLeftChield();
}
}
public boolean hasNext() {
return !stack.empty();
}
public V next() {
TreeNode<V> node = stack.pop();
V v = node.getValue();
if (node.getRightChield() != null) {
node = node.getRightChield();
while (node != null) {
stack.push(node);
node = node.getLeftChield();
}
}
return v;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Related
There is a Tree implementation, which requires the correction and idea of how to implement the logic.
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* #param <T>
*/
class TreeNode<T> implements Iterable<TreeNode<T>> {
private final List<TreeNode<T>> elementsIndex;
public T data;
public TreeNode<T> parent;
public List<TreeNode<T>> children;
/**
* #param data
*/
public TreeNode(T data) {
this.data = data;
this.children = new LinkedList<TreeNode<T>>();
this.elementsIndex = new LinkedList<TreeNode<T>>();
this.elementsIndex.add(this);
}
/**
* #param depth
* #return Indentation
*/
private static String createIndent(int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append('-');
}
return sb.toString();
}
/**
* #return parent
*/
public boolean isRoot() {
return parent == null;
}
/**
* #return check the size of child
*/
public boolean isLeaf() {
return children.size() == 0;
}
/**
* #param child
* #return child node
*/
public TreeNode<T> addChild(T child) {
TreeNode<T> childNode = new TreeNode<T>(child);
childNode.parent = this;
this.children.add(childNode);
this.registerChildForSearch(childNode);
return childNode;
}
/**
* #return the depth of the level
*/
public int getLevel() {
if (this.isRoot())
return 0;
else
return parent.getLevel() + 1;
}
/**
* #param node
*/
private void registerChildForSearch(TreeNode<T> node) {
elementsIndex.add(node);
if (parent != null)
parent.registerChildForSearch(node);
}
/**
* #param cmp
* #return finds the element
*/
public TreeNode<T> findTreeNode(Comparable<T> cmp) {
for (TreeNode<T> element : this.elementsIndex) {
T elData = element.data;
if (cmp.compareTo(elData) == 0)
return element;
}
return null;
}
/**
* #return the root
*/
#Override
public String toString() {
return data != null ? data.toString() : "[data null]";
}
/**
* #return iterator
*/
#Override
public Iterator<TreeNode<T>> iterator() {
TreeNodeIter<T> iter = new TreeNodeIter<T>(this);
return iter;
}
/**
* #param treeRoot
* #param data
* #return the data else null if not found
*/
public TreeNode<T> search(TreeNode<T> treeRoot, T data) {
Comparable<T> searchCriteria = new Comparable<T>() {
#Override
public int compareTo(Object treeData) {
if (treeData == null)
return 1;
boolean nodeOk = treeData.equals(data);
return nodeOk ? 0 : 1;
}
};
TreeNode<T> found = treeRoot.findTreeNode(searchCriteria);
return found;
}
/**
* #param treeRoot
* #return the whole tree
*/
public StringBuilder display(TreeNode<T> treeRoot) {
StringBuilder print = new StringBuilder();
print.append('\n');
for (TreeNode<T> node : treeRoot) {
String indent = createIndent(node.getLevel());
print.append(indent + node.data);
print.append("\n|");
}
if (print.length() > 0)
print.deleteCharAt(print.length() - 1);
return print;
}
}
/**
* #param <T>
*/
class TreeNodeIter<T> implements Iterator<TreeNode<T>> {
private final TreeNode<T> treeNode;
private final Iterator<TreeNode<T>> childrenCurNodeIter;
private ProcessStages doNext;
private TreeNode<T> next;
private Iterator<TreeNode<T>> childrenSubNodeIter;
/**
* #param treeNode
*/
public TreeNodeIter(TreeNode<T> treeNode) {
this.treeNode = treeNode;
this.doNext = ProcessStages.ProcessParent;
this.childrenCurNodeIter = treeNode.children.iterator();
}
/**
* #return true if there is nay element
*/
#Override
public boolean hasNext() {
if (this.doNext == ProcessStages.ProcessParent) {
this.next = this.treeNode;
this.doNext = ProcessStages.ProcessChildCurNode;
return true;
}
if (this.doNext == ProcessStages.ProcessChildCurNode) {
if (childrenCurNodeIter.hasNext()) {
TreeNode<T> childDirect = childrenCurNodeIter.next();
childrenSubNodeIter = childDirect.iterator();
this.doNext = ProcessStages.ProcessChildSubNode;
return hasNext();
} else {
this.doNext = null;
return false;
}
}
if (this.doNext == ProcessStages.ProcessChildSubNode) {
if (childrenSubNodeIter.hasNext()) {
this.next = childrenSubNodeIter.next();
return true;
} else {
this.next = null;
this.doNext = ProcessStages.ProcessChildCurNode;
return hasNext();
}
}
return false;
}
/**
* #return the next element
*/
#Override
public TreeNode<T> next() {
return this.next;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
enum ProcessStages {
ProcessParent,
ProcessChildCurNode,
ProcessChildSubNode
}
}
So, the issue is that I have the data something like this
Gen
|-Test1
|--Mat
|-Test2
|--123
|---Child's Child
|----Child's Child's Child
|----2406
|-Test3
|--24
But to implement that I have to hard code something like this
public static TreeNode<String> getSet() {
TreeNode<String> root = new TreeNode<String>("Gen");
{
TreeNode<String> node0 = root.addChild("Test1");
{
TreeNode<String> node00 = node0.addChild("Mat");
}
TreeNode<String> node1 = root.addChild("Test2");
{
TreeNode<String> node10 = node1.addChild("123");
{
TreeNode<String> node100 = node10.addChild("Child's Child");
{
TreeNode<String> node1000 = node100.addChild("Child's Child's Child");
TreeNode<String> node1001 = node100.addChild("2406");
}
}
}
TreeNode<String> node2 = root.addChild("Test3");
{
TreeNode<String> node20 = node2.addChild("24");
}
}
return root;
}
}
On the top that I have the helper method called getPartentChildPart() method which is used to get the
Map<Parent, List> that is Map<String,List<String>>
Gen
|-Test1
|--Mat
|-Test2
|--123
|---Child's Child
|----Child's Child's Child
|----2406
|-Test3
|--24
For example, if I gave Gen as the parameter to getPartentChildPart() then it will return
Map<Gen,<Test1,Test2,Test3>>
So far what I can achieve is this
public void Build(Map<String, List<String>> ROOT) {
TreeNode<String> root = null;
TreeNode<String> node = null;
for (Map.Entry<String, List<String>> i : ROOT.entrySet()) {
root = new TreeNode<>(i.getKey());
for (String j : i.getValue())
{
node = root.addChild(j);
parent = getPartentChildPart(j);
Build(parent);
}
System.out.println("Root"+root.display(root));
}
}
public void Show() {
Map<String, List<String>> rt = null;
rt = getPartentChildPart("Gen");
Build(rt);
}
The result what I get this is
Gen
|-Test1
|-Test2
|-Test3
I don't understand why recursion is not working and how can I implement this... Although if I hardcode this it can work what if my tree grows in future then hard code will not work.
The first thing to do would be to add a method that returns your list of children. From there recursion becomes quite simple.
void itChildren(TreeNode<T> node)
{
// do stuff
if (!node.getChildren().isEmpty())
{
for (int i = 0; i < node.getChildren().size(); i++)
{
itChildren(node.getChildren().get(i));
}
}
// do stuff
}
This would then iterate over the entirety of the tree. Depending on whether you want to do things before (which I believe is your case) or after the children you can place your code either at the top or bottom of the function.
Let me know if this works for you.
final TreeNode<String> struct = "Gen";
public void build(Map<String, List<String>> parentRoot, TreeNode<String> node) {
Map<String, List<String>> parent;
for (Map.Entry<String, List<String>> i : parentRoot.entrySet()) {
for (Stringj : i.getValue()) {
TreeNode<String> childNode = node.addChild(new TreeNode<>(j));
parent = getPartentChildPart(j);
build(parent, childNode);
}
}
}
public void show() {
Map<String, List<String>> ROOT = null;
ROOT = getPartentChildPart("Gen");
build(ROOT, struct);
System.out.println(struct.display(struct));
}
The mistake was that I need to create a new node every time and need to get the root outside the recurrsion.
I am currently having a difficulty understanding the role of a constructor when it comes to a Priority Queue. I have gone through and created methods such as peek, pop, length and etc for the queue however I am stuck to when it comes to the constructor. It is probably a mental block more than anything.
My class is as follows:
public class PQueue<T> {
private PQueueItem<T> head;
public static enum ORDER {
ASC, DESC;
}
public static ORDER DEFAULT_ORDER;
private ORDER order;
/**
* The default constructor for a PQueue, with the default order for priorities
*/
public PQueue() {
// ...add code
}
/**
* The constructor to make a new PQueue with a given order
*
* #param order
*/
public PQueue(ORDER order) {
// ...add code
}
/**
* Remove and return data from the item at the front of the queue
*
* #return
*/
public T pop() {
if(head == null) {
return null;
}
// temp variable to hold head data
T e1 = head.getData();
// gives the next item the head
head = head.getNext();
// returns temp variable
return e1;
}
/**
* Return the data from the item at the front of the queue, without removing the
* item itself
*
* #return
*/
public T peek() {
// returns head data
if(head == null) {
return null;
}
return head.getData();
}
/**
* Remove and return the item at the front of the queue
*
* #return
*/
public PQueueItem<T> popItem() {
if (head == null) {
return null;
}
// temp variable to hold item
PQueueItem<T> e1 = this.head;
// gives the next item the head
this.head = head.getNext();
// returns temp variable
return e1;
}
/**
* Return the item at the front of the queue without removing it
*
* #return
*/
public PQueueItem<T> peekItem() {
if (head == null) {
return null;
}
return head;
}
/**
* Insert a new item into the queue, which should be put in the right place
* according to its priority. That is, is order == ASC, then the new item should
* appear in the queue before all items with a HIGHER priority. If order ==
* DESC, then the new item should appear in the queue before all items with a
* LOWER priority.
*
* #param data
* #param priority
*/
public void insert(T data, int priority) {
if (order == ORDER.ASC) {
// current item
PQueueItem<T> e1 = head;
while (e1.getNext() != null) {
// is inserted item greater than current item
if (priority > e1.getPriority()) {
// is inserted item smaller than next item
if (priority < e1.getNext().getPriority()) {
// create and insert new item, reassign links in the list
PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
newPQ.setNext(e1.getNext());
e1.setNext(newPQ);
}
// check to see if priority equates to the next item's priority
else if (priority == e1.getNext().getPriority()) {
// is new item's data alphabetically greater than the next item's data
if (((String) data).compareToIgnoreCase((String) e1.getNext().getData()) > 0) {
PQueueItem<T> nextPQ = e1.getNext();
PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
newPQ.setNext(nextPQ.getNext());
nextPQ.setNext(newPQ);
} else {
PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
newPQ.setNext(e1.getNext());
e1.setNext(newPQ);
}
} else {
// iterate current item
e1 = head.getNext();
}
}
// if item to be inserted is smaller than the current item
else if (priority < e1.getPriority()) {
PQueueItem<T> newPQ = new PQueueItem<T>(e1.getData(), e1.getPriority());
newPQ.setNext(e1.getNext());
e1.setData(data);
e1.setPriority(priority);
}
}
} else if (order == ORDER.DESC) {
PQueueItem<T> e1 = head;
while (e1.getNext() != null) {
// is inserted item less than current item
if (priority < e1.getPriority()) {
// is inserted item greater than next item
if (priority > e1.getNext().getPriority()) {
// create and insert new item, reassign links in the list
PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
newPQ.setNext(e1.getNext());
e1.setNext(newPQ);
}
// check to see if priority equates to the next item's priority
else if (priority == e1.getNext().getPriority()) {
// is new item's data alphabetically less than the next item's data
if (((String) data).compareToIgnoreCase((String) e1.getNext().getData()) < 0) {
PQueueItem<T> nextPQ = e1.getNext();
PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
newPQ.setNext(nextPQ.getNext());
nextPQ.setNext(newPQ);
} else {
PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
newPQ.setNext(e1.getNext());
e1.setNext(newPQ);
}
} else {
// iterate current item
e1 = head.getNext();
}
}
// if item to be inserted is greater than the current item
else if (priority > e1.getPriority()) {
PQueueItem<T> newPQ = new PQueueItem<T>(e1.getData(), e1.getPriority());
newPQ.setNext(e1.getNext());
e1.setData(data);
e1.setPriority(priority);
}
}
}
}
/**
* Return the length of the queue
*
* #return
*/
public int length() {
if (head == null) {
return 0;
} else {
int size = 0;
for (PQueueItem<T> i = head; i.getNext() != null; i = i.getNext()) {
size++;
}
return size;
}
}
public String toString() {
int i = length();
PQueueItem<T> current = head;
StringBuffer sb = new StringBuffer();
while (i > 0) {
sb.append(current.toString());
if (i > 1)
sb.append(": ");
current = current.getNext();
i--;
}
return sb.toString();
}
}
Also when it comes to the code I have done a few null checks however I have read that there is a method of using optional which is far cleaner and better. If you have any recommendations can you please let me know?
The other class for the PQueueItem is as below:
public class PQueueItem<T> {
private int priority;
private T data;
private PQueueItem<T> next;
public PQueueItem(T data, int priority) {
this.data = data;
this.priority = priority;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public PQueueItem<T> getNext() {
return next;
}
public void setNext(PQueueItem<T> next) {
this.next = next;
}
public String toString() {
return String.format("[%s,%d]", data.toString(), priority);
}
}
Thank you in advanced and any criticism will be taken with gratitude.
I've been working on trying to fix this error for a few hours and i cant figure out where/what is causing the error
(java.lang.IndexOutOfBoundsException: index:68 size: 26)
this creates the alphabet in all caps
String [] myStringsChars= new String[26];
for(int i = 0; i < 26; i++)
{
myStringsChars[i] = new String(Character.toChars(i+65));
System.out.println(myStringsChars[i]);
}
i suspect the cause of the problem is one of these two loops
adds array letters to a linked list and sets it as a node
int j=0;
while (j<myStringsChars.length){
BinaryTree.add(alphabet = new TreeNode(myStringsChars[j]));
if (j<=26){
j++;
}
}
sets the node parents and children
int k =0;
while (k<BinaryTree.size()){
int find=(k-1)/2;
BinaryTree.get(k).setParent(BinaryTree.get(find));
if(k%2 ==0){
(BinaryTree.get(k).getParent()). setRightChild(BinaryTree.get(k));
}
else{
(BinaryTree.get(k).getParent()).setLeftChild(BinaryTree.get(k));
}
k++;
}
here's the rest of my code in case it helps
import java.util.*;
public class TreeExercise
{
public static void main(String args[])
{
String [] myStringsChars= new String[26];
for(int i = 0; i < 26; i++)
{
myStringsChars[i] = new String(Character.toChars(i+65));
System.out.println(myStringsChars[i]);
}
List<TreeNode> BinaryTree = new LinkedList();
int j=0;
while (j<myStringsChars.length){
BinaryTree.add(alphabet = new TreeNode(myStringsChars[j]));
if (j<=26){
j++;
}
}
int k =0;
while (k<BinaryTree.size()){
int find=(k-1)/2;
BinaryTree.get(k).setParent(BinaryTree.get(find));
if(k%2 ==0){
(BinaryTree.get(k).getParent()). setRightChild(BinaryTree.get(k));
}
else{
(BinaryTree.get(k).getParent()).setLeftChild(BinaryTree.get(k));
}
k++;
}
BinaryTree.get(0).setParent(null);
Scanner input= new Scanner(System.in);
String userChoice="";
while (!(userChoice.equals("end"))){
System.out.println("enter two CAPITAL letters to find their common ancestor ex.(DC)\n type 'end' to end program");
userChoice= input.nextLine();
char letter1=userChoice.charAt(0);
char letter2=userChoice.charAt(1);
int let1= (int)letter1;
int let2= (int)letter2;
if(userChoice.length()<=2){
// cant find BinaryTree ERROR
TreeNode commonAncestor= findLowestCommonAncestor(root, BinaryTree.get(let1), BinaryTree.get(let2));
if (commonAncestor !=null){
System.out.println(commonAncestor.getContents());
}
System.out.println("Result is: " + "D");
}
else if (userChoice.equals("end")){
System.exit(0);
}
else{
System.out.println("you must type in 2 capital letters");
userChoice=input.nextLine();
}
}
}
public static TreeNode findLowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2)
{
findLowestCommonAncestor(root.getRightChild(), node1, node2)
//every time
TreeNode rightChild= findLowestCommonAncestor(root.getRightChild(), node1, node2);
TreeNode leftChild= findLowestCommonAncestor(root.getLeftChild(), node1, node2);
if (leftChild != null && rightChild!=null){
return root;
}
if(root==null){
return null;
}
if (leftChild!=null){
return leftChild;
}
if(root.getContents()==node1 || root.getContents()==node2){
return root;
}
else {
return rightChild;
}
}
}
TreeNode nodes
public class TreeNode<T extends Comparable>{
private T contents;
private TreeNode<T> parent;
private TreeNode<T> leftChild;
private TreeNode<T> rightChild;
private int level;
public TreeNode()
{
//added
//parent=null;
//leftChild=null;
//rightChild=null;
//level=0;
}
public TreeNode(T data){
contents=data;
this.parent=parent;
}
public TreeNode(T data, TreeNode parent)
{
contents = data;
this.parent = parent;
}
public void setLeftChild(TreeNode node)
{
this.leftChild = node;
}
public void setRightChild(TreeNode node)
{
this.rightChild = node;
}
public boolean isContentEquals(T data)
{
return 0 == getContents().compareTo(data);
}
/**
* #return the contents
*/
public T getContents() {
return contents;
}
/**
* #param contents the contents to set
*/
public void setContents(T contents) {
this.contents = contents;
}
/**
* #return the parent
*/
public TreeNode getParent() {
return parent;
}
/**
* #param parent the parent to set
*/
public void setParent(TreeNode parent) {
this.parent = parent;
}
/**
* #return the leftChild
*/
public TreeNode getLeftChild() {
return leftChild;
}
/**
* #return the rightChild
*/
public TreeNode getRightChild() {
return rightChild;
}
/**
* Given an object T contentToSearch, this method returns
* the node that stores the contentToShare or null if not found on the current tree
* #return the node
*/
public TreeNode findNodeOnTree(T contentToSearch)
{
List<TreeNode> nodes = new LinkedList();
nodes.clear();
nodes.add(this);
while(!nodes.isEmpty())
{
TreeNode current = nodes.remove(0);
if(current.isContentEquals(contentToSearch))
{
return current;
}
if(current.leftChild != null)
{
nodes.add(current.leftChild);
}
if(current.rightChild != null)
{
nodes.add(current.rightChild);
}
}
return null;
}
/**
* #return the level
*/
public int getLevel() {
return level;
}
/**
* #param level the level to set
*/
public void setLevel(int level) {
this.level = level;
}
}
Your error appears to be here, guessing that this is line TreeExercise.java:113:
int let1= (int)letter1;
int let2= (int)letter2;
if(userChoice.length()<=2){
// cant find BinaryTree ERROR
TreeNode commonAncestor= findLowestCommonAncestor(root,
BinaryTree.get(let1), BinaryTree.get(let2));
^^^^ ^^^^
Your tree list is indexed from 0 to 25, but let1 and let2, given an input of DE, are 68 and 69. So, try:
int let1= (int)letter1 - 'A';
int let2= (int)letter2 - 'A';
It would be clearer in your other code, too, to use 'A' rather than 65.
I am learning Java SE and am currently at simple linked lists (page 687/1047 of Savitch's Absolute Java).
I am stuck at instantiating the LinkList in the main method of my demo class:
LinkedList1 list = new LinkedList1();
I tried using breakpoint and it indicates a ReflectiveOperationException.
This is the code:
public class Node1
{
private String item;
private int count;
private Node1 link;
public Node1()
{
link = null;
item = null;
count = 0;
}
public Node1(String newItem, int newCount, Node1 linkValue)
{
setData(newItem, newCount);
link = linkValue;
}
public void setData(String newItem, int newCount)
{
item = newItem;
count = newCount;
}
public void setLink(Node1 newLink)
{
link = newLink;
}
public String getItem()
{
return item;
}
public int getCount()
{
return count;
}
public Node1 getLink()
{
return link;
}
}
This is the LinkedList1 class:
public class LinkedList1
{
private Node1 head;
public LinkedList1()
{
head = null;
}
/**
* Adds a node at the start of the list with the specified data.
* The added node will be the first node in the list.
*/
public void add(String itemName, int itemCount)
{
head = new Node1(itemName, itemCount, head);
}
/**
* Removes the head node and returns true if the list contains at least
* one node. Returns false if the list is empty.
*/
public boolean deleteHeadNode()
{
if (head != null)
{
head = head.getLink();
return true;
}
else
return false;
}
/**
* Returns the number of nodes in the list.
*/
public int size()
{
int count = 0;
Node1 position = head;
while (position != null)
{
count++;
head = position.getLink();
}
return count;
}
public boolean contains(String item)
{
return (find(item) != null);
}
/**
* Finds the first node containing the target item, and returns a
* reference to that node. If the target is not in the list, null is returned.
*/
public Node1 find(String target)
{
Node1 position = head;
String itemAtPosition;
while(position != null)
{
itemAtPosition = position.getItem();
if(itemAtPosition.equals(target))
{
return position;
}
position = position.getLink();
}
return null; //target was not found
}
public void outputList()
{
Node1 position = head;
while (position != null)
{
System.out.println(position.getItem() + " " + position.getCount());
position = position.getLink();
}
}
}
I think that the problem has something to do with the constructor of Node1 having the member link of type Node1. I'm trying to understand how these data structures work and not just resort to using the built-in ArrayList(& APIs) for my projects. Can you guys have a look and point me in the right direction. Any help would be very much appreciated.
This is my main method.
public class LinkedListDemo
{
public static void main(String[] args)
{
try
{
LinkedList1 list = new LinkedList1();
list.add("apples", 1);
list.add("bananas", 2);
list.add("cantaloupe", 3);
System.out.println("List has "+ list.size() + " nodes.");
list.outputList();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
Your size method contains an infinite loop which explain why the outputs are never reached.
while (position != null)
{
count++;
head = position.getLink();
}
You are looping until position is null, but never assign anything to position and instead assign to head. Instead, you want to do
while (position != null)
{
count++;
position = position.getLink();
}
Now you would get the output
List has 3 nodes.
cantaloupe 3
bananas 2
apples 1
I have written a program which will show whether a word can be transformed into another by changing a single character at a time, while the intermediate words are also valid words.
For e.g CAT->COT -> DOT-> DOC
The program works when I use LinkedHashSet to represent the vertices
but it goes into an infinite loop or wrong answer when I use HashSet.
I would like to know what is the problem and if there is a better way to solve the problem then please tell me.
Here is the code: Split into 3 files:
Graph.java
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
public class Graph {
private Set<GraphNode> vertices;
public Graph() {
//the code runs when I use LinkedHashSet
vertices = new LinkedHashSet<>();
//the code goes into infinite loop or wrong answer when I use HashSet to represent the vertices
//************
//vertices = new HashSet<>();
//*************
//^^^^^ strange behaviour
}
/**
* adds all the words from the given dictonary to the graph
* #param dictonary
* #return
*/
public boolean addAll(Set<String> dictonary){
boolean result= false;
for (String word : dictonary){
addNode(word);
}
return result;
}
/**
* add a single node into the graph
* #param data
* #return
*/
public GraphNode addNode(String data){
GraphNode node = new GraphNode();
node.setValue(data);
vertices.add(node);
return node;
}
/**
* add a neighbour to the "source" node
* #param source
* #param neighbour
* #return
*/
public boolean addNeighbour(GraphNode source, GraphNode neighbour) {
boolean result = false;
source.getNeighbours().add(neighbour);
return result;
}
/**
* This method assigns the neighbours of nodes depending on whether they are one edit
* away or not
*/
public void assignNeighbours(){
ArrayList<GraphNode> listOfNodes = getAllVertices();
Set<String> usedWords = new HashSet<>();
for ( int i=0 ;i <listOfNodes.size() ;i++){
String currentWord = listOfNodes.get(i).value;
for (int j=0 ; j < listOfNodes.size() ;j++ ){
if (currentWord.equals(listOfNodes.get(j).value)==false){
if (oneEditAway(currentWord, listOfNodes.get(j).value) && usedWords.contains(listOfNodes.get(j).value)==false){
listOfNodes.get(i).neighbours.add(listOfNodes.get(j));
//reflective
listOfNodes.get(j).neighbours.add(listOfNodes.get(i));
usedWords.add(listOfNodes.get(j).value);
}
}
}
}
}
public ArrayList<GraphNode> getAllVertices(){
return new ArrayList<>(vertices);
}
/**
* This method determines whether 2 strings are one edit away or not
* #param first
* #param second
* #return
*/
public boolean oneEditAway(String first, String second) {
// TODO Auto-generated method stub
if (first == null || second == null)
return false;
if (Math.abs(first.length() - second.length())>1){
return false;
}else{
int firstLength = first.length();
int secondLength = second.length();
int mismatchCount = 0;
for (int i=0 ;i < firstLength && i < secondLength ; ++i){
if (first.charAt(i) != second.charAt(i)){
mismatchCount++;
}
}
if (mismatchCount > 1 || Math.abs(firstLength - secondLength) == 1){
return false;
}
return true;
}
}
/**
* This method prints the graph and the connections
*/
public void printGraph() {
// TODO Auto-generated method stub
for (GraphNode node :vertices){
System.out.println("Node is :"+node.value);
System.out.println("Neighbours are :");
for (GraphNode graphNode : node.getNeighbours()){
System.out.print(graphNode.value+ " ");
}
System.out.println();
}
}
/**
* This function determines whether a word can be transformed into an another or not
* #param source
* #param dest
* #return
*/
public boolean canTransform(String source, String dest) {
boolean result = false;
Set<GraphNode> visited = new HashSet<>();
//BFS is the way to go
Queue<GraphNode> allNodes = new LinkedList<>();
GraphNode root=null;
//find the source node in the graph
for (GraphNode node : vertices){
if (node.value.equals(source)){
root = node;
}
}
allNodes.add(root);
System.out.println("***************");
while(!allNodes.isEmpty()){
GraphNode currentNode = allNodes.poll();
System.out.println(currentNode.value);
visited.add(currentNode);
if (currentNode.value.equals(dest)){
result = true;
break;
}
for (GraphNode node: currentNode.getNeighbours()){
if (visited.contains(node) == false){
allNodes.add(node);
}
}
}
return result;
}
#Override
public String toString() {
return "Graph is as follows :\nvertices=" + vertices + "";
}
public Set<GraphNode> getVertices() {
return vertices;
}
public void setVertices(Set<GraphNode> vertices) {
this.vertices = vertices;
}
}
Here is the GraphNode.java
import java.util.HashSet;
import java.util.Set;
public class GraphNode {
String value;
Set<GraphNode> neighbours = new HashSet<GraphNode>();
public GraphNode() {
// TODO Auto-generated constructor stub
}
public GraphNode(String value) {
super();
this.value = value;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GraphNode other = (GraphNode) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
#Override
public String toString() {
return "GraphNode [value=" + value + ", neighbours=" + neighbours + "]";
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Set<GraphNode> getNeighbours() {
return neighbours;
}
public void setNeighbours(Set<GraphNode> neighbours) {
this.neighbours = neighbours;
}
}
Here is the driver class:
import java.util.HashSet;
import java.util.Set;
public class GraphMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
Graph graph = new Graph();
Set<String> dict = new HashSet<>();
dict.add("CAT");
dict.add("COT");
dict.add("DOT");
dict.add("DOG");
dict.add("DOC");
graph.addAll(dict);
graph.assignNeighbours();
graph.printGraph();
String source="CAT",dest = "DOC";
System.out.println("can transform from "+source+" to "+dest+" ??"+graph.canTransform(source,dest));
}
}
The method determining the neighbours of a word is incorrect as the use of the Set usedWords is incorrect. The relation neighbour(w1,w2) must be independent of the order the neighbours are determined, so using some state to decide whether one word is the neighbour of another one cannot be correct.
public void assignNeighbours(){
for ( GraphNode w1: vertices ){
for ( GraphNode w2: vertices ){
if (! w1.equals(w2) ){
if (oneEditAway(w1.getValue(), w2.getValue())){
w1.neighbours.add(w2);
//reflective
w2.neighbours.add(w1);
}
}
}
}
}