I know references to objects in java are passed by copy , but the copy still points to the same memory in system , so after updating some data of the complex object in another function , the original data should me maintained. But interestingly something is going wrong here. I am working with Tries.
Here is my implementation of Trie, it's fairly custom implementation because of some custom rules:
public class Trie {
boolean isEnd;
Trie trie[] = new Trie[256];
ArrayList<Integer> indexNode;
public static Trie createTrieNode() {
Trie temp = new Trie();
temp.isEnd = false;
temp.indexNode = new ArrayList<Integer>();
for (int i = 0; i < temp.trie.length; i++) {
temp.trie[i] = null;
}
return temp;
}
public static void insertIntoTrie(Trie root, char[] alpha, int index, int i) {
if (root == null)
root = createTrieNode();
if (i < alpha.length)
insertIntoTrie(root.trie[alpha[i] - 'a'], alpha, index, i + 1);
else {
if (root.isEnd == true) {
root.indexNode.add(index);
} else {
root.isEnd = true;
root.indexNode.add(index);
}
}
}
}
Now my object root comes from this class and In the debugger I can see this statement being executed : root.isEnd = true;
Class:
public class AnagramsTogether {
public Trie root = new Trie();
public void printAnagrams(String[] anagrams){
char[] buffer;
for (int i = 0; i < anagrams.length; i++) {
buffer = anagrams[i].toCharArray();
Arrays.sort(buffer);
Trie.insertIntoTrie(root, buffer, i, 0);
}
AnagramsUtil.anagramUtil(root,anagrams);
}
}
But when when root is passed here AnagramsUtil.anagramUtil(root,anagrams);
public class AnagramsUtil {
public static void anagramUtil(Trie root, String[] anagrams) {
if (root.isEnd == true) {
for (Iterator<Integer> iterator = root.indexNode.iterator(); iterator
.hasNext();) {
Integer integer = (Integer) iterator.next();
System.out.println(anagrams[integer]);
}
} else {
for (int i = 0; i < root.trie.length; i++) {
if (root.trie[i] == null)
continue;
anagramUtil(root.trie[i], anagrams);
}
}
}
}
public class Anagram{
public static String string[] = {"cat", "dog", "god","act", "tac","gdo"};
public static void main(String args){
new AnagramsTogether().printAnagrams(Anagram.string);
}
}
This statement if (root.isEnd == true) in never executed and so is this is never executed anagramUtil(root.trie[i], anagrams); . The program just keep executing the continue statement.
Which should not be the case as I've already seen root.trie[i] receiving values.
Why does this happen?I am fairly new to java.
You have many Trie objects in your program and you are confusing them. If you check object identity (object number) with your debugger, you will see that they are not the same.
You are saying that you see in the debugger the statement root.isEnd = true; to be executed however you don't mention for which object is executing.
Your insertIntoTrie() method is called recursively so, that statement is probably executed for the Trie objects that the root has in its trie[] array but not for the root object itself.
Since the actual execution depends on the arguments you are using to call printAnagrams(String[] anagrams) please add those to your question if you need a more specific answer.
Update: Ok after you have edited your question it is clear that you are making the mistake to misuse object references even though you know that all "...references to objects in java are passed by copy". Your insertIntoTrie() is faulty. It seems that you intend to create a new object if the argument root is null however that new object will be lost because root argument is a copy. At the end of your method if you print the whole trie[] member of your original root object (the one in the AnagramsTogether class) you will see that all objects are null.
In Java, null is not an object, it is only a special type. Therefore null hasn't got a reference. So that, for example:
Trie root = null;
insertIntoTrie(root, alpha, index, i);
// after called this function, root = null
After called this function, root is still null because the variable root isn't yet an object before calling this function. So that there wasn't any reference of the variable root to be passed by copy in this calling.
Solution:
Change your function:
public static void insertIntoTrie(Trie root, char[] alpha, int index, int i) {
if (root == null)
root = createTrieNode();
if (i < alpha.length)
insertIntoTrie(root.trie[alpha[i] - 'a'], alpha, index, i + 1);
else {
if (root.isEnd == true) {
root.indexNode.add(index);
} else {
root.isEnd = true;
root.indexNode.add(index);
}
}
}
Into :
public static void insertIntoTrie(Trie root, char[] alpha, int index, int i) {
if (i < alpha.length) {
if (root.trie[alpha[i] - 'a'] == null) {
root.trie[alpha[i] - 'a'] = createTrieNode();
}
insertIntoTrie(root.trie[alpha[i] - 'a'], alpha, index, i + 1);
}
else {
if (root.isEnd == true) {
root.indexNode.add(index);
} else {
root.isEnd = true;
root.indexNode.add(index);
}
}
}
This solution make sure that the root is always an object before passing to the insertIntoTrie(...) function.
Related
I am creating a program that inserts a character (number/letter) into a binary tree. So far, I'm able to produce an output but it's not what I expected. These are the problems I'm encountering:
The insert method is not able to print the correct height of the tree. I am not sure where I should insert my height++; statement to get the correct output.
The insert method is only able to add nodes to the right.
Expected Output: ht=3 [K=3 L=[K=1 R=[K=2]] R=[K=5 L=[K=4]]]
My Output: ht=4 [K=3 R=[K=1 R=[K=2 R=[K=5 R=[K=4]]]]
(all nodes are only added to the right 'R')
Here are my classes for reference:
Main Class
BST<Character> bst = new BST<>();
bst.insert('3');
bst.insert('1');
bst.insert('2');
bst.insert('5');
bst.insert('4');
System.out.println("ht=" + bst.height + " " + bst.toString());
BST Class - where the insert method is declared
public class BST<T> extends BT<T> {
// insert() method
public void insert(char k)
{
if (root == null) {
root = new BTNode(k);
return;
}
BTNode<T> n = root;
BTNode<T> p = null; // parent
while (n != null) {
p = n;
if (k < n.value) {
n = n.left;
} else {
n = n.right;
}
}
if (k < p.value) {
p.left = new BTNode(k);
} else {
p.right = new BTNode(k);
height++; // adds 1 to height when a new level is made
}
}
}
BTNode Class
public class BTNode<T> {
T info;
int value, level;
BTNode<T> left, right;
public BTNode(T el) {
this(el, null, null);
}
public BTNode(T el, BTNode<T> l, BTNode<T> r) {
info = el;
left = l;
right = r;
}
}
BT Class - where the toString method is declared
public class BT<T> {
BTNode<T> root = null;
int height = 0;
public BT() {
BTNode<T> node = new BTNode("");
}
// other methods
// toString()
public String toString() {
return toString(root);
}
public String toString(BTNode<T> n) {
String s = "";
if (n == null) {
return "";
}
if (n != null) {
s = "[K=" + n.info;
if (n.left != null) {
s = s + " L=" + toString(n.left) + "]";
}
if (n.right != null) {
s = s + " R=" + toString(n.right) + "]";
}
}
return s;
}
}
Hope you can help me out, thanks!
You have quite a few issues in your code. I'll list a few immediate items but you really will need to learn to use an interactive debugger and unit testing to resolve the sorts of issues you are seeing.
You refer to the value field in BTNode in your comparison but it is never set. You should really be referring to info (which is the actual data in the node).
But given info is a generic type you can't use standard comparison operators. Instead you'll need to define it as <T extends Comparable<T>> and then use n.info.compareTo(k) > 0.
The key passed into insert should also be of type T
Which means the other classes also need to ensure T extends Comparable.
Height is only incremented when nodes are added to the right which makes no sense.
Height needs to be increased only when a node is inserted further from the root than the current maximum. Something like the following:
int depth = 0;
while (n != null) {
depth++;
p = n;
...
}
depth++;
if (depth > height)
height = depth;
You should get used to making your fields private and accessing them through getters. In your case a compareValue method would likely make sense.
I'm trying to apply insertion sort to an array of objects but my else if never compiles and says "bad operand types".
Just wondering if I need to make a very specific compareTo method or if there's a better way of comparing arrays of objects in an insertion sort method.
EDIT:
So here's me trying to use my compareTo method and it compiles but I get a null pointer exception on the else if. Why?
public static void insertElement(WordClass[] Words, int next)
{
WordClass value = Words[next];
int i = next;
while(true)
{
//
if(i == 0)
{
Words[0] = value;
break;
}
else if(Words[i-1].getStr().compareTo(value.getStr()) <= 0)
{
Words[i] = value;
break;
}
else
{
Words[i] = Words[i-1];
i--;
}
}
}
public static void insertionSort(WordClass[] Words)
{
for(int i = 1; i< Words.length; i++)
{
insertElement(Words, i);
}
}
//in WordClass
public int compareTo(WordClass w) //makes WordClass comparable
{
return getStr().compareTo(w.getStr());
}
You should always use campareTo instead of == or <= operators for object types, unless you want to campare two object variables to see if both refers to same object.
Also your WordClass class must implement the Camparable interface in order for this to work.
I need help with a Circular Doubly Linked List in Java.
This is my code (originally coded by "sanfoundry"; it uses interfaces):
LinkedList.java:
public class LinkedList<T extends Comparable<T>> implements
ILinkedList<T> {
private ILinkedListNode<T> head;
private ILinkedListNode<T> end;
private int size;
public LinkedList() {
head = null;
end = null;
head = null;
size = 0;
}
#Override
public void append(T element) {
ILinkedListNode<T> tempNode = new LinkedListNode(element, null, null);
if (head == null) {
head = tempNode;
end = head;
} else {
tempNode.setPrev(end);
tempNode.setNext(tempNode);
end = tempNode;
}
size++;
}
// should return element at position "index"
#Override
public T get(int index) {
return null;
}
#Override
public int size() {
return size;
}
#Override
public ILinkedListNode<T> getHead() {
return head;
}
}
Now I need help to get it working. Did I do something wrong and what do I have to code in method "public T get (int index)"? Sorry, but I'm a Java noob :(
EDIT: Is this a possible solution?
public T get(int index) {
T element = null;
if (index == 0) {
element = head.getElement();
} else if (index == size()-1) {
element = head.getPrev().getElement(); // end.getElement() also possible
} else {
ILinkedListNode<T> temp = head;
for (int i = 0; i < index; i++) {
temp = temp.getNext();
}
element = temp.getElement();
}
return element;
}
You should traverse the LinkedList, keeping track of your current position as you go. When your current position is equal to the index passed in, then you can return the T from that node.
Read about traversing a linked list here.
Try making some test cases. Ideally you'll want to use a real test framework but using a normal main method could work. For example:
public static void main(String[] args) {
ILinkedList<String> a = new LinkedList<String>();
System.out.println(a.size()); // 0
System.out.println(a.getHead()); // null
a.append("foo");
System.out.println(a.size()); // 1
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // decide yourself what this should result in
a.append("bar");
System.out.println(a.size()); // 2
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // "bar"
a.append("baz");
System.out.println(a.size()); // 3
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // "bar"
System.out.println(a.get(2)); // "baz"
}
Expand the test as necessary. See if the code returns what you expect it to, or if the code never returns, or throws an exception, etc.... The easiest way to check whether your code is running properly is, after all, to actually run it.
Hint: the code, as of this writing, has some errors.
Also, if the code can run as expected, consider:
Traversing the nodes backward if it's faster than forward.
Using a recursion instead of iteration.
With the below program, Java does not allow non-final variables to be used in thread to avoid "data race" unlike C++11, which makes sense. Using synchronized keyword with insertFront() would also not make sure that right value of j would get insert in list.
public class Dummy2 {
public static void main(String[] args) throws InterruptedException {
final SList list = new SList();
for(Integer j = 0; j < 10; j++){
Thread t = new Thread(new Runnable(){
public void run(){
list.insertFront(j);
}
});
t.start();
}
// not sure, how to join the threads with above code.
for(int i = 1; i <= 10; i++){
Object obj = list.nth(i);
System.out.println(obj);
}
}
}
can make this work by final Integer k = j; with inconsistent values
Here is the insertFront() operation in class SList
public synchronized void insertFront(Object obj) {
head = new SListNode(obj, head);
size++;
}
Here is nth() method
public Object nth(int position) {
SListNode currentNode;
if ((position < 1) || (head == null)) {
return null;
} else {
currentNode = head;
while (position > 1) {
currentNode = currentNode.next;
if (currentNode == null) {
return null;
}
position--;
}
return currentNode.item;
}
}
SList() {
size = 0;
head = null;
}
As of now, Please do not encourage me to use existing Java packages.
Please let me know, how can insert operation happen in SList using thread with consistent values in the above program?
Note: New to multithreading
Java does not allow non-final variables to be used in thread to avoid
"data race"
This is false. It's telling you to use a final variable because you're referencing it from within an anonymous inner class (your Runnable).
Further, final or not, your SList is never instantiated, thus your problems. Try changing
final SList list = null;
to
final SList list = new SList();
And what's an SList anyway?
Structure of my class:
public class Priorityy implement Comparable {
public int compareTo(Object pe) {
Priorityy p = (Priorityy) pe;
if (this.key < p.key) {
return 1;
} else if (this.key > p.key) {
return -1;
} else {
return 0;
}
}
}
Th problem is that p.key is always null, why exactly is that? I have my array initialized with elements in it but it always throws NullPointerException whenever I try Arrays.sort(arr).
How can I fix this?
Edit: Here is the complete code and print did print the elements of array arr:
import java.util.Arrays;
class Priorityy implements Comparable {
int size;
int front = 0;
int rear = 0;
static Priorityy[] arr = new Priorityy[3];
int key;
String value;
public Priorityy(int key, String value) {
this.key = key;
this.value = value;
insert();
}
public void insert() {
arr[front] = this;
System.out.println(arr[front].value);
while (front + 1 != 3) {
front = front + 1;
}
}
public Priorityy remove() {
Priorityy x = arr[front];
front = front - 1;
return x;
}
public int compareTo(Object pe) {
Priorityy p = (Priorityy) pe;
if (this.key < p.key) {
System.out.println(p.key);
return 1;
} else if (this.key > p.key) {
System.out.println("3");
return -1;
} else {
System.out.println("4");
return 0;
}
}
public static void main(String... s) {
new Priorityy(10, "Watch");
new Priorityy(40, "Laptop");
new Priorityy(60, "Wallet");
Arrays.sort(arr);
for (Priorityy element : arr) {
System.out.println(element.key);
System.out.println(element.value);
}
}
}
As per your code
Priorityy p = (Priorityy)pe;
^^ ---------- this is null
You have null object in the array. Handle null object gracefully.
For example
if(pe instanceof Priorityy){ // return false for null object
// your code goes here
}
Better use Generic Comparable and use Integer.compare(int,int) to compare two int values.
class Priorityy implements Comparable<Priorityy> {
public int compareTo(Priorityy pe) {
if (pe != null) {
return Integer.compare(this.key, pe.key);
} else {
// return what ever if pe is null
}
}
}
You're putting things into your array in a really strange manner.
But given that, the problem is that you're not using a static field to store the next position to insert an element into, so the next time you create an instance of Priorityy, the field first contains the value zero again. So you're inserting all three objects into element zero of the array.
Change one line of your code and it will work:
int front = 0;
To:
static int front = 0;
I don't see where you are using size and rear but you probably want these to be static too.
One other suggestion: Java has a nice short syntax for increasing or decreasing the value of a variable by one using the ++ or -- operator, so you can shorten things by saying:
front++;
instead of
front = front + 1;
(and front-- instead of front = front - 1)