I am trying to return a list of Strings of the nodes whose data is "directory" by returning its true name as children.get(0).children.get(0).data
So far, when I go through the tree, it can find the nodes and add the data that Im looking for, but as I add those strings in the List and them System.out.println the list out, the list changes. It can reset, remove Strings, etc.
Right before the return statement, I print off the list. It is not what gets returned.
!!!beforeoutput[Pictures, Pictures2.0, Pictures, Pictures2.0] //print of the list
!!!beforeoutput[Movies and Pictures, Movies, Pictures] //print of the list
getdirectories [Movies and Pictures, Movies, Pictures] //actual output
Someone had told me to define the list in the global scope, and I did, and literally nothing happened.
I guess what I'm asking for is how does one properly query through a tree. I know its recursive, but when adding the values in the list, it messes up the list.
My method's code + the console + an example tree is posted here: http://pastebin.com/9nXvcCNS
I don't understand what you are trying to actually do here, as your code is messy and fussy. You need to understand that when you return a value from a recursive function call, it will return it to a point from where it has previously been called.
If you have a structure like this,
a
| - b
| - c
where each item is represented as
class Node{
String data;
Node nextNode;
}
and would like your list to contain Strings "a", "b", and "c", you wold have to write something like this:
List<String> allDirectories = new ArrayList<String>();
getDirectories(allDirectories);
private void getDirectories(List<String> allDirectories) {
//somehow get next node
Node node = getNextNode();
//if next node is null, or terminating node: return
if (node == null) return;
allDirectories.add(node.getData());
getDirectories(allDirectories);
}
In other words, try passing your list as a parameter to a method, and don't reset it at the beginning of a function call.
Related
From a binary tree, you want to create a 2-d arraylist where each arraylist within the main arraylist contains all the nodes of a binary tree on a single level, for all of the levels. I understand how to do this recursively with DFS but I am very confused about why it possible to get the correct answer by passing in the arraylist I want to populate as a parameter in the recursive function.
The header of my recursive function looks like this
createLevelLinkedList(TreeNode current, ArrayList<LinkedList<TreeNode>> lists, int level)
With basecase:
if (current == null) return;
As the tree is traversed, the current node will be appended to its corresponding arraylist within "lists". Within the recursive function there there two recursive calls to move the function to the child nodes of current:
createLevelLinkedList(current.left, lists, level + 1);
createLevelLinkedList(current.right, lists, level + 1);
Suppose there is a tree that looks like this
5
3 8
2 4 9
With depth first tree traversal, after the first return, we will have TreeNode "2" is the top object in the stack, then "3". When TreeNode "3" is current and the function calls
createLevelLinkedList(current.right, lists, level + 1);
To push TreeNode "4" onto the stack, how can lists contains TreeNode "2" if it actually does and what is really going in memory?
The code I am referencing can be found on Github: https://github.com/gaylemcd/ctci/blob/master/java/Chapter%204/Question4_4/QuestionDFS.java
public static void createLevelLinkedList(TreeNode root, ArrayList<LinkedList<TreeNode>> lists, int level)
{
if (root == null) return;
LinkedList<TreeNode> list = null;
if (lists.size() == level) { // Level not contained in list
list = new LinkedList<TreeNode>();
/* Levels are always traversed in order. So, if this is the first time we've visited level i,
* we must have seen levels 0 through i - 1. We can therefore safely add the level at the end. */
lists.add(list);
} else {
list = lists.get(level);
}
list.add(root);
createLevelLinkedList(root.left, lists, level + 1);
createLevelLinkedList(root.right, lists, level + 1);
}
You should understand that there's only one ArrayList instance passed to the createLevelLinkedList method. Each recursive call to createLevelLinkedList receives a reference to the same instance of the ArrayList.
Therefore, once the TreeNode 2 is added to the ArrayList (or, to be exact, to one of the LinkedLists contained within the ArrayList), it stays there throughout the execution of the recursive method. It doesn't disappear when the invocation of createLevelLinkedList that added it to the list returns.
I need to implement a Trie (in Java) for a college project. The Trie should be able to add and remove Strings (for phase 1).
I have spent several hours each day (for the last few days) trying to figure out how to do this and FAILED miserably each time.
I require some help, the examples on the internet and my textbook (Data Structures and Algorithms in Java By Adam Drozdek) are not helping.
Information
Node classes I am working with:
class Node {
public boolean isLeaf;
}
class internalNode extends Node {
public String letters; //letter[0] = '$' always.
//See image -> if letter[1] = 'A' then children[1] refers to child node "AMMO"
//See image -> if letter[2] = 'B' then children[2] refers to internal node "#EU"
public TrieNode[] children = new TrieNode[2];
public TrieInternalNode(char ch)
{
letters = "#" + String.valueOf(ch);//letter[0] = '$' always.
isLeaf = false;
}
}
class leafNode extends Node
{
public String word;
public TrieLeafNode(String word)
{
this.word = new String(word);
isLeaf = true;
}
}
And here is the pseudo code for insert that I need to follow: (warning it is very vague)
trieInsert(String K)
{
i = 0;
p = the root;
while (not inserted)
{
if the end of word k is reached
set the end-of-word marker in p to true;
else if (p.ptrs[K[i]] == 0)
create a leaf containing K and put its address in p.ptrs[K[i]];
else if reference p.ptrs[K[i]] refers to a leaf
{
K_L = key in leaf p.ptrs[K[i]]
do
{
create a nonleaf and put its address in p.ptrs[K[i]];
p = the new nonleaf;
} while (K[i] == K_L[i++]);
}
create a leaf containing K and put its address in p.ptrs[K[--i]];
if the end of word k is reached
set the end-of-word marker in p to true;
else
create a leaf containing K_L and put its address in p.ptrs[K_L[i]];
else
p = p.ptrs[K[i++]];
}
}
I need to implement the following methods.
public boolean add(String word){...}//adds word to trie structure should return true if successful and false otherwise
public boolean remove(String word){...}//removes word from trie structure should return true if successful and false otherwise
I cant find pseudo code for remove, but if insert does not work delete wont help me.
Here is a image of how the Trie that I need to implement should look like.
I am aware that the Trie will still be inefficient if implemented like this, but at the moment I need not worry about this.
The book provides an implementation that is similar to what I need to do but doesn't use the end of word char ('$') and only stores the words without their prefixes in the child nodes http://mathcs.duq.edu/drozdek/DSinJava/SpellCheck.java
Constraints
I need to implement the trie in JAVA.
I may not import or use any of Java's built-in data structures. (ie. no Map, HashMap, ArrayList etc)
I may use Arrays, Java primitive Types and Java Strings.
The Trie must use a $ (dollar) symbol to indicate a end-of-word. (see the image below )
I may asume that now word containing the $symbol will be inserted.
I need to implement the Trie it in the same style as the book does.
Case of words doesn't matter ie. all words will be considered to be lowercase
The Trie should only store the end-of-word character and the characters applicable to a word and not the entire alphabet(like some implementations).
I do not expect anyone to do the implementation for me(unless they have one lying around :P) I just really need help.
First of all, I don't think you should make leaf nodes and internal nodes separate classes. I recommend making a universal node class with an isLeaf() method. This method would return true if a node has no children.
Here is some higher-level pseudocode for the functions you need to implement. For simplicity, I assume the existence of a method called getIndex() which returns the index corresponding to a character.
Insert(String str)
Node current = null
for each character in str
int index = getIndex(character)
if current.children[index] has not been initialized
initialize current.children[index] to be a new Node
current = current.children[index]
You can easily augment this pseudocode to fit your needs. For example, if you want to return false whenever insertion isn't successful:
Return false if the input string is null
Return false if the input string contains invalid characters
Now, here is some higher-level pseudocode for remove.
Remove(String str)
Node current = null
for each character in str
int index = getIndex(character)
current = current.children[index]
// At this point, we found the node we want to remove. However, we want to
// delete as many ancestor nodes as possible. We can delete an ancestor node
// if it is not need it any more. That is, we can delete an ancestor node
// if it has exactly one child.
Node ancestor = current
while ancestor is not null
if ancestor has 2 or more children
break out of loop
else if ancestor has less than 2 children
Node grandAncestor = ancestor.parent
if grandAncestor is not null
reinitialize grandAncestor.children // this has the effect of removing ancestor
ancestor = ancestor.parent
At a very high level, we follow the input string to the node we want to remove. After this, we traverse up the tree following parent pointers and delete every node with 1 child (since it is no longer needed). Once we reach a node with 2 children, we stop.
Like Insert, we can easily augment this pseudocode to return false whenever deletion isn't successful:
Return false if the input string is null
Return false if the input string contains invalid characters
Return false if the input string leads to a Node which doesn't exist
It is easiest to implement delete if your Node class has a parent field. However, it is possible to implement the method without parent points, but it is more difficult. You can see an example of the trickier implementation here.
Im currently making a shopping store application, I have 6 classes. 1 for products where it defines the fields for products in the store, another for the shopping basket, one for the GUI and the rest for listeners.
I need to be able to run a method that runs through an array list and running the to.String method on it and returning it as String. Here is what I have at the moment,
private ArrayList<OrderItem> basket = new ArrayList<OrderItem>();
public String createArrayText () {
for (int i = 0; i < OrderItem.size(); i++){
if (i == OrderItem.size() - 1){
return ordersText ;
}
}
}
ordersText is a variable I made at the top of my shopping cart class.
This was my first start at it however I'm getting a error on the .size and obviously missing some key components.
One thing Extra is that each item created is added to the array list, each item has a unique order number.
Arrays.toString(basket);
Is that what you're looking for? If not, you need to explain a little better.
You generally speaking loop over a List like this (Java 7, it's called enhanced for loop):
for (TYPE TEMP_NAME : COLLECTION) {
}
That's the overall syntax. TYPE is the type of item in the list, yours are Object's in the given code. TEMP_NAME is the temporary name you want each entry to be referred as. COLLECTION is the list/array/stack/queue or other Collection.
Concretely:
for (Object o : basket) {
// if basket contains 10 entries the line will run 10 times. each new run contains a different object with name o
}
Normally when building strings it's preferred to use StringBuilder. We can skip that as it's "only" performance that you gain from it. We'll do it with a regular String. So:
Create an empty string that will get longer and longer
Loop the collection/array/list
Append each object's .toString() to the string from 1)
e.g.
String myReturnString = "";
for (Object o : basket) {
myReturnString = myReturnString + " // " + o.toString();
}
return myReturnString;
Notes:
Your loop with an index is fine. You can do it that way too, if you want to.
The line of code that appends the string has a " // " separator between each entry. You can pick whatever you like. You can also simplify it to be myReturnString += " // " + o.toString();
I need to write my own Deque class and must used a doublylinked list implementation to store data. the problem is writing the method pushfromLeft(Thing thing) which will insert into the left side of the deque. Below is what I have thus far but does not seem to work.
public void pushLeft(Thing thing) {
Node beg = new Node();
Node end = new Node();
Node T = new Node();
if(isEmpty())
{
beg = first;
end = last;
beg = end;
T = beg.thing;
N++;
}
else
{
beg = beg.next;
end = end.next;
T = beg.previous;
N++;
}
Little you do in that method has any effect outside, except changing N and item. Presumably you should be modifying first. It would help if you provide the fields of your class, and what they mean, for context. For instance, it's not clear what item is.
You should also either come up with different conventions for naming member and local variables, or consistently use this., or both.
Might I make a suggestion that may clear a lot of this up for you. it's not what you asked for, but it may be what you need.
Use OO design, this means not operating on something but asking something to operate on itself. What this means is that Node should be more intelligent--currently you are acting on node.
Since Node is doubly linked, it can be pretty smart! It can have methods like:
newNode.insertBefore(currentNode)
newNode.insertAfter(currentNode)
currentNode.remove()
Once you have those, the rest of your code should clean up a bit. They should be trivial to implement given a doubly linked list.
void insertBefore(node existing) {
// first set my stuff up
previous = existing.previous;
next = existing;
// then point other stuff at me
previous.next = this;
existing.previous = this;
}
I think--that's just off the top of my head.
The other question is how do you handle your "Endpoints". Your first and last pointers have to be instances of Node for this to work, but if they are notice that the whole "If" factors out of your original code! Sweet!
Just ALWAYS have a first and last object that start out pointing to each other (and never take on values). When you do your first add, do first.insertAfter() or last.insertBefore() and you are done.
Another possibility, by the way, is to make the list circular--there is no reason that First and Last couldn't be the same "Special" unassigned node, you could still traverse it's Next (which will give you the first real item in the list) and Previous (giving you the last item in your list).
When iterating the entire list, if .value == null, you know you've made it to the other end which makes node.next() and previous() fascinatingly easy to implement (You don't really even need to implement .next, but see below.
/** returns null if there are no more items in the list */
Node next() {
return next;
}
Try it, it will simplify your code a LOT. Most people really don't get how useful actual OO code is.
Also, make all your variables private, it's a good habit to get into. In this case when you are having nodes operate on each other, they can still access each other's private members (not as dirty as it sounds) so you can still have the insertBefore as I wrote it AND you don't have to have getters and setters or public variables. Best of both worlds.
Also notice how your original class that "Operated" on node all but disappears--in fact, it can go away completely. If you needed some specific methods like find(item) or insertSorted(item) there is no reason you couldn't add them to node itself. This may be hard to see until after you implemented it though.
Funny how if you actually code well, most of the complaints people have about Java just don't come up.
Have you looked at the LinkedList source code as a reference?
You definitly don't need to create more than one Node inside adding method. If you want to read from left AND from right later, each Node must remember previous and next element. Then when adding, you just need to re-locate these links, like this:
public void pushLeft(Thing thing) {
Node newNode = new Node();
newNode.setValue(thing); //or just newNode.value = thing;
if(this.isEmpty())
{
this.first = this.last = newNode;
this.n=1;
}
else
{
this.first.previous = newNode;
newNode.next = this.first;
this.first = newNode;
this.n++;
}
}
It vould be wise to create a constuctor for Node class which shoul automaticaly set the value, then you can just wite:
Node newNode = new Node(thing);
My dipslay function of linked list is as follows:-
public void display()
{
cur = first;
if(isEmpty())
{
System.out.println("no elements in the list");
}
else
{
System.out.println("elements in the list are:");
do {
System.out.println(first.data);
first = first.link;
} while(first.link!=null);
first=cur;
}
where curr and first are references of class node
public class node
{
int data;
Node link=null;
}
why is this function only printing the last element?
The function looks more or less correct. However why are you setting cur to first and then using first to do the iteration? Just use cur in the iteration so you don't have to reset first.
Check to make sure you're adding nodes into the list correctly. So if you think there are 3 elements in the list, run this in display():
System.out.println(first.data);
System.out.println(first.link.data);
System.out.println(first.link.link.data);
This is to check if your links are correct.
It is not possible to say for sure, but it is probable that your list actually contains only one element; i.e. that the code that creates the list is broken.
I should also point out that the display method should use a local variable to step through the elements. If you use an instance variable (e.g. first) you are liable to get different methods interfering with each other.
Finally, your test for the end of the list is incorrect. Think carefully about what first and first.link point at when the while test is executed.