This is my code so far to find all of the nodes represented by char characters. I've been able to code how to get the root node's "(" and ")" using the helper method. However, i'm having a mind block when trying to integrate the helper method into the treeProcessor. In the treeProcessor method i'm trying to further delve into binary tree so that the end goal is to just print out the root node and sub trees.
public static ArrayList<String> paths = new ArrayList<>();
public static void main(String[] args)
{
String tree = "(a(b()())(c()()))";
//replace this line with a call to the treeProcessor
System.out.println(Arrays.toString(treeBreakdownHelper(tree)));//a, (b()()), (c()())
System.out.println();
System.out.println(paths);//prints every path found
}
//recursive method
public static void treeProcessor(String tree, String path)
{
//breakdown tree
//update path
//check if current element is leaf/last element
//if it is, add to ArrayList
//if not last element, run processor again on subtrees that are not empty
}
//valid tree:
//(a()())
//(a(b()())(c()()))
//helper method
public static String[] treeBreakdownHelper(String tree)
{
String[] temp = new String[3];
//0 = root
//1 = left tree
//2 = right tree
tree = tree.substring(1, tree.length()-1);
//System.out.println(tree);//test removal of outer parens
temp[0] = "" + tree.charAt(0);
tree = tree.substring(1);
//System.out.println(tree);//test removal of root node
int openCount = 0;
int middle = 0;
for(int i = 0; i < tree.length(); i++)
{
//System.out.println(openCount);
if(tree.charAt(i) == '(')
{
openCount++;
}
else if(tree.charAt(i) == ')')
{
openCount--;
}
if(openCount == 0)
{
middle = i;
break;
}
}
//System.out.println(middle);
//System.out.println(tree.substring(0,middle+1));
temp[1] = tree.substring(0,middle+1);
//System.out.println(tree.substring(middle+1));
temp[2] = tree.substring(middle+1);
return temp;
}
}
Related
I have a binary tree where each node has the value of 0 or 1, and each path from the root to leaf node represents a binary string of a certain length. The aim of the program is to find all possible binary String (i.e. all possible paths from root to leaf). Now I want to parallelise it, so that it can use multiple cores. I assume I need to somehow split up the workload on the branch nodes, but I have no idea where to begin. I am looking at the ForkJoin functionality, but I have no idea how to split up the work and then combine it.
public class Tree{
Node root;
int levels;
Tree(int v){
root = new Node(v);
levels = 1;
}
Tree(){
root = null;
levels = 0;
}
public static void main(String[] args){
Tree tree = new Tree(0);
populate(tree, tree.root, tree.levels);
tree.printPaths(tree.root);
}
public static void populate(Tree t, Node n, int levels){
levels++;
if(levels >6){
n.left = null;
n.right = null;
}
else{
t.levels = levels;
n.left = new Node(0);
n.right = new Node(1);
populate(t, n.left, levels);
populate(t, n.right, levels);
}
}
void printPaths(Node node)
{
int path[] = new int[1000];
printPathsRecur(node, path, 0);
}
void printPathsRecur(Node node, int path[], int pathLen)
{
if (node == null)
return;
/* append this node to the path array */
path[pathLen] = node.value;
pathLen++;
/* it's a leaf, so print the path that led to here */
if (node.left == null && node.right == null)
printArray(path, pathLen);
else
{
/* otherwise try both subtrees */
printPathsRecur(node.left, path, pathLen);
printPathsRecur(node.right, path, pathLen);
}
}
/* Utility function that prints out an array on a line. */
void printArray(int ints[], int len)
{
int i;
for (i = 0; i < len; i++)
{
System.out.print(ints[i] + " ");
}
System.out.println("");
}
}
You can use Thread Pools to efficiently split the load between separate threads.
One possible approach:
ExecutorService service = Executors.newFixedThreadPool(8);
Runnable recursiveRunnable = new Runnable() {
#Override
public void run() {
//your recursive code goes here (for every new branch you have a runnable (recommended to have a custom class implementing Runnable))
}
};
service.execute(recursiveRunnable);
However, this approach is no longer a deep first search, since you list the sub-branches for your position before searching through the first one. In my understanding, DFS is a strictly linear approach and is therefore not entirely parallelizable (feel free to correct me in the comments though).
I am trying to implement a suffix trie in Java. A trie has a root node and connected to it are edges. However, when implementing functions such as constructTrie(T) (constructs a trie given a String T) or substring(S,T) (checks whether S is a substring of T), I am keeping a current node cNode which changes throughout the code depending on which node I am considering.
I am not sure if I'm changing cNode's value correctly. The following is class Trie.
import java.util.*;
class Trie{
protected Node root = null;
public Trie(){
Node n = new Node();
root = n;
}
// Constructs a trie for a given string T
public void constructTrie(String T){
ArrayList<String> suffixArray = new ArrayList<String>();
T += "#"; // Terminator
int length = T.length();
// Creates suffix array and removes first letter with every iteration
for(int i=0; i<length; i++){
suffixArray.add(T);
T = T.substring(1);
}
// Goes through suffix array
for(int i=0; i<length; i++){
Node cNode = null;
cNode = root; // Current node
int j = 0;
// Goes through each letter of an entry in the suffix array
while(j < (suffixArray.get(i)).length()){
int index = cNode.findEdge((suffixArray.get(i)).charAt(j));
// If an edge is found at the root with the current letter, update cNode and remove the letter from word
if(index != -1){
cNode = cNode.getEdge(index).getNode(); // Gets node pointed at by edge and sets it as current node
String replace = (suffixArray.get(i)).substring(1);
suffixArray.set(0, replace); // Erases first letter of suffix
j++;
System.out.println(i + " " + j + " " + replace);
}
// If an edge is not found at the root, write the whole word
else{
for(int k=0; k<(suffixArray.get(i)).length(); k++){
Edge e = new Edge((suffixArray.get(i)).charAt(k)); // Creates edge with current letter of current entry of the suffix array
Node n = new Node(); // Creates node to be pointed at by edge
e.setNode(n);
cNode.newEdge(e);
cNode = n; // Updates current node
}
j = (suffixArray.get(i)).length(); // If the word is written, we break from the while and move on to the next suffix array entry
}
}
}
}
// Checks if S is a substring of T
public boolean substring(String S, String T){
constructTrie(T);
Node cNode = null;
cNode = root;
int index;
for(int i=0; i<S.length(); i++){
index = cNode.findEdge(S.charAt(i));
if(index == -1)
return false; // Substring was not found because a path was not followed
cNode = (cNode.getEdge(index)).getNode(); // Reset current node to the next node in the path
}
return true; // Substring was found
}
Specifically, am I allowed to set Node root = null as a class variable, initialise root when an object of type Trie is created and change cNode as shown in the methods? The code is compiled with no errors, however when tested it does not always output the correct response e.g. when tested, it outputs that 'es' is not a substring of 'pest'.
Updating fields in a method of a class makes a class not thread safe. Your methods have side effects that may not be what the user of the your class expects.
Consider:
Trie t = new Trie("My String");
boolean startsWithMy = t.substring("My");
boolean startsWithMyString = t.substring("My String");
If you're updating the root field in the substring method, then the 2nd call won't do what you might expect, since the first substring call changed the Trie.
If you want to make a reusable class that is easy to use with minimal side effects, then what I would do is write your class following this basic pattern:
public class Trie {
private final Node root;
public Trie(String input) {
// Construct the Trie here and assign it to root:
this.root = constructTry(input);
}
public boolean substring(String part) {
// Create a local Node variable:
Node currentNode = root;
// Navigate the Trie here using currentNode:
// ...
return result;
}
}
You can even add a method (if you desire) to return a subpart of the Trie:
public Trie subTrie(String part) {
// Find the Node here that matches the substring part, and return it.
// If nothing found, then throw NoSuchElementException or return null.
Node subNode = findNode(part);
if (subNode == null) {
throw new NoSuchElementException("No element starting with: " + part);
}
// Constructs a new Trie with a different root node using a 2nd constructor option
return new Trie(subNode);
}
You are changing the reference of your root node by adding garbage to it.
Let say you do this:
Trie trie = new Trie();
trie.substring("es", "pest"); // this returns true.
but if you do
Trie trie = new Trie();
trie.substring("es", "pest");
trie.substring("te", "Master");
You second call to Substring will pick up where your last call left. You root is already initialized and contains a tree for the word "pest" root(p, e, s, t, #). After the second call instead of having as expected root(M, a, s, t, e, r, #), you end up with root(p, e, s, t, #, M, a, r). Which is is a completely different word. As such te is not a substring of pest#Mar.
But if you implement it according to #john16384, you will be forced to do the following which eliminate the side effects:
Trie trie = new Trie("pest");
trie.substring("es"); // this returns true.
trie = new Trie("Master");
trie.substring("te") // this returns true.
Doing it this way alway forces you to start from a clean root. See the implementation below:
class Trie {
protected Node root = null;
public Trie(String T) {
root = constructTrie(T);
}
// Constructs a trie for a given string T
private Node constructTrie(String T) {
ArrayList<String> suffixArray = new ArrayList<String>();
T += "#"; // Terminator
int length = T.length();
// Creates suffix array and removes first letter with every iteration
for (int i = 0; i < length; i++) {
suffixArray.add(T);
T = T.substring(1);
}
Node localRoot = new Node();
// Goes through suffix array
for (int i = 0; i < length; i++) {
Node cNode = localRoot;
int j = 0;
// Goes through each letter of an entry in the suffix array
while (j < (suffixArray.get(i)).length()) {
int index = cNode.findEdge((suffixArray.get(i)).charAt(j));
// If an edge is found at the root with the current letter, update cNode and remove the letter from word
if (index != -1) {
cNode = cNode.getEdge(index).getNode(); // Gets node pointed at by edge and sets it as current node
String replace = (suffixArray.get(i)).substring(1);
suffixArray.set(0, replace); // Erases first letter of suffix
j++;
System.out.println(i + " " + j + " " + replace);
}
// If an edge is not found at the root, write the whole word
else {
for (int k = 0; k < (suffixArray.get(i)).length(); k++) {
Edge e = new Edge((suffixArray.get(i)).charAt(k)); // Creates edge with current letter of current entry of the suffix array
Node n = new Node(); // Creates node to be pointed at by edge
e.setNode(n);
cNode.newEdge(e);
cNode = n; // Updates current node
}
j = (suffixArray.get(i)).length(); // If the word is written, we break from the while and move on to the next suffix array entry
}
}
}
return localRoot;
}
// Checks if S is a substring of T
public boolean substring(String S) {
Node cNode = root;
int index;
for (int i = 0; i < S.length(); i++) {
index = cNode.findEdge(S.charAt(i));
if (index == -1)
return false; // Substring was not found because a path was not followed
cNode = (cNode.getEdge(index)).getNode(); // Reset current node to the next node in the path
}
return true; // Substring was found
}
}
I'm trying to create a balanced tree with a string of letters. If you put "ABCDE" for string, your code is expected to give an output something like this.
INPUT : "ABCDE"
OUTPUT :
.......................................................
+
+ E
+ + -- --
A B C D -- -- -- --
.......................................................
The book suggests me to first create an array of one-node tree whose root will be each character of the string. Then, make a three-node tree out of each pair of one-node trees, making a new + node for the root which will result in a forest of three - node trees.
I know this problem is a stepping-stone to ultimately write the Huffman tree.
I'm having trouble putting the three-node tree back into the array with one-node trees and then make a 7-node tree by combining the two three-node trees and so on.
Below is my code,
import java.util.*; // for Stack class
class StringNode {
public char iData; // data item (key)
public StringNode leftChild; // this node's left child
public StringNode rightChild; // this node's right child
StringNode(char d) {
iData = d;
}
public void displayNode() // display ourself
{
System.out.print('{');
System.out.print(iData);
System.out.print("} ");
}
} // end class Node
class STree {
private StringNode root; // first node of tree
public String sequence;
// -------------------------------------------------------------
public STree() // constructor
{
root = null;
} // no nodes in tree yet
public void makeBalanceTree() // creating a balanced tree
{
StringNode array[] = new StringNode[sequence.length()];
for (int i = 0; i < sequence.length(); i++)
array[i] =
new StringNode(sequence.charAt(i)); //fill array with node holding each character as key
STree forest[] = new STree[array.length]; //make a forest of trees
for (int j = 0; j < array.length; j++) { //store each node as the root of the tree
forest[j] = new STree();
forest[j].root = array[j];
}
int count = sequence.length();
while (count == 0) {}
}
public void displayTree() {
Stack globalStack = new Stack();
globalStack.push(root);
int nBlanks = 32;
boolean isRowEmpty = false;
System.out.println("......................................................");
while (isRowEmpty == false) {
Stack localStack = new Stack();
isRowEmpty = true;
for (int j = 0; j < nBlanks; j++) System.out.print(' ');
while (globalStack.isEmpty() == false) {
StringNode temp = (StringNode) globalStack.pop();
if (temp != null) {
System.out.print(temp.iData);
localStack.push(temp.leftChild);
localStack.push(temp.rightChild);
if (temp.leftChild != null || temp.rightChild != null) isRowEmpty = false;
} else {
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for (int j = 0; j < nBlanks * 2 - 2; j++) System.out.print(' ');
} // end while globalStack not empty
System.out.println();
nBlanks /= 2;
while (localStack.isEmpty() == false) globalStack.push(localStack.pop());
} // end while isRowEmpty is false
System.out.println("......................................................");
} // end displayTree()
} // end class Tree
public class StringTreeApp {
public static void main(String[] args) {
int value;
STree theTree = new STree();
theTree.sequence = "ABCDE";
theTree.makeBalanceTree();
theTree.displayTree();
} // end main()
} // end class TreeApp
I think that the book is making it harder for you than necessary by recommending creating an array of StringNodes up front.
If you have a String, you know that the "middle" character is going to be the iData; the characters preceding it are going to be in the left tree; the characters following it are going to be in the right tree.
As such, you should be able to construct a StringNode as follows:
StringNode buildStringNode(String sequence) {
if (sequence.isEmpty()) return null;
int middlePos = (sequence.length() + 1) / 2;
char iData = sequence.charAt(middlePos);
StringNode result = new StringNode(iData);
result.leftChild = buildStringNode(sequence.substring(0, middlePos));
result.rightChild = buildStringNode(sequence.substring(middlePos + 1));
return result;
}
This "automatically" combines the child trees with the parent tree. Your makeBalanceTree() method is then simply:
void makeBalanceTree() {
root = buildStringNode(sequence);
}
I already build a binary search tree. The primitive data type I store in the tree is integer. I try to store it on a 2-D char array and then print it out as the graph shown below(the numbers represent row numbers and column numbers and I do not need to print it, ignoring "-" symbol please, I only use it to indicate the exact position)
-----0---1---2---3---4---5---6---7---8---9---10---11---12---13---14---15---16
0---------------------------------------12
1--------------------------------/-------------------\
2----------------------8--------------------------------------14
3-----------------/----------\ -----------------------------------------\
4-------------5----------------9-------------------------------------------34
5--------/-------------------------------------------------------------/-------------\
6---2---------------------------------------------------------24------------------------35
number 12 need to store on location [0][8], the middle of the first row.
number 4 store on[2][4], number 14=[2][12], 5=[4][2], 9=[4][9] and so on.
row number 1 which is second row, "/" is on position[1][6] and "\" is on position[1][10] etc.they are also on the middle between two numbers
following is my code
public class MainClass {
public static void main(String[] args) {
//level represents row number;
// start indicates the column I am going to
//store number in, and end is a fixed column number
// BinarySearchTree is a BinaryTree type instance,
// I already story integers on it and follow with the format
// of binary search trees, and I did tested it.
int level=0; int start=0; int end=80;
BinaryTree.plot(BinarySearchTree, level, start, end);
}
private static class BinaryTree {
private BinaryNode root;
static char[][] offset = new char [10][20];
public BinaryTree(){
root = null;
}
public BinaryTree(Object x){
root = new BinaryNode(x);
}
public boolean isEmpty(){
return root == null;
}
public Object getRootobj() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else
return root.element;
}
public BinaryTree getLeft() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else {
BinaryTree t = new BinaryTree();
t.root = root.left;
return t;
}
}
public BinaryTree getRight() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else {
BinaryTree t = new BinaryTree();
t.root = root.right;
return t;
}
}
public static void plot(BinaryTree t, int level, int start, int end){
if(!t.isEmpty()){
plot(t.getLeft(), level+2, start/2, end/2);
String string = Integer.toString((Integer)t.getRootobj());
for(char c: string.toCharArray())
offset[level][start++]=c;
if(!(t.getLeft().isEmpty()))
offset[++level][start/4*3] = '/';
if(!(t.getRight().isEmpty()))
offset[++level][((start+end)/2+start)/2] = '\\';
plot(t.getRight(), level+2, end/2, end);
}
for(int i = 0; i<10; i++){
for(int j= 0; j<20; j++)
System.out.print(offset[i][j]);
}
}
}
private static class BinaryNode {
Object element;
BinaryNode left,right;
BinaryNode() {
this(0);
}
BinaryNode(Object e) {
this(e, null, null);
}
BinaryNode(Object e, BinaryNode ln, BinaryNode m){
element=e;
left=ln;
right=m;
}
}
}
Question: the method plot I used to store and print out binarysearchtree did not work, which causes a java.lang.ArrayIndexOutOfBoundsException:
can anyone take a look at it. appreciated for the help.
Your fixed-size char-Array cannot cope with your dynamic sized BinaryTree. For your given example alone you need way more then 20 characters per line! That's where your Exception is coming from.
But to give you an idea of an alternative approach - even though it took a while, made the following additions to your code:
First, I added a method to the BinaryNode class:
int getDepth() {
int subTreeDepth;
if (left == null && right == null) {
subTreeDepth = 0;
} else if (left == null) {
subTreeDepth = right.getDepth();
} else if (right == null) {
subTreeDepth = left.getDepth();
} else {
subTreeDepth = Math.max(left.getDepth(), right.getDepth());
}
return 1 + subTreeDepth;
}
Second, I removed your fixed char-Array and replaced the whole plotting algorithm in your BinaryTree (I just couldn't wrap my head around all those relative array-index manipulations):
public void plot() {
if (root == null) {
throw new BinaryTreeException("Empty Tree");
}
int lineCount = 2 * root.getDepth() - 1;
StringBuilder[] lines = new StringBuilder[lineCount];
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
lines[lineIndex] = new StringBuilder();
}
// get the right most node (which contains the largest element value)
BinaryNode rightMostNode = root;
while (rightMostNode.right != null) {
rightMostNode = rightMostNode.right;
}
// check how many characters we have to reserve for a single node element
int maxElementLength = String.valueOf(rightMostNode.element).length();
plot(root, 0, 0, maxElementLength, lines);
for (StringBuilder singleLine : lines) {
System.out.println(singleLine.toString());
}
}
private void plot(BinaryNode subTreeRoot, int offset, int lineIndex, int elementLength, StringBuilder[] lines) {
int actualOffset;
if (subTreeRoot.left == null) {
actualOffset = offset;
} else {
actualOffset = offset + (int) Math.pow(2, subTreeRoot.left.getDepth() - 1) * elementLength;
}
StringBuilder currentLine = lines[lineIndex];
String elementValue = String.valueOf(subTreeRoot.element);
for (int lineFillIndex = currentLine.length() + elementValue.length() / 2; lineFillIndex < actualOffset; lineFillIndex++) {
currentLine.append(' ');
}
currentLine.append(elementValue);
if (subTreeRoot.left != null) {
// draw connection to left sub tree
int connectPosition = (actualOffset - offset) * 3 / 4 + offset;
StringBuilder connectLine = lines[lineIndex + 1];
for (int lineFillIndex = connectLine.length(); lineFillIndex < connectPosition; lineFillIndex++) {
connectLine.append(' ');
}
connectLine.append('/');
// insert the left part of the next value line
plot(subTreeRoot.left, offset, lineIndex + 2, elementLength, lines);
}
if (subTreeRoot.right != null) {
// draw connection to right sub tree
int connectPosition = actualOffset + elementLength - elementValue.length() / 2;
if (subTreeRoot.right.left != null) {
connectPosition += (int) Math.pow(2, subTreeRoot.right.left.getDepth() - 1) * elementLength / 2;
}
StringBuilder connectLine = lines[lineIndex + 1];
for (int lineFillIndex = connectLine.length(); lineFillIndex < connectPosition; lineFillIndex++) {
connectLine.append(' ');
}
connectLine.append('\\');
// insert the right part of the next value line
plot(subTreeRoot.right, actualOffset + elementLength, lineIndex + 2, elementLength, lines);
}
}
For a tree similar to the one, you included in your question:
BinaryTree binarySearchTree = new BinaryTree(
new BinaryNode(12,
new BinaryNode(8,
new BinaryNode(5,
new BinaryNode(3),
null),
new BinaryNode(9)),
new BinaryNode(14,
null,
new BinaryNode(34,
new BinaryNode(24),
new BinaryNode(35)))));
binarySearchTree.plot();
I get the following output:
12
/ \
8 14
/ \ \
5 9 34
/ / \
3 24 35
I have a String:
String stringContent="{\\*\\listtable{\\list{\\listlevel{\\leveltext}{\\levelNumber}}}}"
How do I select values of all enclosing braces one by one in each pass like this:
"{\\levelNumber}"
"{\\leveltext}"
"{\\listlevel{\\leveltext}{\\levelNumber}}"
"{\\list{\\listlevel{\\leveltext}}}"
"{\\*\\listtable{\\list{\\listlevel{\\leveltext}}}}"
So far I've done this:
public class StringExtracter {
public String stringofObject(Section parentSectionObject, String stringContent) {
Stack stack=new Stack();
String returnString = "";
char arr[] = stringContent.toCharArray();
for(int i=0;i<=arr.length;i++){
while(arr[i]!='}'){
if(arr[i]=='{'){
stringContent=stringContent.substring(i+1);
returnString=stringContent;
System.out.println(stringContent);
braces=true;
Section sectionObject=new Section(parentSectionObject,stringContent);
stack.push(arr[i]);
}
}
return returnString;
}
But the problem is that it is not detecting the right } like this. How should I be doing this?
Output as of now:
\*\listtable{\list{\listlevel{\leveltext}{\fefw}}}}
\list{\listlevel{\leveltext}{\fefw}}}}
\listlevel{\leveltext}{\fefw}}}}
\leveltext}{\fefw}}}}
\fefw}}}}
Stack-based solution (problably could be simpler, but let's solve the problem first):
public class Main {
public static class Node {
public int level;
public String content = "";
public List<Node> children = new ArrayList<>();
}
public static void main(String[] args) {
String input="{\\\\*\\\\listtable{\\\\list{\\\\listlevel{\\\\leveltext}{\\\\levelNumber}}}}";
Node root = null;
Stack<Node> stack = new Stack<>();
for(char c: input.toCharArray()) {
if (c == '{') {
Node n = new Node();
n.level = stack.size() + 1;
n.content += c;
stack.push(n);
if (root == null) root = n;
} else if (c == '}') {
Node n = stack.pop();
n.content += c;
if (!stack.isEmpty()) {
stack.peek().children.add(n);
}
} else {
stack.peek().content += c;
}
}
TreeTraverser<Node> treeTraverser = new TreeTraverser<Node>() {
#Override
public Iterable<Node> children(Node root) {
return root.children;
}
};
for(Node node : treeTraverser.preOrderTraversal(root)) {
String indent = String.format("%" + node.level + "s", " ");
System.out.println(indent + node.content);
}
}
}
Note: Google's Guava library is needed for the TreeTraverser
Output:
{\\*\\listtable}
{\\list}
{\\listlevel}
{\\leveltext}
{\\levelNumber}
Edit 1: modified to create a tree after additional input from the OP
Edit 2: modified to treat the siblings correctly
I recommend you to, instead of using a for loop, create a variable called i and increase it in the while loop. You're checking for "arr[i]!='}'" in the while loop, but as it's inside the for loop, i never increases, and therefore it's always checking the same character.