I need to navigate my 23Tree and print all the levels and corresponding elements. However, my recursion goes in any one direction and does not return and perform other calls. Any help would be much appreciated.
Here is my node class:
class Node<T extends Comparable<T>> {
List<T> vals = new ArrayList<T>();
List<Node<T>> children = new ArrayList<Node<T>>();
boolean isLeaf() { return children.size() == 0; }
boolean is4Node() { return vals.size() == 3; }
// new Nodes always are 2-nodes (1 value). The node may be
// a leaf, or has 2 children.
Node(T x) {
vals.add(x);
}
Node(T x, Node<T> left, Node<T> right) {
vals.add(x);
children.add(left);
children.add(right);
children.add(null); // hack
}
This is my recursive function to print the nodes:
private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root){
System.out.println("present element: " + root);
if(root.vals.size() == 1 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0));
}else if(root.vals.size() == 2 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0) + "/" + root.vals.get(1));
}
if(root.children.get(0) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "left", (Node) root.children.get(0));
}
if(root.children.get(1) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "middle", (Node) root.children.get(1));
}
if(root.children.get(2) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "right", (Node) root.children.get(2));
}
return true;
}
And here is the output:
present element: [[[a]b[c]]d, [[e]f[g]]h[[i]j, [k]y[z]]]
Level = 0 [root] value = d/h
present element: [[a]b[c]]
Level = 1 [left] value = b
present element: [a]
Level = 2 [left] value = a
(Edit) Here is my main method:
public static void main(String[] args) {
StringTwoThreeTree set = new StringTwoThreeTree();
try{
String line = null;
FileReader fileReader =
new FileReader("C:\\Users\\Redoubt\\IdeaProjects\\23Tree\\src\\resources\\test.dat");
// new FileReader("C:\\Users\\Redoubt\\IdeaProjects\\23Tree\\src\\resources\\a4q1search.txt");
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader =
new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
set.insert(line);
}
// System.out.println("\n\n\n");
String str = set.toString();
// System.out.println(str);
set.print();
}catch (Exception e){
}
}
and the contents of the file test.dat :
a
a
b
c
d
e
f
g
h
i
j
k
y
z
Just for clarity, I'm adding the 2 large classes as well:
StringTwoThree class:
import java.util.List;
public class StringTwoThreeTree extends TwoThreeTree<String> {
#Override
public String toString() {
return super.toString();
}
public void insert(String str){
super.add(str);
}
public void print(){
Node root = super.root;
// System.out.println(root.vals);
// dumpList("",root);
iterateChildrenAndPrintPerLevelAndLevelType(0, "root", root);
super.displayLevelWise();
}
private void dumpList(String string, Node list) {
int i = 0;
for (Object item : list.children) {
if (item instanceof List) {
dumpList(string + i, (Node) item);
} else {
System.out.println(String.format("%s%d %s", string, i, item));
}
++i;
}
}
private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root){
System.out.println("present element: " + root);
if(root.vals.size() == 1 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0));
}else if(root.vals.size() == 2 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0) + "/" + root.vals.get(1));
}
if(root.children.get(0) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "left", (Node) root.children.get(0));
}
if(root.children.get(1) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "middle", (Node) root.children.get(1));
}
if(root.children.get(2) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "right", (Node) root.children.get(2));
}
return true;
}
}
TwoThreeTree class:
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Queue;
public class TwoThreeTree<T extends Comparable<T>> implements Iterable<T> {
// a Node has 1 (2-Node) or 2 (3-Node) values
// and 2 or 3 children. Values and children are stored
// in ArrayLists. If there are children, that ArrayList
// has a null element at the end, so as to make easier the
// method which adds a new child.
class Node<T extends Comparable<T>> {
List<T> vals = new ArrayList<T>();
List<Node<T>> children = new ArrayList<Node<T>>();
boolean isLeaf() { return children.size() == 0; }
boolean is4Node() { return vals.size() == 3; }
// new Nodes always are 2-nodes (1 value). The node may be
// a leaf, or has 2 children.
Node(T x) {
vals.add(x);
}
Node(T x, Node<T> left, Node<T> right) {
vals.add(x);
children.add(left);
children.add(right);
children.add(null); // hack
}
public String toString() {
String answer = "[";
for (int i=0; i<vals.size(); i++) {
if (i != 0) answer += ", ";
if (children.size() != 0)
answer += children.get(i).toString();
answer += vals.get(i);
}
if (children.size() != 0)
answer += children.get(children.size()-2).toString();
return answer + "]";
}
// used in Iterator
void getVals(List<T> iteratorList) {
for (int i=0; i<vals.size(); i++) {
if (children.size() != 0)
children.get(i).getVals(iteratorList);
iteratorList.add(vals.get(i));
}
if (children.size() != 0)
children.get(children.size()-2).getVals(iteratorList);
}
// recursively adds a new value to a subtree
boolean add(T val) {
if (isLeaf())
return addToLeaf(val);
else return addToInterior(val);
}
// new values are always added to a leaf. The result may be a 4-node leaf.
boolean addToLeaf(T x) {
int cmp;
// size is 1 for a 2-node, or 2 for a 3-node
for (int i = 0; i < vals.size(); i++) {
cmp = x.compareTo(vals.get(i));
if (cmp == 0) return false;
else if (cmp < 0) {
vals.add(i,x);
return true;
}
}
vals.add(x);
return true;
}
// adds a value to a subtree rooted by an interior node. If
// the addition results in one of the children being a 4-node,
// then adjustments are made.
boolean addToInterior(T x) {
int cmp;
// size is 1 for a 2-node, or 2 for a 3-node
for (int i = 0; i <= vals.size(); i++) {
if (i == vals.size()) cmp = -1; // hack because there is no vals[2]
else cmp = x.compareTo(vals.get(i));
if (cmp == 0) return false;
else if (cmp < 0) {
boolean retVal = children.get(i).add(x);
if (children.get(i).is4Node())
childIs4Node(i);
return retVal;
}
}
return false; // unreachable -- just for compiler
}
// the ith child is a 4-node
void childIs4Node(int i) {
Node<T> the4Node = children.get(i);
// move the middle value from the 4-node child up
// to its parent
if (i == 2)
vals.add(children.get(i).vals.get(1));
else vals.add(i, children.get(i).vals.get(1));
Node<T> newChild1, newChild2;
if (children.get(i).isLeaf()) {
newChild1 = new Node<T>(children.get(i).vals.get(0));
newChild2 = new Node<T>(children.get(i).vals.get(2));
}
else {
newChild1 = new Node<T>(children.get(i).vals.get(0),
children.get(i).children.get(0),
children.get(i).children.get(1));
newChild2 = new Node<T>(children.get(i).vals.get(2),
children.get(i).children.get(2),
children.get(i).children.get(3));
}
children.remove(the4Node);
children.add(i, newChild2);
children.add(i, newChild1);
}
}
Node<T> root;
public TwoThreeTree() {
root = null;
}
// TwoThreeTree add
public boolean add(T val) {
if (root == null) {
root = new Node<T>(val);
return true;
}
else {
boolean isNew = root.add(val);
// if root is a 4-node, split it
if (root.vals.size() == 3) {
Node<T> left, right;
if (root.isLeaf()) {
left = new Node<T>(root.vals.get(0));
right = new Node<T>(root.vals.get(2));
}
else {
left = new Node<T>(root.vals.get(0),
root.children.get(0),
root.children.get(1));
right = new Node<T>(root.vals.get(2),
root.children.get(2),
root.children.get(3));
}
root = new Node<T>(root.vals.get(1), left, right);
}
return isNew;
}
}
// this method creates a list containing all of the values in
// the tree and returns that list's iterator
public Iterator<T> iterator() {
List<T> vals = new ArrayList<T>();
if (root != null) root.getVals(vals);
return vals.iterator();
}
public String toString(){
String result = "[";
for (T item : this
) {
result += item.toString() + ",";
}
result = result.substring(0,result.length()-1);
result += "]";
return result;
}
public void displayLevelWise(){
}
}
Your index is going out of bound in your private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root) method.
Related
I have to implement binary search tree with method that prints nice diagram with connections like this:
For now I managed to print this:
However I'm struggling to make it better :/
Do you have any hints how to fix that?
It's my code of instance implementing it:
public interface PrintableTree {
class Node {
int data;
Node left, right;
Node(int data) {
this.data = data;
this.left = null;
this.right = null;
}
}
class Trunk {
Trunk prev;
String str;
Trunk(Trunk prev, String str) {
this.prev = prev;
this.str = str;
}
}
Node insert_Recursive(Node root, int key);
void add(int i);
String prettyPrint();
static PrintableTree getInstance() {
return new PrintableTree() {
String stringOfTree = "";
static final int COUNT = 2;
Node root;
#Override
public void add(int i) {
root = insert_Recursive(root, i);
}
#Override
public Node insert_Recursive(Node root, int key) {
if (root == null) {
root = new Node(key);
return root;
}
if (key < root.data)
root.left = insert_Recursive(root.left, key);
else if (key > root.data)
root.right = insert_Recursive(root.right, key);
return root;
}
#Override
public String prettyPrint() {
printTree(root, null, false);
return "";
}
public void showTrunks(Trunk p) {
if (p == null) {
return;
}
showTrunks(p.prev);
System.out.print(p.str);
}
public void printTree(Node root, Trunk prev, boolean isLeft) {
if (root == null) {
return;
}
String prev_str = " ";
Trunk trunk = new Trunk(prev, prev_str);
printTree(root.left, trunk, true);
if (prev == null) {
trunk.str = "";
} else if (isLeft) {
trunk.str = "┌";
prev_str = " │";
} else {
trunk.str = "└";
prev.str = prev_str;
}
showTrunks(trunk);
System.out.println(" " + root.data);
if (prev != null) {
prev.str = prev_str;
}
trunk.str = " │";
printTree(root.right, trunk, false);
}
};
}
}
You could use these functions. They return a string, so it is up to the caller to print it.
I also find it nicer when the right subtree is printed upwards, and the left subtree downwards. That way, the tree is just rotated 90° from how it is usually depicted -- with the root at the top.
Here is the relevant code:
public String pretty() {
return pretty(root, "", 1);
}
private String pretty(Node root, String prefix, int dir) {
if (root == null) {
return "";
}
String space = " ".repeat(("" + root.data).length());
return pretty(root.right, prefix + "│ ".charAt(dir) + space, 2)
+ prefix + "└ ┌".charAt(dir) + root.data
+ " ┘┐┤".charAt((root.left != null ? 2 : 0)
+ (root.right != null ? 1 : 0)) + "\n"
+ pretty(root.left, prefix + " │".charAt(dir) + space, 0);
}
I am trying to implement a max priority queue using a heap binary tree with a triple-linked node. This is the code that I currently have yet when I run it and try to print out the tree nothing prints out it is just empty lines. I am using the helped methods sink and swim in order to help me organize the queue as I add different elements. I am also implementing an ADT (MaxPQ) which just has the public methods that need to be implemented. I was wondering if there is anything that I am doing wrong?
public class LinkedMaxPQ<T extends Comparable<T>> implements MaxPQ<T> {
// Instance variables
Node root;
int size;
Node lastInserted;
// Node inner class definition
// Node class
class Node {
int N;
T info;
Node left;
Node right;
Node parent;
Node(T info, int N) {
this.info = info; this.N = N;
}
}
private void swim(Node x){
if(x == null) return;
if(x.parent == null) return; // we're at root
int cmp = x.info.compareTo(x.parent.info);
if(cmp > 0){
swapNodeData(x, x.parent);
swim(x.parent);
}
}
private void swapNodeData(Node x, Node y){
T temp = x.info;
x.info = y.info;
y.info = temp;
}
private void sink(Node x){
if(x == null) return;
Node swapNode;
if(x.left == null && x.right == null){
return;
}
else if(x.left == null){
swapNode = x.right;
int cmp = x.info.compareTo(swapNode.info);
if(cmp < 0)
swapNodeData(swapNode, x);
} else if(x.right == null){
swapNode = x.left;
int cmp = x.info.compareTo(swapNode.info);
if(cmp < 0)
swapNodeData(swapNode, x);
} else{
int cmp = x.left.info.compareTo(x.right.info);
if(cmp >= 0){
swapNode = x.left;
} else{
swapNode = x.right;
}
int cmpParChild = x.info.compareTo(swapNode.info);
if(cmpParChild < 0) {
swapNodeData(swapNode, x);
sink(swapNode);
}
}
}
String printThisLevel (Node rootnode, int level) {
StringBuilder s = new StringBuilder();
// Base case 1: if the current rootnode is null, return the current string.
if (rootnode == null) {
return s.toString();
}
// Base case 2: If you're at the first level, append the
// info field of the current rootnode.
if (level == 1) {
s.append( rootnode.info.toString());
}
// Recursive calls: otherwise call the method on the left
// and on the right of the next lower level.
else if (level > 1) {
s.append( printThisLevel(rootnode.left, level-1));
s.append( printThisLevel(rootnode.right, level-1));
}
return s.toString();
}
private int size(Node x){
if(x == null) return 0;
return x.N;
}
private Node insert(Node x, T data){
if(x == null){
lastInserted = new Node(data, 1);
return lastInserted;
}
// compare left and right sizes see where to go
int leftSize = size(x.left);
int rightSize = size(x.right);
if(leftSize <= rightSize){
// go to left
Node inserted = insert(x.left, data);
x.left = inserted;
inserted.parent = x;
} else{
// go to right
Node inserted = insert(x.right, data);
x.right = inserted;
inserted.parent = x;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
private Node resetLastInserted(Node x){
if(x == null) return null;
if(x.left == null && x.right == null) return x;
if(size(x.right) < size(x.left))return resetLastInserted(x.left);
else return resetLastInserted(x.right);
}
public void insert(T data){
root = insert(root, data);
swim(lastInserted);
}
public T getMax(){
if(root == null) return null;
return root.info;
}
public T removeMax(){
if(size() == 1){
T ret = root.info;
root = null;
return ret;
}
swapNodeData(root, lastInserted);
Node lastInsParent = lastInserted.parent;
T lastInsData = lastInserted.info;
if(lastInserted == lastInsParent.left){
lastInsParent.left = null;
} else{
lastInsParent.right = null;
}
Node traverser = lastInserted;
while(traverser != null){
traverser.N--;
traverser = traverser.parent;
}
lastInserted = resetLastInserted(root);
sink(root);
return lastInsData;
}
public int size(){
return size(root);
}
public boolean isEmpty(){
return size() == 0;
}
public String toString() {
// Create a StringBuilder object to make it more efficient.
StringBuilder sb=new StringBuilder();
// get the height of the tree
int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));
// for each level in the tree, call printThisLevel and
// append the output to the StringBuilder
for (int i=1; i<=height; i++) {
sb.append("level " + i + ": "+ printThisLevel(this.root, i) + "\n");
}
// Return the string of the StringBuilder object
return sb.toString();
}
public static void main (String[] args) {
LinkedMaxPQ<String> t = new LinkedMaxPQ<String>();
t.insert("a");
System.out.println(t.toString());
t.insert("b");
t.insert("c");
t.insert("d");
t.insert("e");
t.insert("f");
t.insert("g");
t.insert("h");
t.insert("i");
t.insert("j");
t.insert("k");
t.size();
t.removeMax();
t.getMax();
t.removeMax();
t.insert("x");
t.insert("y");
t.removeMax();
t.getMax();
System.out.println(t.toString());
}
}
In this line:
int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));
size should be size().
int height = (int)Math.ceil(Math.log(size()+1) / Math.log(2));
After this correction, the results are coming out.
However, there is a logic problem, which needs a solution.
For test case, testdata = new int[] {3, 5, 2, -7, 9, 4, 7};
The result is 9 4 7 -7 3 2 5
But correct result should be 9 5 7 -7 3 2 4 (from another array implementation).
I know the mistake comes from when at the 3rd levle, insert data {9}, its parent should be the 2nd leverl data {3} on the left, not the {2} on the right. Any thought to solve it?
I am trying to return the data held by the nth item of a BST, I'm trying to do an inorder traversal with a counter, and when the counter is larger than n, return the current node. My current code seems to always return the first item, and I can't see where my logic is wrong. I only wrote the nth and inOrder methods, the rest were provided. I think I'm incrementing my counter too often, is that the cause or am I doing something else wrong. I'll post the main method I'm testing with below as well.
import java.util.NoSuchElementException;
public class BST {
private BTNode<Integer> root;
public BST() {
root = null;
}
public boolean insert(Integer i) {
BTNode<Integer> parent = root, child = root;
boolean goneLeft = false;
while (child != null && i.compareTo(child.data) != 0) {
parent = child;
if (i.compareTo(child.data) < 0) {
child = child.left;
goneLeft = true;
} else {
child = child.right;
goneLeft = false;
}
}
if (child != null)
return false; // number already present
else {
BTNode<Integer> leaf = new BTNode<Integer>(i);
if (parent == null) // tree was empty
root = leaf;
else if (goneLeft)
parent.left = leaf;
else
parent.right = leaf;
return true;
}
}
public int greater(int n) {
if (root == null) {
return 0;
}
else {
return n;
}
}
int c = 0;
public int nth(int n) throws NoSuchElementException {
BTNode<Integer> node = null;
if (root == null) {
throw new NoSuchElementException("Element " + n + " not found in tree");
}
else {
if (root != null){
node = inOrder(root, n);
}
}
return node.data;
}
public BTNode inOrder(BTNode<Integer> node, int n) {
c++;
while (c <= n) {
if (node.left != null) {
inOrder(node.left, n);
}
c++;
if (node.right != null) {
inOrder(node.right, n);
}
}
return node;
}
}
class BTNode<T> {
T data;
BTNode<T> left, right;
BTNode(T o) {
data = o;
left = right = null;
}
}
public class bstTest {
public static void main(String[] args) {
BST tree = new BST();
tree.insert(2);
tree.insert(5);
tree.insert(7);
tree.insert(4);
System.out.println(tree.nth(2));
}
}
An invariant you should consider is that when n = sizeOfLeftSubtree + 1, then return that node. If n is less, then go left. If n is greater, then go right and reduce n by sizeOfLeftSubtree+1. Note that I map n=1 to the first element (the leftmost element).
You could trivially calculate the size of a subtree recursively, or you can store the size at every root (every node is a root of a subtree) modifying you insert method (save in a stack/queue all nodes visited and if a new node is added just increment all sizes by 1).
If the size is stored the complexity will be O(log n). If not if could become O(n^2).
public int nth(int n) throws NoSuchElementException {
if( sizeOfTree(this.root) < n || n < 1)
throw new NoSuchElementException("Element " + n + " not found in tree");
BTNode<Integer> root = this.root;
boolean found = false;
do{
int sizeOfLeftSubtree = sizeOfTree(root.left);
if( sizeOfLeftSubtree + 1 == n ){
found = true;
}else if( n < sizeOfLeftSubtree+1 ){
root = root.left;
}else if( sizeOfLeftSubtree+1 < n ){
root = root.right;
n -= sizeOfLeftSubtree+1;
}
}while( !found );
return root.data;
}
public int sizeOfTree(BTNode<Integer> root){
if( root == null )
return 0;
else
return sizeOfTree(root.left) + 1 + sizeOfTree(root.right);
}
You don't change node in the inOrder method.
public BTNode inOrder(BTNode<Integer> node, int n) {
c++;
while (c <= n) {
if (node.left != null) {
// **** Add this - or something.
node = inOrder(node.left, n);
}
c++;
if (node.right != null) {
// **** Add this - or something.
node = inOrder(node.right, n);
}
}
return node;
}
Not suggesting this is the bug you are trying to fix but it is certainly a problem with the code.
I am trying ti implement the insert method of the Patricia Trie data structure but I have the feeling I wrote to many code lines. Please can someone tell me where can I call the method insert(TrieNode nodeRoot, String s) rekursiv?
Code:
private void insert(TrieNode nodeRoot, String s) {
int len1 = nodeRoot.value.length();
int len2 = s.length();
int len = Math.min(len1, len2);
for (int index = 0; index < len; index++) {
if (s.charAt(index) != nodeRoot.value.charAt(index)) {
// In case the both words have common substrings and after the
// common substrings the words are split.
String samesubString = s.substring(0, index);
String substringSplit1 = nodeRoot.value.substring(index);
String substringSplit2 = s.substring(index);
if (!samesubString.isEmpty()) {
nodeRoot.value = samesubString;
}
TrieNode nodeLeft = new TrieNode(substringSplit1);
nodeLeft.isWord = true;
TrieNode nodeRight = new TrieNode(substringSplit2);
nodeRight.isWord = true;
if (nodeRoot.getNext() != null && !nodeRoot.getNext().isEmpty()) {
checkTheValieAvialable(nodeRoot, s, nodeRight);
} else {
nodeRoot.next.add(nodeLeft);
nodeRoot.next.add(nodeRight);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
break;
} else if (index == (s.length() - 1)
|| index == (nodeRoot.value.length() - 1)) {
// In case the node just needs one path since one word is
// substring of the other.
// For example (aba and abac)
if (len1 > len2) {
// root value is longer
System.out.println("root value is longer");
String samesubString = nodeRoot.value.substring(0,
index + 1);
String different = nodeRoot.value.substring(index + 1);
if (nodeRoot.getNext() != null
&& !nodeRoot.getNext().isEmpty()) {
for (TrieNode subword : nodeRoot.getNext()) {
String subword2 = subword.getValue();
boolean contains = different.contains(subword2);
if (contains) {
String[] split = different.split(subword2);
TrieNode leaf1 = new TrieNode(split[1]);
leaf1.isWord = true;
subword.next.add(leaf1);
System.out.println("Test.");
}
}
} else {
String substringSplit1 = nodeRoot.value.substring(index + 1);
nodeRoot.value = samesubString;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
String substringSplit1 = nodeRoot.value
.substring(index + 1);
nodeRoot.value = samesubString;
nodeRoot.isWord = true;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
} else {
// new inserted string value is longer. For example (abac and aba).
System.out.println("instered is longer");
String samesubString = s.substring(0, index + 1);
String different = s.substring(index + 1);
if (nodeRoot.getNext() != null
&& !nodeRoot.getNext().isEmpty()) {
for (TrieNode subword : nodeRoot.getNext()) {
String subword2 = subword.getValue();
boolean contains = different.contains(subword2);
if (contains) {
String[] split = different.split(subword2);
TrieNode leaf1 = new TrieNode(split[1]);
leaf1.isWord = true;
subword.next.add(leaf1);
System.out.println("Test.");
}
}
} else {
String substringSplit1 = s.substring(index + 1);
s = samesubString;
TrieNode parentLeaf = new TrieNode(s);
parentLeaf.isWord = true;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
}
} else {
System.out.println("They are the same - " + index);
}
}
}
TrieNode class:
package patriciaTrie;
import java.util.ArrayList;
public class TrieNode {
ArrayList<TrieNode> next = new ArrayList<TrieNode>();
String value;
boolean isWord;
TrieNode(String value){
this.value = value;
}
public ArrayList<TrieNode> getNext() {
return next;
}
public void setNext(ArrayList<TrieNode> next) {
this.next = next;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
While using recursion please consider the steps:
Base condition
Logic (if any)
Recursive call.
Ex. for factorial of number:
int fact(int n)
{
if(n==0 || n==1)
return 1; // Base condition
return n * fact(n-1); // Recursive call
}
Applying the same concept in Trie:
base condition is: while traversing through a path, if we have reached leaf, current string is not in trie, then create a new edge or node and add remaining character to it.
Recursively call the insert if we have found a matching node. And if a matching node doen't exist create a new path with common parent.
You can take help from link : http://www.geeksforgeeks.org/trie-insert-and-search/
The best way to approach to problem recursively is to identify base condition in a problem.
I'm trying to work on a method that will insert the node passed to it before the current node in a linked list. It has 3 conditions. For this implementation there cannot be any head nodes (only a reference to the first node in the list) and I cannot add any more variables.
If the list is empty, then set the passed node as the first node in the list.
If the current node is at the front of the list. If so, set the passed node's next to the current node and set the first node as the passed node to move it to the front.
If the list is not empty and the current is not at the front, then iterate through the list until a local node is equal to the current node of the list. Then I carry out the same instruction as in 2.
Here is my code.
public class LinkedList
{
private Node currentNode;
private Node firstNode;
private int nodeCount;
public static void main(String[] args)
{
LinkedList test;
String dataTest;
test = new LinkedList();
dataTest = "abcdefghijklmnopqrstuvwxyz";
for(int i=0; i< dataTest.length(); i++) { test.insert(new String(new char[] { dataTest.charAt(i) })); }
System.out.println("[1] "+ test);
for(int i=0; i< dataTest.length(); i++) { test.deleteCurrentNode(); }
System.out.println("[2] "+test);
for(int i=0; i< dataTest.length(); i++)
{
test.insertBeforeCurrentNode(new String(new char[] { dataTest.charAt(i) }));
if(i%2 == 0) { test.first(); } else { test.last(); }
}
System.out.println("[3] "+test);
}
public LinkedList()
{
setListPtr(null);
setCurrent(null);
nodeCount = 0;
}
public boolean atEnd()
{
checkCurrent();
return getCurrent().getNext() == null;
}
public boolean isEmpty()
{
return getListPtr() == null;
}
public void first()
{
setCurrent(getListPtr());
}
public void next()
{
checkCurrent();
if (atEnd()) {throw new InvalidPositionInListException("You are at the end of the list. There is no next node. next().");}
setCurrent(this.currentNode.getNext());
}
public void last()
{
if (isEmpty()) {throw new ListEmptyException("The list is currently empty! last()");}
while (!atEnd())
{
setCurrent(getCurrent().getNext());
}
}
public Object getData()
{
return getCurrent().getData();
}
public void insertBeforeCurrentNode(Object bcNode) //beforeCurrentNode
{
Node current;
Node hold;
boolean done;
hold = allocateNode();
hold.setData(bcNode);
current = getListPtr();
done = false;
if (isEmpty())
{
setListPtr(hold);
setCurrent(hold);
}
else if (getCurrent() == getListPtr())
{
System.out.println("hi" + hold);
hold.setNext(getCurrent());
setListPtr(hold);
}
else //if (!isEmpty() && getCurrent() != getListPtr())
{
while (!done && current.getNext() != null)
{
System.out.println("in else if " + hold);
if (current.getNext() == getCurrent())
{
//previous.setNext(hold);
//System.out.println("hi"+ "yo" + " " + getListPtr());
hold.setNext(current.getNext());
current.setNext(hold);
done = true;
}
//previous = current;
current = current.getNext();
}
}
System.out.println(getCurrent());
}
public void insertAfterCurrentNode(Object acNode) //afterCurrentNode
{
Node hold;
hold = allocateNode();
hold.setData(acNode);
if (isEmpty())
{
setListPtr(hold);
setCurrent(hold);
//System.out.println(hold + " hi");
}
else
{
//System.out.println(hold + " hia");
hold.setNext(getCurrent().getNext());
getCurrent().setNext(hold);
}
}
public void insert(Object iNode)
{
insertAfterCurrentNode(iNode);
}
public Object deleteCurrentNode()
{
Object nData;
Node previous;
Node current;
previous = getListPtr();
current = getListPtr();
nData = getCurrent().getData();
if (isEmpty()) {throw new ListEmptyException("The list is currently empty! last()");}
else if (previous == getCurrent())
{
getListPtr().setNext(getCurrent().getNext());
setCurrent(getCurrent().getNext());
nodeCount = nodeCount - 1;
}
else
{
while (previous.getNext() != getCurrent())
{
previous = current;
current = current.getNext();
}
previous.setNext(getCurrent().getNext());
setCurrent(getCurrent().getNext());
nodeCount = nodeCount - 1;
}
return nData;
}
public Object deleteFirstNode(boolean toDelete)
{
if (toDelete)
{
setListPtr(null);
}
return getListPtr();
}
public Object deleteFirstNode()
{
Object deleteFirst;
deleteFirst = deleteFirstNode(true);
return deleteFirst;
}
public int size()
{
return this.nodeCount;
}
public String toString()
{
String nodeString;
Node sNode;
sNode = getCurrent();
//System.out.println(nodeCount);
nodeString = ("List contains " + nodeCount + " nodes");
while (sNode != null)
{
nodeString = nodeString + " " +sNode.getData();
sNode = sNode.getNext();
}
return nodeString;
}
private Node allocateNode()
{
Node newNode;
newNode = new Node();
nodeCount = nodeCount + 1;
return newNode;
}
private void deAllocateNode(Node dNode)
{
dNode.setData(null);
}
private Node getListPtr()
{
return this.firstNode;
}
private void setListPtr(Node pNode)
{
this.firstNode = pNode;
}
private Node getCurrent()
{
return this.currentNode;
}
private void setCurrent(Node cNode)
{
this.currentNode = cNode;
}
private void checkCurrent()
{
if (getCurrent() == null) {throw new InvalidPositionInListException("Current node is null and is set to an invalid position within the list! checkCurrent()");}
}
/**NODE CLASS ----------------------------------------------*/
private class Node
{
private Node next; //serves as a reference to the next node
private Object data;
public Node()
{
this.next = null;
this.data = null;
}
public Object getData()
{
return this.data;
}
public void setData(Object obj)
{
this.data = obj;
}
public Node getNext()
{
return this.next;
}
public void setNext(Node nextNode)
{
this.next = nextNode;
}
public String toString()
{
String nodeString;
Node sNode;
sNode = getCurrent();
//System.out.println(nodeCount);
nodeString = ("List contains " + nodeCount + " nodes");
while (sNode != null)
{
nodeString = nodeString + " " +sNode.getData();
sNode = sNode.getNext();
}
return nodeString;
}
}
}
I have it working for my [1] and [2] conditions. But my [3] (that tests insertBeforeCurrentNode()) isn't working correctly. I've set up print statements, and I've determined that my current is reset somewhere, but I can't figure out where and could use some guidance or a solution.
The output for [1] and [2] is correct. The output for [3] should read
[3] List contains 26 nodes: z x v t r p n l j h f d b c e g i k m o q s u w y a
Thanks for any help in advance.
In your toString method you start printing nodes from the currentNode till the end of your list. Because you call test.last() just before printing your results, the currentNode will point on the last node of the list, and your toString() will only print 'a'.
In your toString() method, you may want to change
sNode = getCurrent();
with
sNode = getListPtr();
to print your 26 nodes.
For [3] you need to keep pointers to two nodes: one pointer in the "current" node, the one you're looking for, and the other in the "previous" node, the one just before the current. In that way, when you find the node you're looking in the "current" position, then you can connect the new node after the "previous" and before the "current". In pseudocode, and after making sure that the cases [1] and [2] have been covered before:
Node previous = null;
Node current = first;
while (current != null && current.getValue() != searchedValue) {
previous = current;
current = current.getNext();
}
previous.setNext(newNode);
newNode.setNext(current);