I want to write a method that would record all positions of nodes of haystack starting from where the pattern (structure) of itself matches as that of the needle. The value stored in the node doesn't need to be equal, its just the pattern that is supposed to match.
Illustration
Example 1
If I have the following haystack and needle
In the example above, the program is expected to record
ROOT
ROOT->Left
Example 2
If I have the same haystack as that of above and my needle as
Then my program is expected to record,
ROOT
ROOT->Left
ROOT->Right
However, it seems like the way I am implementing my code is flawed because my method even records positions that shouldn't have been true.
The way I am implementing my code is, I have the following method that would return a list which contains all such positions and I am using a isSubtree method to check if the pattern starting from a particular node finds a match.
public static List<String> searchForNeedleInHaystack(Node haystack,
Node needle) {
List<String> resultList = new ArrayList<String>();
if(haystack.getLeftChild() != null) {
value = value + "L";//value is just a global string variable initially ""
if(isSubtree(haystack.getLeftChild(), needle)) {
resultList.add(value);
} else {
if(value.length() > 1)
value = value.substring(0, value.length() - 1);
}
searchForNeedleInHaystack(haystack.getLeftChild(), needle);
}
if(haystack.getRightChild() != null) {
value = value + "R";
if(isSubtree(haystack.getRightChild(), needle)) {
resultList.add(value);
} else {
if(value.length() > 1)
value = value.substring(0, value.length() - 1);
}
searchForNeedleInHaystack(haystack.getRightChild(), needle);
}
return resultList;
}
public static boolean isSubtree(Node haystack, Node needle) {
if(needle == null)
return true;
if(haystack == null)
return false;
return isSubtree(haystack.getLeftChild(), needle.getLeftChild()) && isSubtree(haystack.getRightChild(), needle.getRightChild());
}
Node class
public class Node {
private String info;
private Node leftChild = null;
private Node rightChild = null;
public Node() {
this("");
}
public Node(String info) {
this.info = info;
}
public void setinfo(String info) {
this.info = info;
}
public void setLeftChild(Node n) {
leftChild = n;
}
public void setRightChild(Node n) {
rightChild = n;
}
public Node getLeftChild() {
return leftChild;
}
public Node getRightChild() {
return rightChild;
}
public String getinfo() {
return info;
}
public boolean isLeaf() {
return rightChild == null && leftChild == null;
}
}
Problem
I just wanted to know what logic could I perhaps use so that I can compare for subtree structures successfully?
Thanks in advance!
Related
I have a Binary Search Tree and I think one of my method is working incorrectly. The program I have is a program that separates the strings read from a file word by word and deletes the special characters in it, then transfers these words to the data structure in alphabetical order. If the same word was previously conveyed during the transmission, it increases the frequency of that word. While checking the output of my program, I saw something like this.
MY OUTPUT:
Readed Line: sun-meal //After some operation it is seperated like "sun" and "metal"
String inserted.
String inserted.
Readed Line: sun-oil //After some operation it is seperated like "sun" and "oil"
String inserted.
String inserted. //Error is here.
TRUE OUTPUT SHOULD BE:
Readed Line: sun-meal //After some operation it is seperated like "sun" and "metal"
String inserted.
String inserted.
Readed Line: sun-oil //After some operation it is seperated like "sun" and "oil"
String inserted.
Repeated String. Frequency +1. //It should be like that.
I will share my source code but what I want to know is what am I doing wrong? Why is "sun" inserted 2 times?
TreeDriver Class:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class TreeDriver
{
public static void main(String [] args) throws FileNotFoundException {
Tree stTree = new Tree();
TreeNode compareNode;
Scanner scan = new Scanner(new File(args[0]));
while (scan.hasNextLine()) {
String data = scan.nextLine();
System.out.println("Readed Line: "+data);
String[] convertedData = data.replaceAll("[^a-zA-Z ]", " ").toLowerCase().split("\\s+");
int y = 0;
try {
while(convertedData[y] != null){
String st = convertedData[y];
if (st.contains(" ")) {
}
else{
compareNode = Tree.search(stTree.getRoot(), st);
if (compareNode != null) {
compareNode.upFreq();
System.out.println("\tRepeated String. Frequency +1.");
} else {
stTree.insert(st);
System.out.println("\tString inserted.");
}
y++;
}
}
}
catch(Exception ignored) {
}
}
scan.close();
}
}
TreeNode Class
public class TreeNode
{
private int freq; //frequency of the String in the Node
private String stValue;
private TreeNode left;
private TreeNode right;
public TreeNode(String st)
{
stValue = st;
left = null;
right = null;
freq = 1;
}
public void add(String st)
{
if (left == null)
{
left = new TreeNode(st);
}
else if (right == null)
{
right = new TreeNode(st);
}
else
{
if(countNodes(left) <= countNodes(right))
{
left.add(st);
}
else
{
right.add(st);
}
}
}
//Count the nodes in the binary tree to which root points, and
public static int countNodes( TreeNode root ) {
if ( root == null )
// The tree is empty. It contains no nodes.
return 0;
else {
// Start by counting the root.
int count = 1;
// Add the number of nodes in the left subtree.
count += countNodes(root.getLeft());
// Add the number of nodes in the right subtree.
count += countNodes(root.getRight());
return count; // Return the total.
}
}
public TreeNode getLeft(){
return left;
}
public TreeNode getRight(){
return right;
}
public String getString()
{
return stValue;
}
public void upFreq()
{
freq = freq + 1;
}
public int getFreq()
{
return freq;
}
}
Tree Class:
public class Tree
{
private TreeNode root;
public Tree()
{
root = null;
}
public boolean isEmpty()
{
return root == null;
}
public void insert(String st)
{
if (isEmpty())
{
root = new TreeNode(st);
}
else
{
root.add(st);
}
}
public TreeNode getRoot()
{
return root;
}
public static TreeNode search(TreeNode root, String st)
{
if(root == null)
{
return null;
}
else if(st.equals(root.getString()))
{
return root;
}
else
{ if (root.getLeft() != null)
return search(root.getLeft(), st);
else
return search(root.getRight(), st);
}
}
public TreeNode found(TreeNode root)
{
return root;
}
public static void preorderPrint(TreeNode root)
{
if ( root != null )
{
System.out.print( root.getString() + " " ); // Print the root item.
preorderPrint( root.getLeft() ); // Print items in left subtree.
preorderPrint( root.getRight() ); // Print items in right subtree.
}
}
}
Can you please help me find the problem?
Indeed, your search function is wrong :
if (root.getLeft() != null)
return search(root.getLeft(), st);
else
return search(root.getRight(), st);
You are going through the right child node only if the left one is null, when you should go through both.
i have a BST and each node contain a word and a frequencies.
the BST sorted according to the word.
before inserting into the BST we must check if the word in BST or not, if it is not insert it.
if it is there i will increase the frequencies by 1.
the question is
how to get the word which have the highest frequencies?
here is my BST class
public class BST {
private BSTword root;//root as reference variable
// CONSTRUCTORS
public BST() {
root = null;
}
and this is the node which contain the word and its frequencies
public class BSTword {
private int freq;
private String word;
private BSTword left;
private BSTword right;
public BSTword() {
word = "";
left = right = null;
}
public BSTword(String word) {
this.word = word;
freq=1;
left = right = null;
}
and here is what i have done so far
this method in BST class
private BSTword mostCommonWord(BSTword p, int c) {
if (p == null) {//No Subtree
return p;
} else {
if (p != null) {
if (p.getData() == c) {
return p;
}
mostCommonWord(p.getLeft(), c);
if (p.getLeft().getData() > c) {
return p;
}
if (p.getRight().getData() > c) {
mostCommonWord(p.getRight(), c);
}
}
}
return p;
}
I'm having trouble writing a method that appends all elements in a method's parameter list to the end of another list. The method is supposed to return true if the list was changed, and false otherwise.
For example, if the original list was 1->6->5, and the other list is 3->8->2. After the call, the list is now 1->6->5->3->8->2.
I'm having trouble with the Boolean return statements as I am confused how they link into the logic of the list. I also don't know how far the pointers need to move in order to append the lists. The whole thing can be done in one loop but I don't know how.
public boolean appendList(DynamicList othrList) {
for (DynamicNode tmp = head; tmp != null; tmp.getNext()) {
if(tmp == null) {
DynamicNode ex = otherList.getList;
tmp.setNext(ex);
}
return true;
}
return false;
}
Full code:
public class DynamicNode {
private Object info; // the data in the node
private DynamicNode next; // refers to the next node on the list
public DynamicNode(Object x, DynamicNode n) {
info = x;
next = n;
}
public Object getInfo() { return info; }
public DynamicNode getNext() { return next; }
public void setInfo(Object x) { info = x; }
public void setNext(DynamicNode n) { next = n; }
public String toString() { return info.toString(); }
}
class DynamicList {
private DynamicNode head;
public DynamicList() { head = null; }
public DynamicList(DynamicNode head) { this.head = head; }
public boolean isEmpty() { return head == null; }
public DynamicNode getList() { return head; }
// The problem
public boolean appendList(DynamicList othrList) {
for (DynamicNode tmp = head; tmp != null; tmp.getNext()) {
if(tmp == null) {
DynamicNode ex = otherList.getList;
tmp.setNext(ex);
}
return true;
}
return false;
}
}
For the code in question (with comments in the code holding additional explanation).
This does fulfill the requirement: "if the original list was 1->6->5, and the other list is 3->8->2. After the call, the list is now 1->6->5->3->8->2."
It appends the elements(nodes) so after appending both list share the same nodes. Which should be okay. However this implies that if a node in "othrlist" changes after appending, it will also change in the list. Often this is the expected behavior.
So it is "shallow" and does not create any unessary (deep-)copies of elements.
To sum up this behaves the way, the aproach the op choose in his method does: One(!) loop, only appending and not duplicating.
public boolean appendList(DynamicList othrList) {
DynamicNode tmp = head;
if(tmp == null) { //special case empty list
head = othrList.getList();
return null != head; //early exit, list changed if head is no longer null.
}
while (tmp.getNext() != null) tmp = tmp.getNext(); //search for the last element
tmp.setNext(othrList.getList()); //link last element to head of other.
return null != tmp.getNext(); //list changed if tmp.next is no longer null(as it was before).
}
I am attempting to use recursion to search through a binary tree and return true or false depending on if the binary tree contains the string. Here is my code
public class BinaryTree {
private String data;
private BinaryTree leftChild;
private BinaryTree rightChild;
public BinaryTree() {
data = null;
leftChild = null;
rightChild = null;
}
public BinaryTree(String d) {
data = d;
leftChild = new BinaryTree();
rightChild = new BinaryTree();
}
// This constructor is unchanged
public BinaryTree(String d, BinaryTree left, BinaryTree right) {
data = d;
leftChild = left;
rightChild = right;
}
// Get methods
public String getData() {
return data;
}
public BinaryTree getLeftChild() {
return leftChild;
}
public BinaryTree getRightChild() {
return rightChild;
}
// Set methods
public void setData(String d) {
data = d;
}
public void setLeftChild(BinaryTree left) {
leftChild = left;
}
public void setRightChild(BinaryTree right) {
rightChild = right;
}
public boolean contains(String d) {
return d != null && (this.getData().equals(d) ||
contains(this.getLeftChild().getData()) ||
contains(this.getRightChild().getData()));
}
So, my issue is with the contains method as it keeps giving me a stackoverflow.error . I was hoping i could get assistance on this thanks in advance.
You could try this:
public boolean contains(String d)
{
// Not contained if specified string is null
if (d == null)
return (false);
// OK if specified string equals our data
if ((data != null) && data.equals(d))
return (true);
// OK if contained in left tree
if ((leftChild != null) && leftChild.contains(d))
return (true);
// OK if contained in right tree
if ((rightChild != null) && rightChild.contains(d))
return (true);
// Otherwise, it's not OK
return (false);
} // contains
What you're doing there is not recursion. You are asking:
boolean found = tree.contains(candidate)
right?
Your code expands this to
boolean found = candidate != null && (tree.getData.equals(d) || LEFT || RIGHT)
where LEFT is
contains(tree.getLeftChild().getData())
which is not comparing the candidate string with the left data at all but rather expands to
candidate != null && (tree.getData.equals(candidate) || LEFT || RIGHT)
which results in an endless loop, causing the StackOverflow.
You should reformulate the class as
public class Node {
Node left, right;
String data
public boolean contains(String d);
}
and then your tree would be a root Node and the search could be recursive.
On each recursive call this refers to the same object and hence you keep on passing the same values over and over again. You need to pass BinaryTree references as a parameter.
private boolean contains(String data, BinaryTree node) {
if (node == null) {
return false;
}
return node.getData().equals(data) || contains(data, node.getLeftChild())
|| contains(data, node.getRightChild());
}
The main (public) contains needs to pass the String to be searched and the root to the above method.
I need to print the ancestors of a node in binary tree. e.g Node 7 has ancestors as 1,3 . I have written the below code but output is coming as 7. Can you suggest the issues in this code?
1
/ \
2 3
/ \ / \
4 5 6 7
public static String findAncestor(BinaryTreeNode root , int number, boolean matched) {
if (root != null) {
int rootData = root.getData();
BinaryTreeNode left = root.getLeft();
BinaryTreeNode right = root.getRight();
if (left != null && right != null) {
return findAncestor (root.getLeft(), number, matched ) + findAncestor (root.getRight(), number, matched);
}
if (left != null) {
return findAncestor (root.getLeft(), number, matched ) ;
}
if (right != null) {
return findAncestor (root.getRight(), number, matched ) ;
}
if (rootData == number) {
matched = true;
return String.valueOf(rootData);
}
if (matched) {
return String.valueOf(rootData);
}
}
return "";
}
public boolean findAncestorPath(List<Integer> ancestors, BinaryTreeNode node, int number) {
if (node == null)
return false;
int data = node.getData();
if (data == number)
return true;
if (findAncestorPath(ancestors, node.getLeft(), number)) {
ancestors.add(data);
return true;
}
if (findAncestorPath(ancestors, node.getRight(), number)) {
ancestors.add(data);
return true;
}
return false;
}
Then you'd call this as (you should also probably wrap it in a function):
List<Integer>() ancestors = new ArrayList<Integer>();
boolean found = findAncestorPath(ancestors, root, number);
Note that the ancestor list would be reversed.
Here is the Java implementation
public static List<Integer> ancestors(BinaryTreeNode<Integer> root, Integer target) {
List<Integer> result = new ArrayList<Integer>();
findAncestors(root, target, result);
return result;
}
private static boolean findAncestors(BinaryTreeNode<Integer> node, Integer target, List<Integer> result) {
if (node == null) {
return false;
}
if (node.getData() == target) {
return true;
}
if (findAncestors(node.getLeft(), target, result) || findAncestors(node.getRight(), target, result)) {
result.add(node.getData());
return true;
}
return false;
}
Here is the unit test case
#Test
public void allAncestors() {
BinaryTreeNode<Integer> root = buildTree();
List<Integer> ancestors = BinaryTreeUtil.ancestors(root, 6);
assertThat(ancestors.toArray(new Integer[0]), equalTo(new Integer[]{5,2,1}));
}
This piece of code work fine for giving all the ancestors a particular node , node is root node and value is the value of the node for which we have to find all the ancestor.
static boolean flag=false;
static void AnchersterOf(AnchesterNode node,int value) {
// TODO Auto-generated method stub
if(node==null)
return ;
if(node.value==value){
flag=true;
return;
}
if(flag==false){
AnchersterOf(node.left,value);
if(flag==true){
AnchersterOf(node,value);
} if(flag==true)
System.out.println(node.value);
AnchersterOf(node.right,value);
if(flag==true)
System.out.println(node.value);
}
}