I am currently trying to implement a trie data structure for integer tuples. And have implemented as follows:
import java.util.ArrayList;
public class TrieNode {
int num;
ArrayList<TrieNode> links;
boolean endOfTuple;
public TrieNode(int num)
{
this.num = num;
links = new ArrayList<TrieNode>();
this.endOfTuple = false;
}
}
I then have a trie class as follows:
public class Trie {
TrieNode root;
public Trie() {
root = new TrieNode(-1);
}
public void insertTuple(int[] tuple)
{
int l = tuple.length;
TrieNode curNode = root;
for (int i = 0; i < l; i++)
{
TrieNode node = new TrieNode(tuple[i]);
if(!curNode.links.contains(node)){
curNode.links.add(node);
}
curNode = curNode.links.get(curNode.links.indexOf(node));
}
curNode.endOfTuple = true;
}
}
I can add values to this trie, but i need to be able to iterate over this and was wondering how i could do this? For example if i wanted to print the tree using an iterator...Any help will be great...
All you need for an interator is to implement the Iterator interface, which only requires that you supply boolean hasNext() and Integer next(). So the question to ask is: how do represent a position in your trie, such that it's possible to (a) fetch the value associated with that position, and (b) figure out the "next" position given a current one?
I'll refrain from posting an actual solution since I'm not sure whether this is homework. But consider: you can represent a "current position" in your trie just by choosing a particular trie node, and the path of trie nodes you used to reach it. Then you can compute the "next" element recursively: if the current element is a node that has children, then find the first child for which endOfTuple is true. If the current element doesn't have children, then go to its parent and advance to that parent's next child. If that parent doesn't have next children, then go it its parent's next child, etc.
Related
I'm trying to do a depth first search in Java recursively. At the moment, the code runs through my graph fine, but it never backtracks to find a route when they're are no more nodes to visit. I'm having a bit of a mental block honestly. What would be the best way to go back to the parent node?
Here is my code so far:
private final Map<Character, Node> mNodes;
private final List<Edge> mEdges;
public DepthFirstSearch(Graph graph){
mNodes = graph.getNodes();
mEdges = new ArrayList<>(graph.getEdges());
for(Node node : mNodes.values()){
node.setVisited(false);
}
}
public void depthFirstSearch(Node source){
source.setVisited(true);
List<Node> neighbours = source.getNeighbours(mEdges);
for(Node node : neighbours){
if(!node.isVisited()){
System.out.println(node.getName());
depthFirstSearch(node);
}
}
}
And the getNeighbour code:
public List<Node> getNeighbours(List<Edge> edges) {
List<Node> neighbours = new ArrayList<>();
for(Edge edge : edges){
if(edge.getFrom().equals(this)){
neighbours.add(edge.getTo());
}
}
return neighbours;
}
Added code for trying Jager's idea:
public void depthFirstSearch(Node source){
source.setVisited(true);
List<Edge> neighbours = source.getNeighbouringEdges(mEdges);
for(Edge edge : neighbours){
if(!edge.getTo().isVisited()){
System.out.println(edge.getTo().getName());
depthFirstSearch(edge.getTo());
}else{
depthFirstSearch(edge.getFrom());
}
}
}
Well, typically you have a root node that has children. Each child can have children of its own. So you would rather do:
public void depthFirstSearch(Node source)
{
for(Node node : source.getChildren())
{
System.out.println(node.getName());
depthFirstSearch(node);
// and right here you get your back tracking implicitly:
System.out.println("back at " + node.getName());
}
}
Note that I do not have a necessity for a member visited...
Edit:
Now that you provided your data structure, let me propose another approach:
class Node
{
// all that you have so far...
private char mId;
private List<Node> mChildren = new ArrayList<Node>();
public char getId()
{
return mId;
}
public List<Node> getChildren()
{
return Collections.unmodifiableList(children);
}
// appropriate methods to add new children
}
The id replaces the key of your map. Then you simply have a root Node mRoot to start with somewhere. This is the typical way to implement trees.
You might want to go up from a child node directly. Then you'd additionally need a private Node parent; in the node class (immediately being set to this when adding a child to the private list and set to null, when being removed). You won't use this for backtracking, though, so the depth first search above remains unchanged.
Guessing: you are "getting" the neighbors for mEdges which seems to be a field of the surrounding class.
Most likely, you should ask each node for its own edges upon visiting it.
I have been given an assignment to create a 2-3 search tree that is supposed to support a few different operations each divided in to different stages of the assignment.
For stage 1 I'm supposed to suport the operations get, put and size. I'm curently trying to implement the get operation but I'm stuck and I can't wrap my head around how to continue so I'm questioning all of my code I have written and felt like a need someone elses input.
I have looked around how to develop a 2-3 search tree but what I found was alot of code that made no sence to me or it just did not do what I needed it to do, and I wanted to try and make it for my self from scratch and here we are now.
My Node class
package kth.id2010.lab.lab04;
public class Node {
boolean isLeaf = false;
int numberOfKeys;
String[] keys = new String[2]; //each node can contain up to 2 keys
int[] values = new int[2]; //every key contains 2 values
Node[] subtrees = new Node[3]; //every node can contain pointers to 3 different nodes
Node(Node n) {
n.numberOfKeys = 0;
n.isLeaf = true;
}
}
My Tree creating class
package kth.id2010.lab.lab04;
public class Tree {
Node root; // root node of the tree
int n; // number of elements in the tree
private Tree(){
root = new Node(root);
n = 0;
}
//Return the values of the key if we find it
public int[] get(String key){
//if the root has no subtrees check if it contain the right key
if(this.root.subtrees.length == 0){
if(this.root.keys[0] == key){
return(this.root.keys[0].values);
}
else if(this.root.keys[1] == key){
return(this.root.keys[1].values);
}
}
//if noot in root, check its subtree nodes
//and here I can't get my head around how to traverse down the tree
else{
for(int i = 0; i < this.root.subtrees.length; i++){
for(int j = 0; j < this.root.subtrees[i].keys.length; j++){
if(this.root.subtrees[i].keys[j] == key){
return(this.root.subtrees[i].keys[j].values);
}
}
}
}
return null;
}
}
What I can tell for my self is that I need to find a way to bind values[] to each key but I can't figure out a way how. Might be the lack of sleep or that I'm stuck in this way of thinking.
bind values[] to each key
It might make more sense to use a HashMap to do that mapping for you, since that's what it's for. Beyond that, if you have two keys and each key has two values, you have 4 values, not 2 ;)
In general, the get method in a tree structure is almost always implementable recursively. Here is a very general implementation of a get algorithm for a 2-3 tree in psudo-code.
V get<K, V>(Node<K, V> node, K key)
{
if(node.is_leaf())
{
return node.keys.get(key); // This will either return the value, or null if the key isn't in the leaf and thus not in the tree
}
if(key < node.left_key)
{
return get(node.left_child, key); // If our key goes to the left, go left recursively
}
else if(node.two_node && key <= node.right_key)
{
return get(node.center_child, key) // If we have two keys, and we're less than the second one, we go down the center recursively
}
else
{
return get(node.right_child, key); // If we've gotten here, we know we're going right, go down that path recursively
}
}
That should get you started in the right direction. Insertion/deletion for 2-3 trees is a bit more complicated, but this should at least get your head around how to think about it. Hint; Your Node class needs to be doubly-linked, that is each node/leaf needs to reference its parent node as well as its children, and the root is simply a node whose parent is null.
I have a tree structure that looks like the following:
Tree {
Node root;
}
Node {
List children;
}
And I'm trying to make a method that returns the length of the longest path. I've seen some solutions that work when it's a binary tree, but there is no limit to how many children nodes each node can have and that is where I'm running into problems.
I should do somethinkg like this
int getLongestPathLength(Node node) {
if(node == null) return 0;
int max = 0;
for(Node child : node.children){
max = Math.max(getLongestPathLength(child),max);
}
return 1+max;
}
It seems what you are looking for it called the height of the root. You can see the basic algorithm to compute it here (similar to the one given in the previous answer): http://cs.nyu.edu/courses/fall02/V22.0310-002/lectures/lecture-08.html.
I am trying to make a (spanning) tree that comes naturally from traversing a graph (undirected and connected) using Breadth First Search, but I am having difficulties modifying the algorithm such that it makes a tree. I am using Java.
Here is my BFS algorithm.
public void traverse(Node node){
Queue queue= new Queue();
node.visited= true;
//Maybe do something here?
queue.enqueue(node);
while (!queue.isEmpty()){
Node r= queue.dequeue();
for (int i= 0; i < r.childen.size(); i++){
Node s= (Node)r.childen.get(i);
if (s.visited == false){
//And do something here?
s.visited= true;
queue.enqueue(s);
}
}
}
}
My graph data structure is simply this (note it's undirected and connected) :
public class Graph {
Node mainNode; ...
And the tree data structure is also simply this:
public class Tree {
Node root; ...
My Node is like this:
public class Node<T> {
T data;
boolean visited= false;
ArrayList<Node> childen= new ArrayList<Node>();
...
I think my trouble comes from the fact that I can't simply add some Node node from the graph directly to my tree (because this node would have all its children already). Instead, I have to make a new Node(node.data) so that the added node in the tree doesn't point to all the adjacent nodes that the same node would point in the graph.
So my question: how do I make a (spanning) tree out of graph while traversing the said graph using Breadth First Search?
I'm going to operate off the assumption that the graph is both undirected and connected. That being said, I think you're on the right track, but you're going to need a few more things. First, I highly encourage you to keep your search state and node implementation separate - in other words, it's not a great idea to store a private member variable Node.visible just to aid your search.
You can avoid this by maintaining some extra state inside your search method, and use a recursive private helper method to hide that state from callers of your public traverse() method. You will need to properly implement equals and hashCode in your Node class to do this.
Also - if you are wanting to create a completely separate Tree with different nodes, you'll want to essentially create new, empty instances of each Node in the Graph and first populate them with their counterpart's data, then build the tree using the cloned nodes. That said, here's some code to get you going (I haven't tested this, but it should give you an idea of what to do):
/**
* This facade method traverses just the root of the new tree. All recursion is
* passed to the "traverseHelper(3)" recursive method.
*/
public Tree<T> traverse(Graph<T> g){
if(g == null || g.mainNode == null) return null;
Node<T> node = g.mainNode;
Node<T> clone = new Node<T>(node.data); //this is the root of our new Tree
Set<Node<T>> searched = new HashSet<Node<T>>(); //accumulates searched nodes
searched.add(node);
traverseHelper(node,clone,searched);
return new Tree<T>(clone);
}
/**
* Recursively performs BFS on all the children of the specified node and its
* corresponding cloned instance.
*
* Assumes that "node" has been added to "searched" and that
* "searched.contains(node)" AND "searched.contains(clone)" will return true by
* the time this method is called.
*/
private void traverseHelper(Node<T> node, Node<T> clone, Set<Node<T>> searched){
if(node.children == null) return;
Map<Node<T>,Node<T>> toRecurseOn = new HashMap<Node<T>,Node<T>>();
//This is the Breadth-First part - builds the next leaves in the tree:
for(Node<T> child : node.children){
if(child == null || searched.contains(child)) continue;
Node<T> childClone = new Node<T>(child.data); //create leaf in the tree
clone.children.add(childClone); //builds the current level in the tree
childClone.children.add(clone); //maintains undirected-ness of the tree
toRecurseOn.put(child,childClone); //lets us BFS later
}
//This is the Search part - builds the subtrees:
Iterator<Node<T>> i = toRecurseOn.keySet().iterator();
while(i.hasNext()){
Node<T> child = i.next();
Node<T> childClone = toRecurseOn.get(child);
i.remove(); //Saves a little memory throughout the recursion
traverseHelper(child,childClone,searched);
}
}
I found a simple answer to my question. Instead of building a tree, I remove edges which lead to already visited nodes (this information we get for free as part of the BFS algorithm). Below is my implementation (it might be modified if one doesn't want to destroy the initial graph structure).
public static Tree BFS(Node node){
Queue queue= new Queue();
node.visited= true;
queue.enqueue(node);
while (!queue.isEmpty()){
Node r= queue.dequeue();
for (int i= 0; i < r.childen.size(); i++){
Node s= (Node)r.childen.get(i);
if (s.visited == false){
s.visited= true;
queue.enqueue(s);
}
else{
//Remove edge here
r.childen.remove(i);
i--;
}
}
}
Tree tree= new Tree(node);
return tree;
}
EDIT. The following is an implementation which doesn't destroy the initial graph structure by keeping a separate queue.
public static Tree BFS(Graph G, Node node){
Queue queue= new Queue();
Queue treeQueue= new Queue();
ArrayList<Node> tempV= new ArrayList<Node>();
tempV.add(node);
queue.enqueue(node);
Node root= new Node(node.data);
treeQueue.enqueue(root);
while (!queue.isEmpty()){
Node r= queue.dequeue();
Node t= treeQueue.dequeue();
for (int i= 0; i < r.childen.size(); i++){
Node s= (Node)r.childen.get(i);
if (tempV.indexOf(s) < 0){
tempV.add(s);
Node child= new Node(s.data);
t.childen.add(child);
queue.enqueue(s);
treeQueue.enqueue(child);
}
}
}
Tree tree= new Tree(root);
return tree;
}
Alright, my professor (Data Structures class) assigned this: Your task is to write a program that can update character access frequencies in a doubly-Link list. The program should read one character at a time from a text file that contain many characters. To make it easier, do not count spaces. Every time a character is accessed, increment its access frequency by one in the node of the list. If the frequency of the current node is higher than of its previous node, the two nodes need to be swapped in the list. Continue doing so for all the previous nodes until no more previous node has lower access frequency. Eventually, the character with the highest frequency will appear at the beginning of the list, the next highest will be in the next node, etc. Your program also need to print out the characters in the list according to the order of the list.
Here is the program I have made so far. It's just a doubly linked list as of right now.
My main question is how should I go about the "Every time a character is accessed, increment its access frequency by one in the node of the list. If the frequency of the current node is higher than of its previous node, the two nodes need to be swapped in the list."?
I know there aren't any lines getting the info from a file. I'm going to add that later.
Any help is appreciated!
public class DoublyLinkedList {
private class Node {
String value;
Node next,prev;
public Node(String val, Node n, Node p) {
value = val;
next = n;
prev=p;
}
Node(String val) {
this(val, null, null);
}
}
private Node first;
private Node last;
public DoublyLinkedList() {
first = null;
last = null;
}
public boolean isEmpty(){
return first==null;
}
public int size(){
int count=0;
Node p=first;
while(p!=null){
count++;
p=p.next;
}
return count;
}
public void add(String e) {
if(isEmpty()){
last=new Node(e);
first=last;
}
else{
last.next=new Node(e, null, last);
last=last.next;
}
}
public void add(int index, String e){
if(index<0||index>size()){
String message=String.valueOf(index);
throw new IndexOutOfBoundsException(message);
}
if(index==0){
Node p=first;
first=new Node(e,p,null);
if(p!=null)
p.prev=first;
if(last==null)
last=first;
return;
}
Node pred=first;
for(int k=1; k<=index-1;k++){
pred=pred.next;
}
Node succ=pred.next;
Node middle=new Node(e,succ,pred);
pred.next=middle;
if(succ==null)
last=middle;
else
succ.prev=middle;
}
public String toString(){
StringBuilder strBuilder=new StringBuilder();
Node p=first;
while(p!=null){
strBuilder.append(p.value+"\n");
p=p.next;
}
return strBuilder.toString();
}
public String remove(int index){
if(index<0||index>=size()){
String message=String.valueOf(index);
throw new IndexOutOfBoundsException(message);
}
Node target=first;
for(int k=1; k<=index;k++){
target=target.next;
}
String element=target.value;
Node pred=target.prev;
Node succ=target.next;
if(pred==null)
first=succ;
else
pred.next=succ;
if(succ==null)
last=pred;
else
succ.prev=pred;
return element;
}
public boolean remove(String element){
if(isEmpty())
return false;
Node target=first;
while(target!=null&&!element.equals(target.value))
target=target.next;
if(target==null)
return false;
Node pred=target.prev;
Node succ=target.next;
if(pred==null)
first=succ;
else
pred.next=succ;
if(succ==null)
last=pred;
else
succ.prev=pred;
return true;
}
public static void main(String[] args){
DoublyLinkedList list1=new DoublyLinkedList();
String[] array={"a","c","e","f"};
for(int i=0; i<array.length; i++){
list1.add(array[i]);
}
list1.add(1,"b");
list1.add(3,"d");
System.out.println(list1);
}
}
Since this is a homework assigment, I'll only give hints:
Your Node class needs an extra field for a counter.
You need to iterate through the list to find the accessed character and increment its counter value.
You need a temporary Node object to swap nodes. Try it yourself first, then google it. It's an essential process every programmer must know.
I would recommend breaking down the procedure into the component parts. You know you need to keep and update a count, as Sebastian says above. You also know you need to be able to compare a node's count with the count of the node above it in the rankings. You know you need to be able to swap two nodes. You should have methods for those things. Think through what needs to happen in each broken-down method.
I always recommend a physical approach for these kinds of problems to get a feel for them: Try doing this with a set of note cards or post-it notes. On each one, write an object name and the fields for the Node object. Write field values in pencil. Jot down other fields (like the reference to the first element) on a sheet of paper. Then step through your algorithm and see what needs to change on each update. (note: Because this is a doubly-linked list, your changes should survive shuffling your stack of cards. Try that and see)
Good luck with the assignment!
Advice:
"I know there aren't any lines getting the info from a file.". You would be better off writing that code now, so that you can test what you have already written.
The other problem is that what you have written so far is a generic linked list, ignoring the requirement which say how the list is to be used. As a result, you have:
implemented a bunch of methods that appear to be unnecessary, and
not implemented the Node class correctly for the requirements.
Go back and look at the requirements, and work out what methods you actually need, and then implement them. (What you have done so far is a "bottom up" design that is largely ignoring what the top level needs. You would have been better of with a "top down" approach.)
The problem you are asked to solve is collating characters, not creating a "general purpose" linked list data structure.