I have a superclass called Tree and a subclass called AVLTree that extends the class Tree.
A tree has children that are also Tree typed. An AVLTree has children that are AVLTree. I want to use the methods i wrote on the Tree class, on this case the getLeft(returns the left son) and setLeft(set the left son).
The problem is the compiler can't convert a Tree to an AVLTree, even though they have the same variables, structure and constructors.
Any ideas on how should I solve this? Or should I just write all the methods that just an AVLTree has on the Tree class?
The code:
Tree.java:
public class Tree<T extends Tree<T>> {
private T left = null;
private T right = null;
private Object data = null;
public Tree () {
//nothing
}
public Tree (Object data, T left, T right) {
this.data = data;
this.left = left;
this.right = right;
}
public Tree (Object data) {
this.data = data;
}
//Get Values
public T getLeft() {
return this.left;
}
public T getRight() {
return this.right;
}
public Object getData() {
return this.data;
}
//Set Values
public void setLeft(T left) {
this.left = left;
}
public void setRight(T right) {
this.right = right;
}
public void setData(Object data) {
this.data = data;
}
public T treeFromText(String in) {
if (in=="()") return null;
int i=0;
T result = null;
//Find expression
int d = in.indexOf('c')+1;
if (d==0) return null;
int begl, endl, begr, endr;
begl = d+1;
endl = ClosingParentesis(in,begl);
endr = in.length()-2;
begr = OpeningParentesis(in,endr);
T left = null, right = null;
if (begl-endl==0) {
left = null;
} else left = treeFromText(in.substring(begl,endl+1));
if (begr-endr==0) {
right = null;
} else right = treeFromText(in.substring(begr,endr+1));
result.setData(in.charAt(d));
result.setLeft(left);
result.setRight(right);
return result;
}
public static int ClosingParentesis(String in, int openPos) {
int closePos = openPos;
int counter = 1;
while (counter > 0 && closePos < in.length()-1) {
closePos++;
if (in.charAt(closePos)=='(') counter++;
if (in.charAt(closePos)==')') counter--;
}
return closePos;
}
public static int OpeningParentesis(String in, int closePos) {
int openPos = closePos;
int counter = 1;
while (counter > 0 && openPos > 0) {
openPos--;
if (in.charAt(openPos)=='(') counter--;
if (in.charAt(openPos)==')') counter++;
}
return openPos;
}
AVLTree.java:
public class AVLTree extends Tree<AVLTree> {
/*
//Values and Variables
private AVLTree left = null;
private AVLTree right = null;
private Object data;
//Inicialization
public AVLTree (Object data, AVLTree left, AVLTree right) {
super(data,left,right);
}
public AVLTree (Object data) {
super(data);
}
*/
public int getfactor() {
return getHeight(this.getLeft())-getHeight(this.getRight());
}
}
Test.java:
public static void main(String[] args) {
AVLTree tree = new AVLTree();
Scanner console = new Scanner(System.in);
String in = console.nextLine().toLowerCase();
tree = (AVLTree) tree.treeFromText(in); //The error is here.
System.out.println(tree.getHeight());
System.out.println(tree.TreePreOrder());
}
The way I expect it to work is that if the String 'in' in the Test.java is "(c3()(c2()()))" the return must be an Tree with value 3 and a right son with value 2. This return must be of type Tree or anything that extends Tree.
You need a way to get an AVLTree instantiated from a String, using the logic in Tree.treeFromText.
Declare Tree as abstract.
Create a new method in Tree:
abstract protected T createEmptyTree();
Override that method in AVLTree to return an empty instance of AVLTree.
#Override
protected AVLTree createEmptyTree() {
return new AVLTree();
}
In treeFromText(), wherever you need to create an empty instance of T, invoke createEmptyTree().
You already have the rest of the logic.
Try to avoid returning null anywhere. It's best to return an empty AVLTree instead of a null.
You can achieve this by the power of generics: define a new circular generic T:
public class Tree<T extends Tree<T>>
{
T left;
T right;
public T doSomething()
{
return left;
}
public static class AVLTree extends Tree<AVLTree>
{
public AVLTree foo()
{
return doSomething();
}
}
}
UPDATE: here is how you can create different tree instances:
import java.util.Objects;
public class TreesFactory
{
public static AVLTree createAVLTreeFrom(String in)
{
return treeFromText(in, AVLTree::new);
}
#FunctionalInterface
interface SimpleFactory<T extends Tree<T>>
{
T createNew();
}
public static <T extends Tree<T>> T treeFromText(String in, SimpleFactory<T> treeFactory)
{
if (Objects.equals(in, "()"))
return null;
T result = treeFactory.createNew();
//Find expression
int d = in.indexOf('c') + 1;
if (d == 0)
return null;
int begl, endl, begr, endr;
begl = d + 1;
endl = ClosingParentesis(in, begl);
endr = in.length() - 2;
begr = OpeningParentesis(in, endr);
T left, right;
if (begl - endl == 0)
{
left = null;
}
else
left = treeFromText(in.substring(begl, endl + 1), treeFactory);
if (begr - endr == 0)
{
right = null;
}
else
right = treeFromText(in.substring(begr, endr + 1), treeFactory);
result.setData(in.charAt(d));
result.setLeft(left);
result.setRight(right);
return result;
}
public static int ClosingParentesis(String in, int openPos)
{
int closePos = openPos;
int counter = 1;
while (counter > 0 && closePos < in.length() - 1)
{
closePos++;
if (in.charAt(closePos) == '(')
counter++;
if (in.charAt(closePos) == ')')
counter--;
}
return closePos;
}
public static int OpeningParentesis(String in, int closePos)
{
int openPos = closePos;
int counter = 1;
while (counter > 0 && openPos > 0)
{
openPos--;
if (in.charAt(openPos) == '(')
counter--;
if (in.charAt(openPos) == ')')
counter++;
}
return openPos;
}
}
And the Main:
public static void main(String[] args)
{
Scanner console = new Scanner(System.in);
String in = console.nextLine().toLowerCase();
AVLTree tree = TreesFactory.createAVLTreeFrom(in);
//...
}
Related
Hi,
Update: Thanks for all your suggestion
assuming that, this exercise it's like a rebus,
I have a list of numbers made with the concept of Cons and Nil,
List l = new Cons(**3**, new Cons(**2**,new Cons(**1**, new
Cons(**4**, new Cons(**1**, new Nil())))));
and I want to count how many of them are immediately followed by a lower number, recursively.
For example
[5,0,5,3].count() == 2, [5,5,0].count() == 1
The count() method is made by me (it cannot have any parameters), the rest is default, and I can't make and other method or use already defined one's like add(),size()...
The "NEXT" must have the next value after the current elem but I can't get a solution.
Any solutions are welcome.
abstract class List {
public abstract boolean empty();
public abstract int first();
public abstract int count();
}
class Cons extends List {
private int elem;
private List next;
public Cons(int elem, List next) {
this.elem = elem;
this.next = next;
}
public boolean empty(){
return false;
}
public int first(){
return elem;
}
#Override
public int count() {
if(elem>NEXT) {
return 1 + next.count();
}else {
return next.count();
}
}
```![enter image description here](https://i.stack.imgur.com/kWo0v.jpg)
The following code will create a recursive list with N elements with N value being defined by the size of the amount of elements found in the int array called elements in RecursiveList class. Call the startRecursion() method to create a recursive list with the defined elements and call count() to get the amount of elements in the array that are immediately followed by a lower number.
Main Class
This your application entry point:
public static void main(String[] args) {
int count = RecursiveList.startRecursion().count();
System.out.printf("List has %d recursive elements", count);
}
RecursiveList Class
abstract class RecursiveList {
protected static int index = -1;
protected static int[] elements = new int[]{ 5,2,1,4,3,2,6 };
public static RecursiveList startRecursion() {
return new Cons();
}
public abstract boolean empty();
public abstract int count();
public abstract Integer getElement();
public static int incIndex() {
return index += 1;
}
}
Cons Class
public class Cons extends RecursiveList {
private static int result;
private final Integer elem;
private final RecursiveList prev;
private final RecursiveList next;
private Cons(Cons parent) {
prev = parent;
elem = incIndex() < elements.length ? elements[index] : null;
System.out.printf("Creating new Cons with element %d(%d)%n", elem, index);
next = elem != null ? new Cons(this) : null;
}
Cons() {
this(null);
}
public boolean empty() {
return false;
}
#Override
public /*#Nullable*/ Integer getElement() {
return elem;
}
#Override
public int count() {
if (elem != null)
{
if (prev != null && elem < prev.getElement())
result += 1;
if (next != null) {
return next.count();
}
}
return result;
}
}
EDIT
Alright here is the answer you were actually looking for. This completely conforms to the limitations imposed on this exercise that you provided. The solution uses pure Java, neither the class nor any of it's method or field declarations were modified in any way and no such new elements were added. I've only added the implementation where the exercise said you should.
Main Class
public static void main(String[] args) {
List l = new Cons(3, new Cons(2,new Cons(1, new
Cons(4, new Cons(1, new Nil())))));
assert l.count() == 3;
l = new Cons(5, new Nil());
assert l.count() == 0;
l = new Cons(5, new Cons(5, new Cons(0, new Nil())));
assert l.count() == 1;
l = new Cons(5, new Cons(0, new Cons(5, new Cons(3, new Nil()))));
assert l.count() == 2;
System.out.println("All tests completed successfully!");
}
Cons Class
import java.util.NoSuchElementException;
public class Cons extends List {
private int elem;
private List next;
public Cons(int elem, List next) {
this.elem = elem;
this.next = next;
}
public boolean empty()
{ return false; }
public int first()
{ return elem; }
public int count()
{
try {
if (first() > next.first()) {
return 1 + next.count();
}
else return next.count();
}
catch (NoSuchElementException e) {
return 0;
}
}
}
Nil Class
import java.util.NoSuchElementException;
public class Nil extends List {
public boolean empty()
{ return true; }
public int first()
{ throw new NoSuchElementException(); }
public int count()
{
throw new IllegalAccessError();
}
}
public int NEXT(){
if(next!=null)
return next.first()
else
throw new Exception("No next element")
}
how can i send (node.data) from SortTree Class to TreePrinter then used to print A Tree .
import javax.swing.tree.TreeNode;
public class SortTree {
static Node root;
TreePrinter type =new TreePrinter();
class Node<A extends Comparable>{
int data;
Node left, right;
Node(int d) {
data = d;
left = null;
right = null;
}
}
Node sortedArrayToBST(int arr[], int start, int end) {
if (start > end) {
return null;
}
int mid = (start + end) / 2;
Node node = new Node(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid - 1);
node.right = sortedArrayToBST(arr, mid + 1, end);
return node;
}
void preOrder(Node node) {
if (node == null) {
return;
}
//System.out.print(node.data + " ");
preOrder(node.left);
preOrder(node.right);
}
}
And this is TreePrinter class :
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TreePrinter {
public static class Node<T extends Comparable<T>> {
T value;
Node<T> left, right;
public void insertToTree(T v) {
if (value == null) {
value = v;
return;
}
if (v.compareTo(value) < 0) {
if (left == null) {
left = new Node<T>();
}
left.insertToTree(v);
} else {
if (right == null) {
right = new Node<T>();
}
right.insertToTree(v);
}
}
public void printTree(OutputStreamWriter out) throws IOException {
if (right != null) {
right.printTree(out, true, "");
}
printNodeValue(out);
if (left != null) {
left.printTree(out, false, "");
}
}
private void printNodeValue(OutputStreamWriter out) throws IOException {
if (value == null) {
out.write("<null>");
} else {
out.write(value.toString());
}
out.write('\n');
}
private void printTree(OutputStreamWriter out, boolean isRight, String indent) throws IOException {
if (right != null) {
right.printTree(out, true, indent + (isRight ? " " : " | "));
}
out.write(indent);
if (isRight) {
out.write("┌");
} else {
out.write("└");
}
out.write("────");
printNodeValue(out);
if (left != null) {
left.printTree(out, false, indent + (isRight ? " | " : " "));
}
}}}
nodes sorted as preorder any help to send (node.data) to treeprinter class then type the tree:
I recommend you implement a toString, rather than this TreePrinter.
I've slightly changed your Node class, moved it outside the SortTree, resulting in the code available from https://github.com/johanwitters/stackoverflow-tree-printer.
The implementation of Node is here:
package com.johanw.stackoverflow.tree;
import com.johanw.stackoverflow.util.Helper;
public class Node<A extends Comparable>{
private static int AMOUNT_INDENT = 3;
private int data;
private Node left, right;
public Node(int d) {
data = d;
left = null;
right = null;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
public int getData() {
return data;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public void indent(StringBuilder builder, int indent) {
builder.append(Helper.repeat(indent * (AMOUNT_INDENT + 1), " "));
}
public void newLine(StringBuilder builder) {
builder.append(System.lineSeparator());
}
public String toString(int indent) {
StringBuilder builder = new StringBuilder();
builder.append(data);
newLine(builder);
if (left != null) {
indent(builder, indent);
builder.append("└" + Helper.repeat(AMOUNT_INDENT, "─") + left.toString(indent + 1));
}
if (right != null) {
indent(builder, indent);
builder.append("└" + Helper.repeat(AMOUNT_INDENT, "─") + right.toString(indent + 1));
}
return builder.toString();
}
#Override
public String toString() {
return toString(0);
}
}
The below unit test gives the bottom output for the given tree structure:
public class TestSortTree {
#Test
public void test() {
Node node = new Node(1);
Node left = new Node(2);
Node leftLeft = new Node(22);
Node leftRight = new Node(23);
Node leftRightLeft = new Node(24);
left.setLeft(leftLeft);
leftRight.setLeft(new Node(39));
left.setRight(leftRight);
node.setLeft(left);
node.setRight(new Node(3));
System.out.println(node.toString());
}
}
I hope this helps
In order to be able to receive the node.data in TreePrinter. I would add the following code
class TreePrinter<T extends Comparable<T>>{
Node<T extends Comparable<T>> root;
public TreePrinter(){
root = new Node<T extends Comparable<T>>();
}
public void insertToTree(T v) {
root.insertToTree(v);
}
It will now be easy printing the tree using the algorithm from this post:
How to print binary tree diagram?
I would send the data by making the following modification to Node sortedArrayToBST(int arr[], int start, int end) in SortTree
void sortedArrayToBST(int arr[], int start, int end) {
if (start > end) {
return;
}
int mid = (start + end) / 2;
type.insertToTree(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid - 1);
node.right = sortedArrayToBST(arr, mid + 1, end);
}
I have not tried running this so might need some debugging, but I think the underlying idea is solid. Hope this helps!
it's my first time ever posting on StackOverFlow, because I'm truly desperate right now. I couldn't find an answer for my problem anywhere, so long story short, I have some kind of project for my Data Structures course. The project had 2 parts. The first part was implementing a Sorted Array Bag/ Sorted Collection for some problem. We are using java.
The second part is where I do actually have a lot of problems. So the main idea is implementing a doubly-linked list from the sorted-array bag/ sorted collection and in a way that I would just switch sorted array bag with doubly-linked list in my main and everything should work the way it was working before.
The main thing about the SortedArrayBag is as far as I understand using a Comparator when you declare the SortedArrayBag in your main, and it looks like this:
SortedBag<Grupe> al = new SortedArrayBag<>(new ComparatorVot());
al.add(new Grupe("gr1", 5));
al.add(new Grupe("gr2", 7));
The sorted collection/sorted array bag was implemented by my teacher because there is no such data structure in Java, here is her implementation:
public class SortedArrayBag<T> implements SortedBag<T> {
private ArrayList<T> elemente;
private Comparator<T> relatie;
public SortedArrayBag(Comparator<T> rel) {
this.elemente = new ArrayList<>();
this.relatie = rel;
}
public void add(T elem) {
int index = 0;
boolean added = false;
while (index < this.elemente.size() && added == false) {
T currentElem = this.elemente.get(index);
if (relatie.compare(currentElem, elem) < 0) {
index++;
} else {
this.elemente.add(index, elem);
added = true;
}
}
if (!added) {
this.elemente.add(elem);
}
}
public void remove(T elem) {
boolean removed = this.elemente.remove(elem);
}
public int size() {
return this.elemente.size();
}
public boolean search(T elem) {
return this.elemente.contains(elem);
}
public Iterator<T> iterator() {
return this.elemente.iterator();
}
}
And the SortedBag interface looks like this
public interface SortedBag<T> {
public void add(T elem);
public void remove(T elem);
public int size();
public boolean search(T elem);
public Iterator<T> iterator();
}
Also in case it helps, the comparator looks like this:
public class ComparatorVot implements Comparator<Grupe> {
public int compare(Grupe o1, Grupe o2) {
Grupe gr1 = (Grupe) o1;
Grupe gr2 = (Grupe) o2;
if (gr1.getNrPersoane() / 2 + 1 == gr2.getNrPersoane() / 2 + 1) {
return 0;
} else if (gr1.getNrPersoane() / 2 + 1 > gr2.getNrPersoane() / 2 + 1) {
return 1;
} else {
return -1;
}
}
}
So, I tried my best implementing doublyLinkedList using a SortedArrayBag, this is what I did, also if it helps making my code more clear, prim=first, ultim=last, urmator=next, anterior=previous
import java.util.Iterator;
public class LDI {
private Nod prim;
private Nod ultim;
//private int lungime;
public LDI() {
this.prim = null;
this.ultim = null;
//this.lungime = 0;
}
public class Nod {
private int elem;
private int frecventa;
private Nod urmator;
private Nod anterior;
public Nod(int e, int f) {
this.elem = e;
this.frecventa = f;
this.urmator = null;
this.anterior = null;
}
}
public void add(int elem, int frecventa) {
Nod nodNou = new Nod(elem, frecventa);
nodNou.elem = elem;
nodNou.frecventa = frecventa;
if (prim == null) {
this.prim = nodNou;
this.ultim = nodNou;
} else if (frecventa <= prim.frecventa) {
nodNou.urmator = prim;
this.prim.anterior = nodNou;
this.prim = nodNou;
} else if (frecventa >= prim.frecventa) {
nodNou.anterior = prim;
for (; nodNou.anterior.urmator != null; nodNou.anterior = nodNou.anterior.urmator) {
if (nodNou.anterior.urmator.frecventa > frecventa)
break;
}
nodNou.urmator = nodNou.anterior.urmator;
if (nodNou.anterior.urmator != null) {
nodNou.anterior.urmator.anterior = nodNou;
}
nodNou.anterior.urmator = nodNou;
nodNou.anterior = nodNou.anterior;
}
}
public void remove() {
if (this.prim != null) {
if (this.prim == this.ultim) {
this.prim = null;
this.ultim = null;
} else
this.prim = this.prim.urmator;
this.prim.anterior = null;
}
}
public int size() {
int count = 0;
for (Nod nodNou = prim; nodNou != null; nodNou = nodNou.urmator)
count++;
return count;
}
public class MyIterator {
private Nod curent;
public MyIterator() {
this.curent = prim;
}
public void urmator() {
this.curent = this.curent.urmator;
}
public int getElem() {
return this.curent.elem;
}
public boolean valid() {
if (this.curent != null) {
return true;
} else {
return false;
}
}
}
public Iterator iterator() {
return new MyIterator();
}
}
The thing is, it doesn't work, I have no idea how to make my data structure able to receive the Comparator I used and also the Iterator doesn't work. If you have any idea how to make this work, please do help me.
I'm working on a school assignment about creating a balanced binary tree. Interfaces for the Node and the Tree were supplied with declared methods. However, the Node interface had only getLeft, getRight and getValue methods, no setters. Since we submit for grading only the implementation files, I worked around it by using the implementation class itself for typing, instead of the Interface.
When I messaged the teacher, he told me it was possible to implement it using merely the Node constructor, adding a "hint" that "For every node, its child are also trees." which is obvious, but I'm not sure how that is to help me.
It seems to me that without using setters, I'd first need to basically map out the tree in advance and then start building it from bottom instead of from top, which seems needlessly complicated and counter-intuitive. Is there some trick I'm missing?
Thank you for any help or advice you can offer.
My current implementations are as follows:
TreeImpl.java
public class TreeImpl implements Tree {
private NodeImpl root;
public TreeImpl() {}
#Override
public void setTree(int[] values) {
this.root = null;
Arrays.sort(values);
recurseSet(values);
}
private void recurseSet(int[] values) {
if (values.length > 0) {
int middleIndex = values.length / 2;
NodeImpl tempNode = new NodeImpl(values[middleIndex]);
insert(tempNode, root, 1);
recurseSet(cutArray(values, 0, middleIndex - 1));
recurseSet(cutArray(values, middleIndex+1, values.length-1));
}
}
private int[] cutArray(int[] array, int begin, int end) {
int length = end-begin+1;
int[] newArray = new int[length];
System.arraycopy(array, begin, newArray, 0, length);
return newArray;
}
private void insert(NodeImpl node, NodeImpl location, int depth) {
if (root == null) {
root = node;
return;
}
if (node.getValue() < location.getValue()) {
/* left branch */
if(location.getLeft() == null) {
node.setDepth(depth);
location.setLeft(node);
} else {
insert(node, location.getLeft(), depth+1);
}
} else {
/* right branch */
if(location.getRight() == null) {
node.setDepth(depth);
location.setRight(node);
} else {
insert(node, location.getRight(), depth+1);
}
}
}
#Override
public Node getRoot() {
return root;
}
private String toString(NodeImpl root) {
String finalString = "";
if (root != null) {
finalString += root;
finalString += toString(root.getLeft());
finalString += toString(root.getRight());
}
return finalString;
}
#Override
public String toString() {
return toString(root);
}
}
NodeImpl.java
public class NodeImpl implements Node {
private int value;
private NodeImpl left;
private NodeImpl right;
private int depth = 0;
public NodeImpl(int value) {
this.value = value;
}
public void setLeft(NodeImpl left) {
this.left = left;
}
public void setRight(NodeImpl right) {
this.right = right;
}
public void setDepth(int depth) {
this.depth = depth;
}
#Override
public NodeImpl getLeft() {
return left;
}
#Override
public NodeImpl getRight() {
return right;
}
#Override
public int getValue() {
try {
return value;
} catch (NullPointerException e) {
System.out.println("Null pointer.");
}
return 0;
}
#Override
public String toString() {
String finalString = "";
for(int i = 0; i < depth; i++) {
finalString += " ";
}
finalString += "- ";
finalString += value;
finalString += "\n";
return finalString;
}
}
I played with your code a little bit and I think I've figured out how to do that:
class NodeImpl implements Node {
private int value;
private Node left;
private Node right;
public NodeImpl(int value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public int getValue() {
return value;
}
#Override
public String toString() {
// here you have to put some nice drawing logic.
return (left != null ? left.toString() : "") + "<-" + value + "->" + (right != null ? right.toString() : "");
}
}
class TreeImpl implements Tree {
private Node root;
public void setTree(int[] values) {
Arrays.sort(values);
this.root = recurseSet(values);
}
private Node recurseSet(int[] values) {
if (values.length > 0) {
int middleIndex = values.length / 2;
return new NodeImpl(
values[middleIndex], recurseSet(cutArray(values, 0, middleIndex - 1)),
recurseSet(cutArray(values, middleIndex + 1, values.length - 1))
);
} else {
return null;
}
}
private int[] cutArray(int[] array, int begin, int end) {
int length = end - begin + 1;
int[] newArray = new int[length];
System.arraycopy(array, begin, newArray, 0, length);
return newArray;
}
public Node getRoot() {
return root;
}
}
And you will use your classes like:
public static void main(String[] args) {
final Tree tree = new TreeImpl();
tree.setTree(new int[]{1, 10, 9, 8, 2, 5});
System.out.println(tree.getRoot().toString());
}
You just have to think how to implement NodeImpl.toString() method to draw each node in a nice way :) I hope it will help you.
I have already put in the following methods for a binary search tree:
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.ArrayList;
public class MyTree {
private class Node
{
public String data;
public int data2;
public Node left;
public Node right;
public Node(String data, Node left, Node right)
{
this.data = data;
this.left = left;
this.right = right;
}
}
private static Node root = null;
private int getHeight(Node subroot)
{
if (subroot == null)
return -1;
int maxLeft = getHeight(subroot.left);
int maxRight = getHeight(subroot.right);
return Math.max(maxLeft, maxRight) + 1;
}
public String toString()
{
return toString(this.root);
}
private String toString(Node subroot)
{
if (subroot==null)
return "";
return toString(subroot.left)+subroot.data+toString(subroot.right);
}
public boolean containsRecursive(String value)
{
return contains(value, this.root);
}
private boolean contains(String value, Node subroot)
{
if (subroot==null)
return false;
else if (value.equals(subroot.data))
return true;
else if (value.compareTo(subroot.data) < 0)
return contains(value, subroot.left);
else
return contains(value, subroot.right);
}
public boolean contains(String value) // not recursive
{
Node subroot = this.root;
while (subroot != null)
{
if (value.equals(subroot.data))
return true;
else if (value.compareTo(subroot.data) < 0)
subroot = subroot.left;
else
subroot = subroot.right;
}
return false;
}
public int addUp()
{
return addUp(this.root);
}
private int addUp(Node subroot)
{
if (subroot==null)
return 0;
return addUp(subroot.left)+subroot.data2+addUp(subroot.right);
} //data = String, data2 = int
public int count()
{
return count(this.root);
}
private int count(Node subroot)
{
if (subroot==null)
return 0;
return count(subroot.left)+1+count(subroot.right);
}
public int numberLess(int x)
{
return numberLess(this.root, x);
}
private int numberLess(Node subroot, int x)
{
if (subroot==null)
return 0;
if (x < subroot.data2)
return numberLess(subroot.left, x)+1+numberLess(subroot.right, x);
return numberLess(subroot.left, x)+numberLess(subroot.right, x);
}
public int findMax()
{
return findMax(this.root);
}
private int findMax(Node subroot) throws NoSuchElementException
{
if (subroot==null)
throw new NoSuchElementException();
return Math.max(findMax(subroot.left), findMax(subroot.right));
}
private ArrayList<Integer> addToList(Node subroot, ArrayList<Integer> a)
{
if (subroot!=null){
a.add(subroot.data2);
addToList(subroot.left, a).addAll(addToList(subroot.right, a));
return a;
}
return new ArrayList<Integer>();
}
private ArrayList<Integer> getSortedList(){
ArrayList<Integer> rawList = addToList(this.root, new ArrayList<Integer>());
Collections.sort(rawList);
return rawList;
}
public void rebalance(){
ArrayList<Integer> list = getSortedList();
}
}
How can I finish the rebalance method using the structure I already have? I'd like to use the sorted arraylist by finding the midpoints and recursively ordering them. I'm not sure how this would be approached using the way I have my tree set up (with the internal node class) so I'd like some help with this code.
Split the array in two equal sized portions. Take the median element as new root node.
Then split again the two portions and take the median element as second level nodes, etc.
Best implemented recursively....