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.
Related
I have a class that do a tree from directory, subdirectory and files. And need to satisfy two conditions. Sort the contents in following way:
-Directories should go first.
-Directories and files are sorted in lexicographic order (case-insensitive).
I work on windows system and code below work fine, all is sorted how I want. Directories go first and are sorted in lexicographic order. But I read that on windows system is automatically sorted in lexicographic order. But this code doesn't work on Linux, the line children.sort(Comparator.comparing(file -> file.isDirectory() ? -1 : 1)); do not work and files\directory aren't sorted in lexicographic order (case-insensitive). How to solve problem with sort conditions on linux system? How can change sort conditions in code?
import static java.util.Comparator.comparing;
public class TreeNode<T> implements Iterable<TreeNode<T>> {
public T data;
public TreeNode<T> parent;
public List<TreeNode<T>> children;
public boolean isRoot() {
return parent == null;
}
private List<TreeNode<T>> elementsIndex;
public TreeNode(T data) {
this.data = data;
this.children = new LinkedList<TreeNode<T>>();
this.elementsIndex = new LinkedList<TreeNode<T>>();
this.elementsIndex.add(this);
}
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;
}
private void registerChildForSearch(TreeNode<T> node) {
elementsIndex.add(node);
if (parent != null)
parent.registerChildForSearch(node);
}
#Override
public String toString() {
return data != null ? data.toString() : "[data null]";
}
#Override
public Iterator<TreeNode<T>> iterator() {
TreeNode<T> iter = new TreeNode<T>((T) this);
return (Iterator<TreeNode<T>>) iter;
}
public static TreeNode<File> createDirTree(File folder) {
if (!folder.isDirectory()) {
throw new IllegalArgumentException("folder is not a Directory");
}
List<File> children = Arrays.asList(folder.listFiles());
children.sort(Comparator.comparing(file -> file.isDirectory() ? -1 : 1));
TreeNode<File> DirRoot = new TreeNode<File>(folder);
for (File file : children) {
if (file.isDirectory()) {
appendDirTree(file, DirRoot);
} else {
appendFile(file, DirRoot);
}
}
return DirRoot;
}
public static void appendDirTree(File folder, TreeNode<File> dirRoot) {
dirRoot.addChild(folder);
List<File> children = Arrays.asList(folder.listFiles());
children.sort(comparing(file -> file.isDirectory() ? -1 : 1));
for (File file : children) {
if (file.isDirectory()) {
appendDirTree(file, dirRoot.children.get(dirRoot.children.size() - 1));
} else {
appendFile(file, dirRoot.children.get(dirRoot.children.size() - 1));
}
}
}
public static void appendFile(File file, TreeNode<File> filenode) {
filenode.addChild(file);
}
public static String renderDirectoryTree(TreeNode<File> tree) {
List<StringBuilder> lines = renderDirectoryTreeLines(tree);
String newline = "\n";
StringBuilder sb = new StringBuilder(lines.size() * 20);
for (StringBuilder line : lines) {
sb.append(line);
sb.append(newline);
}
//System.out.println(sb);
return sb.toString();
}
public static List<StringBuilder> renderDirectoryTreeLines(TreeNode<File> tree) {
List<StringBuilder> result = new LinkedList<>();
result.add(new StringBuilder().append(tree.data.getName() + " " + calculateFileSize(tree) + " bytes"));
Iterator<TreeNode<File>> iterator = tree.children.iterator();
while (iterator.hasNext()) {
List<StringBuilder> subtree = renderDirectoryTreeLines(iterator.next());
if (iterator.hasNext()) {
addSubtree(result, subtree);
} else {
addLastSubtree(result, subtree);
}
}
return result;
}
private static void addSubtree(List<StringBuilder> result, List<StringBuilder> subtree) {
Iterator<StringBuilder> iterator = subtree.iterator();
result.add(iterator.next().insert(0, "├─ "));
while (iterator.hasNext()) {
result.add(iterator.next().insert(0, "│ "));
}
}
private static void addLastSubtree(List<StringBuilder> result, List<StringBuilder> subtree) {
Iterator<StringBuilder> iterator = subtree.iterator();
result.add(iterator.next().insert(0, "└─ "));
while (iterator.hasNext()) {
result.add(iterator.next().insert(0, " "));
}
}
public static long calculateFileSize(TreeNode<File> tree) {
long fileSize = 0;
if (tree.data.isDirectory()) {
List<TreeNode<File>> children = tree.children;
for (TreeNode<File> child : children) {
fileSize += calculateFileSize(child);
}
} else {
fileSize = tree.data.length();
}
return fileSize;
}
}
A short version could look something like this.
Comparator<File> lexicographicFileComparator = Comparator.comparing(File::isFile)
.thenComparing(Comparator.naturalOrder());
You've wrote that File.compareTo doesn't even check whether the file exists or not. I don't think it's the job of compareTo or Comparator to check if a file exists. Files that don't exist should be filtered before.
I think your example is overusing static methods. TreeNode should be an abstract class, while you have an implementation called FileTreeNode that replaces your static methods.
Here is an example
TreeNode
public abstract class TreeNode<N extends TreeNode<N, T>, T> implements Iterable<N> {
private static <N extends TreeNode<N, ?>> Stream<CharSequence> renderBranch(N node) {
Stream.Builder<CharSequence> result = Stream.builder();
result.add(node.printNode());
Iterator<N> iterator = node.getChildren().iterator();
while (iterator.hasNext()) {
Stream<CharSequence> subtree = renderBranch(iterator.next());
Iterator<CharSequence> subtreeIterator = subtree.iterator();
String branchSplit = "├─ ";
String branchSpacer = "│ ";
if (!iterator.hasNext()) {
branchSplit = "└─ ";
branchSpacer = " ";
}
result.add(branchSplit + subtreeIterator.next());
while (subtreeIterator.hasNext()) {
result.add(branchSpacer + subtreeIterator.next());
}
}
return result.build();
}
private final T data;
private final N parent;
private final List<N> children;
public TreeNode(T data) {
this(data, null);
}
protected TreeNode(T data, N parent) {
this.data = data;
this.parent = parent;
children = initChildren();
}
/**
* Called in constructor to initialize the children list.
*/
protected abstract List<N> initChildren();
/**
* Used to avoid unsafe casting.
*
* #return This
*/
protected abstract N instance();
/**
* TreeNode knows how to print the tree, but not how to print the current element. This way the child class can decide how it wants to be printed in the tree;
*
* #return readable text representation of node.
* #see TreeNode#renderBranch()
*/
protected abstract CharSequence printNode();
/**
* #return Returns a string representation of the entire branch starting at this node.
*/
public String renderBranch() {
Stream<CharSequence> lines = renderBranch(instance());
return lines.collect(Collectors.joining("\n"));
}
/**
* #return Returns a stream of the entire branch starting at this node
*/
public Stream<N> streamBranch() {
return Stream.concat(Stream.of(instance()), getChildren().stream().flatMap(TreeNode::streamBranch));
}
public T getData() {
return data;
}
public N getParent() {
return parent;
}
public List<N> getChildren() {
return children;
}
public boolean isRoot() {
return parent == null;
}
#Override
public String toString() {
return data != null ? data.toString() : "[data null]";
}
#Override
public Iterator<N> iterator() {
// No clue what you want to do here, but your method will not work.
return children.iterator();
}
}
FileTreeNode
public class FileTreeNode extends TreeNode<FileTreeNode, File> {
public FileTreeNode(File root) {
super(root);
}
protected FileTreeNode(File data, FileTreeNode parent) {
super(data, parent);
}
public long calculateFileSize() {
return streamBranch().mapToLong(value -> value.getData().length()).sum();
}
#Override
protected CharSequence printNode() {
return getData().getName() + " " + calculateFileSize() + " bytes";
}
#Override
protected List<FileTreeNode> initChildren() {
File file = getData();
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
return Arrays.stream(files)
.sorted(Comparator.comparing(File::isFile).thenComparing(Comparator.naturalOrder()))
.map(path -> new FileTreeNode(path, this))
.toList();
}
}
return Collections.emptyList();
}
#Override
protected FileTreeNode instance() {
return this;
}
}
Usage
File file = new File("C:\\dir");
FileTreeNode rootNode = new FileTreeNode(file);
System.out.println(rootNode.renderBranch());
This way you can easily implement a TreeNode structure for other classes too. For example File is outdated and replaced by Path so maybe you will want a PathTreeNode in the future. Who knows.
I'm trying to write a method to construct a binary search tree from a given ArrayList that could contain any type of comparable object T, using:
#SuppressWarnings("unchecked")
public boolean buildFromList(ArrayList<T> list) {
if (this != null) {
root = null;
}
for (T toInsert : list) {
if (this.find(toInsert) == true) {
return false;
}
this.insert(toInsert);
}
return true;
}
but when I try to pass it an ArrayList, I get an error stating that "cannot make a static reference to a non-static type T," even though it should accept any object that implements Comparable, which should be Integer, so what am I missing? The code that I'm using to create the ArrayList to pass it is:
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);
a.add(3);
a.add(2);
a.add(4);
a.add(-1);
System.out.println(buildFromList(a));
The full code is:
import java.util.ArrayList;
/**
* Binary Search Tree Class
*
* The head class for a binary search tree implementation.
*
* #author YOURID
* #param <Comparable> Type of data to store in the binary tree
*/
public class BinarySearchTree<T extends Comparable<T>> {
/**
* A reference pointer to the root of the tree
*/
private BinaryTreeNode<T> root;
private StringBuilder sb = new StringBuilder("");
/**
* Default constructor
*
* Creates a binary tree object with null root note (empty tree)
*/
public BinarySearchTree() {
this(null);
}
/**
* Constructor
*
* Creates a binary tree object with the given node as root
*
* #param newRoot The root of the tree
*/
public BinarySearchTree(BinaryTreeNode<T> newRoot) {
this.root = newRoot;
}
/**
* Get the root of the tree
*
* #return The root of the tree
*/
public BinaryTreeNode<T> getRoot() {
return root;
}
/**
* Set the root of the tree
*
* #param root The new root of this tree
*/
public void setRoot(BinaryTreeNode<T> root) {
this.root = root;
}
/**
* Returns the size of the tree (that is, the
* number of nodes in the tree).
*
*/
public int size() {
if (this.root != null) {
return root.size();
}
return 0;
}
/**
* Returns the height of the tree.
*
*/
public int height() {
if (root != null) {
return root.height();
}
return 0;
}
/**
* Find if an element exists
*
* Checks to see if the value val appears in the
* tree (recursively). Returns true if it appears
* and false otherwise.
*
* #param val The value to find
* #return True if the tree contains the value, false otherwise
*/
public boolean find(T val) {
return findHelper(root, val);
}
private boolean findHelper(BinaryTreeNode<T> current, T value) {
if (current == null) {
return false;
}
if (value.compareTo(current.getData()) == 0) {
return true;
}
return value.compareTo(current.getData()) < 0
? findHelper(current.getLeft(), value)
: findHelper(current.getRight(), value);
}
/**
* Insert an element
*
* Inserts val into the tree where it should appear, returning
* true on success and false otherwise
*
* #param val The value to insert
* #return True on success, false otherwise
*/
#SuppressWarnings("unchecked")
public boolean insert(T val) {
root = insertNode(root, new BinaryTreeNode<T>(val));
return this.find(val);
}
// private recursive call
#SuppressWarnings({ "rawtypes", "unchecked" })
private BinaryTreeNode insertNode(BinaryTreeNode currentParent, BinaryTreeNode newNode) {
if (currentParent == null) {
return newNode;
} else if (newNode.getData().compareTo(currentParent.getData()) > 0) {
currentParent.setRight(insertNode(currentParent.getRight(), newNode));
} else if (newNode.getData().compareTo(currentParent.getData()) < 0) {
currentParent.setLeft(insertNode(currentParent.getLeft(), newNode));
}
return currentParent;
}
/**
* Return a string that represents the data held at each
* node following the rules of an in-order traversal.
*
* Covered in class Wednesday, April 22
*/
public String inOrder() {
sb.setLength(0);
return outputInOrder(root);
}
public String outputInOrder(BinaryTreeNode<T> node) {
if (node != null) {
if (node.getLeft() != null) {
outputInOrder(node.getLeft());
}
sb.append("(" + node.getData() + ")");
if (node.getRight() != null) {
outputInOrder(node.getRight());
}
return sb.toString();
}
return "";
}
/**
* Return a string that represents the data held at each
* node following the rules of a post-order traversal.
*
* Covered in class Wednesday, April 22
*/
public String postOrder() {
sb.setLength(0);
return outputPostOrder(root);
}
public String outputPostOrder(BinaryTreeNode<T> node) {
if (node != null) {
outputPostOrder(node.getLeft());
outputPostOrder(node.getRight());
sb.append("(" + node.getData() + ")");
return sb.toString();
}
return "";
}
/**
* Build from a list
*
* Build the tree from the given list, overwriting any tree data
* previously stored in this tree. Should read from beginning to
* end of the list and repeatedly call insert() to build the tree
*
* If the tree is not empty when this method is called, you should
* empty the tree before adding any elements in list.
*
* #param list The list from which to build the tree
* #return True if successfully built, false otherwise
*/
public boolean buildFromList(ArrayList<T> list) {
if (this != null) {
root = null;
/**root.setLeft(null);
root.setRight(null);*/
}
for (T toInsert : list) {
if (this.find(toInsert) == true) {
return false;
}
this.insert(toInsert);
}
return true;
}
#SuppressWarnings("unchecked")
public boolean buildFromList(ArrayList<T> list) {
if (this != null) {
root = null;
}
for (T toInsert : list) {
if (this.find(toInsert) == true) {
return false;
}
this.insert(toInsert);
}
return true;
}
/**
* toString method
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return inOrder();
}
/**
* Main method
*
* For testing, etc
*
* #param args Command line arguments
*/
public static void main(String[] args) {
BinarySearchTree<Integer> tree = new BinarySearchTree<Integer>();
BinaryTreeNode<Integer> n1 = new BinaryTreeNode<Integer>();
n1.setData(0);
BinaryTreeNode<Integer> n2 = new BinaryTreeNode<Integer>();
n2.setData(1);
BinaryTreeNode<Integer> n3 = new BinaryTreeNode<Integer>();
n3.setData(-1);
BinaryTreeNode<Integer> n4 = new BinaryTreeNode<Integer>();
n4.setData(2);
BinaryTreeNode<Integer> n5 = new BinaryTreeNode<Integer>();
n5.setData(-2);
BinaryTreeNode<Integer> n6 = new BinaryTreeNode<Integer>();
n6.setData(4);
BinaryTreeNode<Integer> n7 = new BinaryTreeNode<Integer>();
n7.setData(-6);
tree.insert(n1.getData());
tree.insert(n2.getData());
tree.insert(n3.getData());
tree.insert(n4.getData());
tree.insert(n5.getData());
tree.insert(n6.getData());
tree.insert(n7.getData());
System.out.println(tree.toString());
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);
a.add(3);
a.add(2);
a.add(4);
a.add(-1);
System.out.println(buildFromList(a));
}
}
and I'm almost entirely certain every other part of the code compiles and runs completely fine
Have you tried to make T extend Comparable ?
Haven´t worked with Java for quite a time and don´t have an IDE here right now but I´d give it a try.
Like public boolean buildFromList(ArrayList<T extends Comparable> list) {
I'm tasked to implement a remove() method for my Sorted Binary Tree. I need to pass a set of tests which was assigned by our teacher, and I'm struggling to do so. This is the code I have currently, which was heavily borrowed from our schoolbook.
#Override
#SuppressWarnings("unchecked")
public V remove(Object key) throws NoSuchElementException {
if(!containsKey((K) key)){
throw new NoSuchElementException();
}
ReturnObject oldEntry = new ReturnObject(null);
SortedTreeMap<K, V> newRoot = removeEntry(getRoot(this), (K) key, oldEntry);
if(newRoot != null){
setRoot(newRoot.data);
setLeftChild(newRoot.leftChild);
setRightChild(newRoot.rightChild);
} else{
this.data = null;
}
if(oldEntry.get() != null){
size--;
}
return oldEntry.get();
}
/*
* Removes the entry in a given root node of a subtree.
* rootNode is the root node of the subtree.
* Returns the root node of the revised subtree.
*
* */
private SortedTreeMap<K,V> removeFromRoot(SortedTreeMap<K, V> rootNode){
if(rootNode.hasLeftChild() && rootNode.hasRightChild()){
SortedTreeMap<K,V> leftSubtreeRoot = rootNode.getLeftChild();
SortedTreeMap<K,V> largestNode = findLargest(leftSubtreeRoot);
rootNode.setRoot(largestNode.getRoot());
rootNode.setLeftChild(removeLargest(leftSubtreeRoot));
} else if(rootNode.hasRightChild()) {
rootNode = rootNode.getRightChild();
} else{
rootNode = rootNode.getLeftChild();
}
return rootNode;
}
/*
* Finds the node containing the largest entry in a given tree.
* rootNode is the root node of the tree.
* Returns the node containing the largest entry in the tree.
*
* */
private SortedTreeMap<K,V> findLargest(SortedTreeMap<K, V> rootNode){
if(rootNode.hasRightChild()){
rootNode = findLargest(rootNode.getRightChild());
}
return rootNode;
}
/*
* Removes the node containing the largest entry in a given tree.
* rootNode is the root node of the tree.
* Returns the root node of the revised tree.
*
* */
private SortedTreeMap<K,V> removeLargest(SortedTreeMap<K, V> rootNode){
if(rootNode.hasRightChild()){
SortedTreeMap<K,V> rightEntry = rootNode.getRightChild();
rightEntry = removeLargest(rightEntry);
rootNode.setRightChild(rightEntry);
} else{
rootNode = rootNode.getLeftChild();
}
return rootNode;
}
/*
* Removes an entry from the tree rooted at a given node.
* rootNode is a reference to the root of a tree.
* entry is the object to be removed.
* oldEntry is an object whose data field is null
* Returns the root node of the resulting tree; if entry matches
* an entry in the tree, oldEntry's data field is the entry
* that was removed from the tree; otherwise it is null.
* */
private SortedTreeMap<K,V> removeEntry(SortedTreeMap<K,V> rootNode, K entry, ReturnObject oldEntry){
if(rootNode != null){
K rootData = rootNode.data.key;
int comparison = entry.compareTo(rootData);
if(comparison == 0){
oldEntry.set(rootNode.data.value);
rootNode = removeFromRoot(rootNode);
} else if(comparison < 0){
SortedTreeMap<K,V> leftEntry = rootNode.getLeftChild();
SortedTreeMap<K,V> subtreeRoot = removeEntry(leftEntry, entry, oldEntry);
rootNode.setLeftChild(subtreeRoot);
} else{
SortedTreeMap<K,V> rightEntry = rootNode.getRightChild();
rootNode.setRightChild(removeEntry(rightEntry, entry, oldEntry));
}
}
return rootNode;
}
And this is the test I'm struggling to pass:
/**
* Check that entry is no longer in map after remove
*/
public Property remove_removes_entry() {
return property(isKVList,
kvs -> implies(kvs.length() > 0,
() -> property(choose(0, kvs.length()-1),
i -> {
P2<Integer, String> entry = kvs.index(i);
SortedTreeMap<Integer, String> tm = new SortedTreeMap<>(intOrd.toComparator());
kvs.foreachDoEffect(kv -> tm.add(kv._1(), kv._2()));
tm.remove(entry._1());
List<Integer> keys = fromIterator(tm.keys().iterator());
return prop(!keys.exists(key -> key.equals(entry._1())));
})
)
);
}
The error message I'm getting is this:
java.lang.Error: Falsified after 2 passed tests with arguments:
List(List((0,gzprxt),(4,lntpqj),(-5,caki),(-6,jzf)),2)
I can get in between 0 to 60 passes and I don't get which scenario the remove method fails in. I've tried to make a Junit test, but didn't succeed.
Here is some more context for my class:
public class Entry<K, V> {
public final K key;
public final V value;
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
#Override
public boolean equals(Object o) {
if (o instanceof Entry) {
Entry other = (Entry)o;
return this.key.equals(other.key) && this.value.equals(other.value);
}
return false;
}
}
public class SortedTreeMap<K extends Comparable<? super K>, V> implements ISortedTreeMap<K, V> {
private int size;
private Entry<K,V> data;
private SortedTreeMap<K,V> leftChild, rightChild, parent;
private Comparator<K> keyComparator;
private SortedTreeMap(K key, V value, Comparator<K> keyComparator, SortedTreeMap<K, V> parent){
data = new Entry<>(key, value);
this.parent = parent;
this.keyComparator = keyComparator;
}
public SortedTreeMap(Comparator<K> kComparator) {
keyComparator = kComparator;
}
private Entry<K,V> getRoot(){
return this.data;
}
private SortedTreeMap<K,V> getLeftChild(){
return this.leftChild;
}
private SortedTreeMap<K,V> getRightChild(){
return this.rightChild;
}
private void setLeftChild(SortedTreeMap<K, V> newLeftChild){
leftChild = newLeftChild;
}
private void setRightChild(SortedTreeMap<K, V> newRightChild){
rightChild = newRightChild;
}
private void setRoot(Entry<K, V> newRoot){
data = newRoot;
}
private boolean hasLeftChild(){
return leftChild != null;
}
private boolean hasRightChild(){
return rightChild != null;
}
#Override
public V add(K key, V value) {
V result = null;
if(isEmpty()) {
data = new Entry<>(key, value);
} else{
int comparison = keyComparator.compare(key, data.key);
SortedTreeMap<K,V> newChild = new SortedTreeMap<>(key, value, keyComparator, this);
if(comparison < 0){
if (hasLeftChild()) {
result = leftChild.add(key, value);
} else{
setLeftChild(newChild);
}
} else if(comparison > 0){
if (hasRightChild()) {
result = rightChild.add(key, value);
} else{
setRightChild(newChild);
}
} else{
result = data.value;
this.data = new Entry<>(key, value);
}
}
if (result == null){
size++;
}
return result;
}
#Override
public Iterable<K> keys() {
return new KeyIterator(this);
}
public class KeyIterator implements Iterable<K>, Iterator<K>{
private SortedTreeMap<K,V> next;
KeyIterator(SortedTreeMap<K, V> root){
next = root;
while(next.leftChild != null){
next = next.leftChild;
}
}
#Override
public Iterator<K> iterator() {
return this;
}
public boolean hasNext(){
return next != null && !next.isEmpty();
}
public K next(){
if(!hasNext()){
throw new NoSuchElementException();
}
SortedTreeMap<K,V> r = next;
if(next.rightChild != null){
next = next.rightChild;
while(next.leftChild != null){
next = next.leftChild;
}
return r.data.key;
}
while(true){
if(next.parent == null){
next = null;
return r.data.key;
}
if(next.parent.leftChild == next){
next = next.parent;
return r.data.key;
}
next = next.parent;
}
}
}
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();
}
}
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.