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;
}
Related
In the class containing the main function, define a function call createTree(String strKey). Giving a string of integers (separated by a space character), this function will create a BST tree with the keys of integers following the input string.
Example: Given a string s = "30 20 40". Calling the function createTree(s) to create a binary seach tree: root = 30, root.left = 20, root.right = 40.
Below is my code:
Node.java
public class Node {
Integer key;
Node left, right;
public Node(Integer key){
this.key = key;
this.left = this.right = null;
}
}
BST.java
public class BST {
private Node root;
public BST(){
this.root = null;
}
public Node getRoot(){
return this.root;
}
public Node insert(Node x, Integer key){
if (x == null){
return new Node(key);
}
int cmp = key.compareTo(x.key);
if (cmp < 0){
x.left = insert(x.left,key);
}
else if (cmp > 0){
x.right = insert(x.right,key);
}
else {
x.key = key;
}
return x;
}
}
Test.java
public class Test {
public static BST createTree(String strKey){
String[] spl = strKey.split(" ");
BST tree = new BST();
Node root = null;
for (int i=0; i<spl.length; i++){
Integer key = Integer.parseInt(spl[i]);
tree.insert(root,key);
}
return tree;
}
public static void main(String[] args){
String s = "20 30 40";
BST tree = createTree(s);
System.out.println(tree.getRoot());
}
}
The result is also null (the root is null) and I don't know the reason why the key is not inserted into the tree. Hope you guys can help me to solve this problem. Thanks a lot
if (x == null){
return new Node(key);
}
The returned node is not assigned to the root in the BST class. Also, you have a root in the createTree method.
You can change it to include an overloaded insert function which takes only the integer to insert and make the existing one private.
private Node insert(Node x, Integer key){
//your existing code
}
public void insert(Integer key) {
this.root = insert(this.root, key);
}
With this, the root will be updated when it is created the first time.
From createTree call the one argument insert method.
public static BST createTree(String strKey) {
String[] spl = strKey.split(" ");
BST tree = new BST();
for (int i = 0; i < spl.length; i++) {
Integer key = Integer.parseInt(spl[i]);
tree.insert(key);
}
return tree;
}
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 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!
I am currently working on a linked list project but I am stumped on my last 3 methods, my removeWord(), concatenate() and doubleChar().. I was wondering if anyone one could give me some tips in what I am doing wrong.
class Node {
private char letter;
private Node next;
public Node(char ch, Node link) {
letter = ch;
next = link;
}
public void setLetter(char letter) {
this.letter=letter;
}
public char getLetter() {
return letter;
}
public void setNext(Node next) {
this.next=next;
}
public Node getNext() {
return next;
}
}
class Word {
// instance variable pointing to the head of the linked list
private Node head;
// default constructor
public Word() {
head = null;
}
// copy constructor
public Word(Word w) {
this.head = copy(w.head);
}
private static Node copy(Node l){
Node newL;
if( l ==null){
newL=null;
}else{
newL = new Node(l.getLetter(),copy(l.getNext()));
}
return newL;
}
// constructor from a String
public Word( String s ) {
Node pt;
head = null;
for( int i = s.length()-1; i >=0; i--){
pt = new Node(s.charAt(i),head);
head = pt;
}
}
// for output purposes -- override Object version
// no spaces between the characters, no linefeeds/returns
#Override
public String toString() {
//s.charAt
return toString(head);
// return toString(head);
}
private static String toString(Node L){
String Word="";
if (L == null){
// do nothing
}
else{
Word = L.getLetter() + toString(L.getNext());
// return the letter
}
return Word;
}
// remove the first occurrence of the Word w from this Word
public void removeWord( Word w ) {
head = removeWord(head,w);
}
private static Node removeWord(Node L, Word w)
{
if(L == null)
{
// do nothing
}else if(L==w.head){
L = L.getNext();
}
else {
// remove the word
L.setNext(removeWord(L.getNext(),w));
}
return L;
}
// concatenate a copy of s to the end of this Word
public void concatenate( Word s ) {
this.head = concatenate(head,s);
}
private static Node concatenate(Node L, Word s){
if( L==null){
L = null;
}
else{
L = new Node(L.getLetter(),concatenate(L.getNext(),s));
L.setNext(concatenate(L.getNext(),s));// add to the end of the list
}
return L;
}
// make a copy of every occurrence of ch in this Word
// for example, if this Word is abbcbccb, doubleChar ( 'b' ) should
// change the Word to abbbbcbbccbb
public void doubleChar( char ch ) {
head = doubleChar(head,ch);
}
public static Node doubleChar(Node L, char ch){
if(L == null)
{
}
else if(L.getLetter()==ch){
}
else{
//double
L.setNext(doubleChar(L.getNext(),ch));
}
return L;
}
I came up with this code but it requires a global variable Rank. Is there any way I can solve this problem without having to have a global variable?
int Rank = 0;
public int inOrderTraversal(TreeNode node, int n){
if(node==null)
return 0;
int x=inOrderTraversal(node.left,n);
if(x!=0)return x;
Rank++;
if(n==Rank) return node.data;
int y=inOrderTraversal(node.right,n);
int c= x==0 ? y:x;
return c;
}
I am just trying to return the nth term in an in-order traversal of a binary tree.
You can pass a TraversalState object down the recursion invocation chain, and store the number of nodes that you visited in a variable there:
class TraversalState {
public int rank = 0;
}
...
public int inOrderTraversal(TreeNode node, int n, TraversalState ts){
if(node==null)
return 0;
int x=inOrderTraversal(node.left,n, ts);
ts.rank++;
if(n==ts.rank) return node.data;
int y=inOrderTraversal(node.right,n, ts);
int c= x==0 ? y:x;
return c;
}
Now your implementation is thread-safe, because it does not use "global" objects. Invoke it as follows:
int r = inOrderTraversal(myNode, targetN, new TraversalState());
The recursive approach is easy to understand, but if your tree shape defies expectation, then you're at the mercy of maximum stack depth here, which is likely to be more limiting that heap memory consumed by an explicitly allocated stack structure. Hence, it's better to invest the time in building an iterative walker.
First, define the structure for the tree nodes themselves:
public final class TreeNode {
public final int data;
public final TreeNode left, right;
public TreeNode(int data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
public TreeNode(int data) {
this(data, null, null);
}
}
We're going to want a way to react to events signaled during a depth-first walk through the tree. Returning true from these methods indicates that the visitor wishes for the walk to continue; returning false requests that the walk stop as soon as possible.
public abstract class Visitor {
public boolean visitPre(TreeNode node) {
return true;
}
public boolean visitMid(TreeNode node) {
return true;
}
public boolean visitPost(TreeNode node) {
return true;
}
}
Now, define the iterative in-order walk algorithm:
final class InOrder {
private InOrder() {}
private static final class Breadcrumb {
public final TreeNode node;
public final boolean rightIsNext; // Not a great name.
public Breadcrumb(TreeNode node, boolean rightIsNext) {
this.node = node;
this.rightIsNext = rightIsNext;
}
public static Breadcrumb goingLeft(TreeNode departingPoint) {
return new Breadcrumb(departingPoint, true);
}
public static Breadcrumb goingRight(TreeNode departingPoint) {
return new Breadcrumb(departingPoint, false);
}
}
public static <T extends Visitor> T walk(TreeNode root, T visitor) {
if (null == root ||
null == visitor)
throw new NullPointerException();
final Deque<Breadcrumb> stack = new ArrayDeque<Breadcrumb>();
if (!visitor.visitPre(root))
return visitor;
for (;;) {
for (TreeNode left = root.left;
null != left;
root = left, left = root.left) {
if (!visitor.visitPre(left))
return visitor;
stack.push(Breadcrumb.goingLeft(root));
}
if (!visitor.visitMid(root))
return visitor;
final TreeNode right = root.right;
if (null != right) {
if (!visitor.visitPre(right))
return visitor;
stack.push(Breadcrumb.goingRight(root));
root = right;
} else {
if (!visitor.visitPost(root))
return visitor;
// Go back up the tree until we find a node with an unexplored right child.
for (;;) {
if (stack.isEmpty())
return visitor;
final Breadcrumb breadcrumb = stack.pop();
if (breadcrumb.rightIsNext) {
if (!visitor.visitMid(breadcrumb.node)) {
return visitor;
}
if (null != breadcrumb.node.right) {
if (!visitor.visitPre(breadcrumb.node.right))
return visitor;
stack.push(Breadcrumb.goingRight(breadcrumb.node));
root = breadcrumb.node.right;
break;
}
}
if (!visitor.visitPost(breadcrumb.node))
return visitor;
}
}
}
}
}
Exercise the walk() function on a sample tree:
(1)
|
+-+-+
| |
(2) (5)
|
+-+-+
| |
(3) -
|
+-+-+
| |
- (4)
That is, there are five nodes, where both leaves with data 4 and 5 are right children.
final TreeNode root = new TreeNode(1,
new TreeNode(2,
new TreeNode(3,
null,
new TreeNode(4)),
null),
new TreeNode(5));
walk(root,
new Visitor() {
private final PrintStream ps = System.out;
#Override
public boolean visitPre(TreeNode node) {
trace(node, "Pre");
return true;
}
#Override
public boolean visitMid(TreeNode node) {
trace(node, "Mid");
return true;
}
#Override
public boolean visitPost(TreeNode node) {
trace(node, "Post");
return true;
}
private TreeNode trace(TreeNode node, String phase) {
ps.print(phase);
ps.print('(');
ps.print(node.data);
ps.println(')');
return node;
}
});
This prints the following:
Pre(1)
Pre(2)
Pre(3)
Mid(3)
Pre(4)
Mid(4)
Post(4)
Post(3)
Mid(2)
Post(2)
Mid(1)
Pre(5)
Mid(5)
Post(5)
Post(1)
Now, you asked for a convenient way to find the nth node encountered during an in-order walk. We'll write a function called findNthInOrder(), where the parameter n designates zero as the first node encountered whose left subtree has already been explored, one designates the second, and so on:
private static TreeNode findNthInOrder(TreeNode root, final int n) {
if (n < 0)
throw new IllegalArgumentException();
return walk(root,
new Visitor() {
public TreeNode found = null;
private int remaining = n + 1;
#Override
public boolean visitMid(TreeNode node) {
if (0 == --remaining) {
found = node;
return false;
}
return true;
}
}).found;
}
Calling this function on our sample tree yields the expected result:
final TreeNode nth = findNthInOrder(root, 3);
System.out.println(null != nth ? nth.data : "(none)");
This prints "1" to the console, which matches the previous tracing walk over the sample tree: the fourth (that is, the zero-based index 3, per the argument above) emitted "Mid" trace is for the root node bearing the data value of one.
In summary, consider building enough to formalize the concepts in play, so that you can write these specific queries more confidently atop a sound foundation.
public int inOrderTraversal(TreeNode node, AtomicInteger n){
if(node == null) return 0;
if(n == 0) return node.data;
int leftVal = inOrderTraversal(node.left, n.decrementAndGet());
if(n == 0) return node.data;
int rightVal = inOrderTraversal(node.right,n.decrementAndGet());
return leftVal == 0 ? rightVal : leftVal;
}
Or to use MutuableInt from Apache commons lang instead of AtomicInteger.