I am trying to find a way to keep track of the maximum value in my code. Right now I know that my for-loop looks at every node in my tree and compares it to the last max. But my issue is as the function calls are popped off the stack I end up only evaluating the first set of children and my max is chosen from those rather than the whole tree. The nodes can have any number of children and a payload.
public static Integer max(TreeNode<Integer> root) {
if (root == null) {
return null;
}
int maximum = root.payload;
if (root != null) {
for (int i = 0; i < root.children.size(); i++) {
if (root.children.get(i).payload > maximum) {
maximum = root.children.get(i).payload;
}
max(root.children.get(i));
}
}
return maximum;
}
tree example:
1
4 6 7
9 10 11 12
Max:12
My Max:7
public class TreeNode<T> {
public ArrayList<TreeNode<T>> children;
public T payload;
}
You could try this
public static Integer max(TreeNode<Integer> root) {
if (root == null) {
return null;
}
if (root.children == null) {
return null;
}
int maximum = root.payload;
for (int i = 0; i < root.children.size(); i++) {
if (root.children.get(i).payload > maximum) {
maximum = root.children.get(i).payload;
}
Integer childsMaximun = max(root.children.get(i));
if ((childsMaximun != null) && (childsMaximun > maximum)){
maximum = childsMaximun;
}
}
return maximum;
}
You need to add contructor to initialize an ArrayList, try my TreeNode class:
public class TreeNode<T> {
public T payload;
public List<TreeNode<T>> children;
public TreeNode(T payload) {
this.payload = payload;
children = new ArrayList<>();
}
public void addChildren(T... childs){
for (T child: childs){
TreeNode<T> node = new TreeNode<>(child);
children.add(node);
}
}
public void addChildren(TreeNode<T>... childs){
for (TreeNode<T> child: childs){
children.add(child);
}
}
public static TreeNode<Integer> DEFAULT(){
TreeNode<Integer> root7 = new TreeNode<>(7);
root7.addChildren(10,11,12);
TreeNode<Integer> root6 = new TreeNode<>(6);
TreeNode<Integer> root4 = new TreeNode<>(4);
root4.addChildren(9);
TreeNode<Integer> root1 = new TreeNode<>(1);
root1.addChildren(root7, root6, root4);
return root1;
}
}
public static int maximum(TreeNode<Integer> t) {
if (t == null) {
return 0;
}
int max = t.payload;
List<TreeNode<Integer>> children = t.children;
if (children != null && children.size() > 0) {
for (TreeNode<Integer> e: children) {
// recursive call here
int maxNext = maximum(e);
if (maxNext > max) max = maxNext;
}
}
return max;
}
Your solution is not recursive. You are only checking the max in the children of root, not deeper than that.
You should traverse through all the children and keep on updating max. I have done it using recursion, there can be many other ways to traverse a tree.
I need to print all the nodes that are N level above all Leaf Nodes. I tried below approach, but now I am stuck and unable to proceed. Please help. I need to code only using Java 7 and no other versions.
For example, I have this path 1 --> 2 --> 3 --> 4, so in this case assuming 4 is my leaf node, node 3 is 1 level above 4 and node 2 is 2 levels above leaf node 4 and node 1 is 3 levels above leaf node 4.
Note: Please use only Java 7.
public class NNodeBeforeLeaf {
static Node root;
static class Node {
int data;
Node left, right;
Node(int data){
this.data = data;
left=right=null;
}
}
public static boolean isLeaf(Node n){
if(n.right == null && n.left == null)
return true;
return false;
}
public static void main(String[] args) {
int level = 2; // level N
root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(8);
print(root, 0, level);
}
public static void print(Node n, int currLevel, int level){
if(n == null){
return;
}
if(!isLeaf(n)){
print(n.left, currLevel + 1, level);
print(n.right, currLevel + 1, level);
}
printNode(n, currLevel, level);
}
public static void printNode(Node n, int currLevel, int level){}
}
You have a miss in your structure to do this a Node know its child but not is parent so you need to build a structure that will give you this link : here is my proposition : i build a map that give me the parent associate to a node with method buildParentMap this function already list all the leaf in one pass to avoid a double iteration on your tree then i use this map to go up as many time as asked on each leaf i list just before here is a snippet
be carefull this code work but there is no security if your are trying to upper that root or if the same node is present in too child (but 2 Node with the same data wont be a problem)
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
public class NNodeBeforeLeaf {
static Node root;
static class Node {
int data;
Node left, right;
Node(int data) {
this.data = data;
left = right = null;
}
#Override
public String toString() {
return "Node : " + data;
}
}
public static boolean isLeaf(Node n) {
if (n.right == null && n.left == null)
return true;
return false;
}
public static void main(String[] args) {
int level = 2; // level N
root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(8);
print(root, 0, level);
int levelToUp = 1;
HashSet<Node> result = getUpper(levelToUp, root);
System.out.println(Arrays.toString(result.toArray()));
}
private static HashSet<Node> getUpper(int levelToUp, Node node) {
HashMap<Node, Node> parenttMap = new HashMap<Node, Node>();
LinkedList<Node> leafs = new LinkedList<Node>();
buildParentMap(node, parenttMap, leafs);
HashSet<Node> result = new HashSet<>();
for (Node leaf : leafs) {
result.add(getUpperLevel(leaf, levelToUp, parenttMap));
}
return result;
}
private static Node getUpperLevel(Node leaf, int i, HashMap<Node, Node> parenttMap) {
Node tmp = leaf;
while (i > 0) {
i--;
tmp = parenttMap.get(tmp);
}
return tmp;
}
private static void buildParentMap(Node root2, HashMap<Node, Node> hashMap, LinkedList<Node> leaf) {
if (root2 == null) {
return;
} else if (isLeaf(root2)) {
leaf.add(root2);
} else {
hashMap.put(root2.left, root2);
buildParentMap(root2.left, hashMap, leaf);
hashMap.put(root2.right, root2);
buildParentMap(root2.right, hashMap, leaf);
}
}
public static void print(Node n, int currLevel, int level) {
if (n == null) {
return;
}
printNode(n, currLevel, level);
if (!isLeaf(n)) {
print(n.left, currLevel + 1, level);
print(n.right, currLevel + 1, level);
}
}
public static void printNode(Node n, int currLevel, int level) {
String output = "";
for (int i = 0; i < currLevel; i++) {
output += "\t";
}
System.out.println(output + n);
}
}
PLEASE READ MY COMMENT FIRST
Since the nodes in your program store data only for the nodes below them, I couldn't really find a way of actually going up the tree ':), but I could think of this work around, basically what you can do is, each time you need to go up by n levels you can traverse down from the root to (curLevel - n) here is a sample program that does this (it prints all the nodes at a level which is n above the current level, i hope this is what you meant):
class tree{
static class Node{
int data;
Node left;
Node right;
Node(int data){
this.data = data;
left = null;
right = null;
}
}
static Node root;
public static boolean isLeaf(Node n){
if(n.left == null && n.right == null)
return true;
return false;
}
public static void goDownTillLevel(Node n, int level){
int l = level;
if(n != null){
if(level == 0) {
System.out.println(n.data);
}
else{
if(!isLeaf(n)){
goDownTillLevel(n.left, --level);
level = l; //since by the time the above function calls finished, level had been reduced to 0
goDownTillLevel(n.right, --level);
}
}
}
}
public static void nLevelsAbove(Node n, int curLevel, int level){
goDownTillLevel(root, (curLevel - level - 1));
}
public static void main(String args[]){
int curLevel = 0;
root = new Node(1);
curLevel++;
root.left = new Node(2);
root.right = new Node(2);
curLevel++;
root.left.left = new Node(3);
root.left.right = new Node(3);
root.right.left = new Node(3);
Node n = new Node(3);
root.right.right = n;
curLevel++;
nLevelsAbove(n, curLevel, 1);
}
}
Though I'd like to add that if going up is one of your concerns, don't use this node structure, instead add another variable to the node, a reference to the node right above it, that way this could be made much easier and shorter.
The output of the above code is:
2
2
I think that the implementation of public static boolean isLeaf(Node n) is wrong, it should check only if right is null otherwise it is not a node, either a leaf
To get the current level of node, you can try with this code
int level = 0;
while(node.right != null) {
level++;
node = node.right;
}
System.out.println("current level node: " + level);
Your structure is not able to determine the height of the current node, except when traversing from bottom to top. In order to achieve this, you have to traverse to the leafs first.
Each recursion (bottom up now) should then return it's heights. As youre not stating if your tree is a full binary tree, a node can have multiple heights depending on his children. If the heights match the desired height, the node can be printed.
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class NNodeBeforeLeaf {
static Node root;
static class Node {
int data;
Node left, right;
Node(int data) {
this.data = data;
left = right = null;
}
}
public static boolean isLeaf(Node n) {
return n.right == null && n.left == null;
}
public static void main(String[] args) {
int level = 2; // level N
root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(8);
print(root, level);
}
public static void print(Node n, int level) {
traversAndPrint(n, level);
}
private static Set<Integer> traversAndPrint(Node n, int levelToPrint) {
if (isLeaf(n)) return Collections.singleton(0); // We are a leaf, so we have height 0
final Set<Integer> childrenHeights = new HashSet<>();
// are no leaf, so we have to get the heights of our children
if (n.right != null) childrenHeights.addAll(traversAndPrint(n.right, levelToPrint));
if (n.left != null) childrenHeights.addAll(traversAndPrint(n.left, levelToPrint));
assert !childrenHeights.isEmpty();
// And increase these heights
final Set<Integer> selfHeights = new HashSet<>();
for (Integer childrenHeigth : childrenHeights) {
final int selfHeight = childrenHeigth + 1;
selfHeights.add(selfHeight);
}
// If we have the desired height, print
if (selfHeights.contains(levelToPrint)) printNode(n);
return selfHeights; // return our heights
}
public static void printNode(Node n) {
// Do whatever you want
System.out.println(n.data);
}
}
I found another approach. I put all nodes in a list. For each level up I remove the leaf nodes in that list. A leaf node in the list is defined as a node with left=null and right=null or if they are not null left and right should not be in the list. After the level ups I print the now leaf nodes in the list.
public class NNodeBeforeLeaf {
static Node root;
static class Node {
int data;
Node left, right;
Node(int data) {
this.data = data;
left = right = null;
}
}
public static boolean isLeaf(Node n) {
if ((n.right == null) && (n.left == null)) {
return true;
}
return false;
}
public static void main(String[] args) {
int level = 2; // level N
root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(8);
printNodes(getNodesNLevelAboveLeafs(root, level));
}
public static void printNodes(List<Node> nodes) {
for (Node n : nodes) {
System.out.println(n.data);
}
}
public static List<Node> getNodesNLevelAboveLeafs(Node root, int level) {
List<Node> allNodes = listAllNodes(root);
for (int i = 0; i < level; i++) {
allNodes.removeAll(getLeafNodes(allNodes));
}
return getLeafNodes(allNodes);
}
private static List<Node> getLeafNodes(List<Node> allNodes) {
List<Node> leafs = new ArrayList<>();
for (Node n : allNodes) {
if (((n.left == null) || !allNodes.contains(n.left))
&& ((n.right == null) || !allNodes.contains(n.right))) {
leafs.add(n);
}
}
return leafs;
}
private static List<Node> listAllNodes(Node node) {
List<Node> nodes = new ArrayList<>();
nodes.add(node);
if (node.left != null) {
nodes.addAll(listAllNodes(node.left));
}
if (node.right != null) {
nodes.addAll(listAllNodes(node.right));
}
return nodes;
}
}
I am trying to write a function in a binary search tree class that will return the number of nodes in the tree that have values greater than n in the form public int greater (int n). I figured it might be easier to store all the values in a list and then iterate over the list and increment count each time a number is found to be greater than n. How would I go about implementing this?
This is my class so far:
public class BST
{ private BTNode<Integer> root;
private int count = 0;
List<Integer> arr = new ArrayList<>();
private BST right = new BST();
private BST left = new BST();
public BST()
{ root = null;
}
public boolean find(Integer i)
{ BTNode<Integer> n = root;
boolean found = false;
while (n!=null && !found)
{ int comp = i.compareTo(n.data);
if (comp==0)
found = true;
else if (comp<0)
n = n.left;
else
n = n.right;
}
return found;
}
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){ //TODO
return 0;
}
}
class BTNode<T>
{ T data;
BTNode<T> left, right;
BTNode(T o)
{ data = o; left = right = null;
}
}
I would not use a list as temporary storage.
There is a concept called Tree Traversal allowing you to visit each node of your tree.
Here is some pseudo code:
preorder(node)
if (node = null)
return
visit(node)
preorder(node.left)
preorder(node.right)
The visit function here is executed exactly once at each node.
For a specialized traversal like the counting you described, you could just replace visit with the functionality you want, like:
if (node.data > n) {
count += 1
}
Even better would be if you implement a Preorder class which you can extend to provide it with a custom visit function.
I'm working on an assignment for my Data Structures class. We have to create an address book using our own sorted linked based list adt. Right now the add method works, but it seems to make all the nodes point to the first node. Whenever I try to output the the list using getEntry() in a for loop, it gives me the last added entry each time. I've tried using toArray but it does the same thing. Can you see any problems?
public class GTSortedLinkedBasedList implements GTListADTInterface {
private Node firstNode;
private int numberOfEntries;
public GTSortedLinkedBasedList(){
//firstNode = new Node(null);
numberOfEntries = 0;
}
public void setNumberOfEntries(int x){
numberOfEntries = x;
}
public void add(ExtPersonType newEntry){
//firstNode = null;
Node newNode = new Node(newEntry);
Node nodeBefore = getNodeBefore(newEntry);
if (isEmpty() || (nodeBefore == null))
{
// Add at beginning
newNode.setNextNode(firstNode);
firstNode = newNode;
}
else
{
// Add after nodeBefore
Node nodeAfter = nodeBefore.getNextNode();
newNode.setNextNode(nodeAfter);
nodeBefore.setNextNode(newNode);
} // end if
numberOfEntries++;
}
private Node getNodeBefore(ExtPersonType anEntry){
Node currentNode = getFirstNode();
Node nodeBefore = null;
while ((currentNode != null) &&
(anEntry.getFirstName().compareTo(currentNode.getData().getFirstName()) > 0))
{
nodeBefore = currentNode;
currentNode = currentNode.getNextNode();
} // end while
return nodeBefore;
}
private class Node {
private ExtPersonType data;
private Node next;
public Node(ExtPersonType dataValue) {
next = null;
data = dataValue;
}
public Node(ExtPersonType dataValue, Node nextValue) {
next = nextValue;
data = dataValue;
}
public ExtPersonType getData(){
return data;
}
public void setData(ExtPersonType newData){
data = newData;
}
public Node getNextNode(){
return next;
}
public void setNextNode(Node newNode){
next = newNode;
}
}
public ExtPersonType getEntry(int givenPosition) {
if ((givenPosition >= 1) && (givenPosition <= numberOfEntries)){
assert !isEmpty();
return getNodeAt(givenPosition).getData();
}
else{
throw new IndexOutOfBoundsException("Illegal position given to getEntry operation.");
}
}
public void loadData(GTSortedLinkedBasedList contacts) throws FileNotFoundException{
//int index = 0;
ExtPersonType person = new ExtPersonType();
DateType tempDate = new DateType();
AddressType tempAddress = new AddressType();
Scanner file = new Scanner(new FileInputStream("Programming Assignment 1 Data.txt"));
while(file.hasNext()){
person.setFirstName(file.next());
person.setLastName(file.next());
tempDate.setMonth(file.nextInt());
tempDate.setDay(file.nextInt());
tempDate.setYear(file.nextInt());
person.setDOB(tempDate);
tempAddress.setStreetAddress(file.nextLine());
if(tempAddress.getStreetAddress().isEmpty()){
tempAddress.setStreetAddress(file.nextLine());
}
tempAddress.setCity(file.nextLine());
tempAddress.setState(file.nextLine());
tempAddress.setZipCode(file.nextLine());
person.setAddress(tempAddress);
person.setPhoneNumber(file.nextLine());
person.setPersonStatus(file.nextLine());
if(person.getPersonStatus().isEmpty()){
person.setPersonStatus(file.nextLine());
}
contacts.add(person);
System.out.println(contacts.getEntry(contacts.getLength()).getFirstName());
//index++;
}
}
public static void main(String[] args) throws FileNotFoundException {
AddressBook ab = new AddressBook();
ab.loadData(ab);
ExtPersonType people = new ExtPersonType();
//people = ab.toArray(people);
System.out.println(ab.getLength());
for(int cnt = 1; cnt <= ab.getLength(); cnt++){
people = ab.getEntry(cnt);
System.out.println(people.getFirstName());
}
}
EDIT: The add method is overwriting each previous object with the newly added one. It also doesn't seem to matter if I do a sorted list or just a basic list.
I'm not going to lie here, I'm not totally sure I understand your code but I think I see what's wrong. In your getNodeBefore() method's code, you set currentNode() always to firstNode(). I believe that is causing the problem. I see that you are trying to recursively move through the list to find the proper node but I don't think each recursive call is causing movement through the list. I suggest you add properties to the object that represent the forward and backward nodes.
Something like this...
private T data;
private Node nodeBefore;
private Node nodeAfter;
As you create objects, you assign the properties before and after and then all the information you need is contained in the object itself.
To move recursively through the list you would then just add a statement like currentNode = currentNode.nodeAfter.
Your getNodeBefore() method would simply return currentNode.nodeBefore and getNodeAfter() would return currentNode.nodeAfter.
You don't have code that handles the situation where the node being added will be the first node in the list, but the list is also not empty. In this case, getNodeBefore returns null, and your code overwrites the root node.
Try
if (isEmpty() && (nodeBefore == null))
{
// Add at beginning
newNode.setNextNode(firstNode);
firstNode = newNode;
}
else if(nodeBefore == null)
{
Node temp = new Node();
temp.setNextNode(first.next);
temp.setData(first.data);
newNode.setNextNode(temp);
firstNode = newNode;
}
I'm trying to write code for a binary search tree, the first method I'm working on is the add (insert) method. The root seems to insert properly, but I'm getting null pointer exception when adding the second node. I'll indicate the exact problem spot in my code with comments.
If you can see how to fix the bugs, or let me know if my overall logic is flawed it would be incredibly helpful.-- I will mention that this is for school, so I'm not looking to make a really impressive model...most of my layout choices simply reflect the way we've been working in class. Also, method names were selected by the teacher and should stay the same. Feel free to edit the formatting, had a little trouble.
BINARY TREE CLASS
public class BinarySearchTree
{
private static Node root;
public BinarySearchTree()
{
root = null;
}
public static void Add (Node newNode)
{
Node k = root;
if (root == null)//-----------------IF TREE IS EMPTY -----------------
{
root = newNode;
}
else // -------TREE IS NOT EMPTY --------
{
if (newNode.value > k.value) //-------NEW NODE IS LARGER THAN ROOT---------
{
boolean searching = true;
while(searching) // SEARCH UNTIL K HAS A LARGER VALUE
{ //***CODE FAILS HERE****
if(k.value > newNode.value || k == null)
{
searching = false;
}
else {k = k.rightChild; }
}
if ( k == null) { k = newNode;}
else if (k.leftChild == null){ k.leftChild = newNode;}
else
{
Node temp = k.leftChild;
k.leftChild = newNode;
newNode = k.leftChild;
if(temp.value > newNode.value )
{
newNode.rightChild = temp;
}
else
{
newNode.leftChild = temp;
}
}
}
if (newNode.value < k.value) //-----IF NEW NODE IS SMALLER THAN ROOT---
{
boolean searching = true;
while(searching) // ----SEARCH UNTIL K HAS SMALLER VALUE
{// **** CODE WILL PROBABLY FAIL HERE TOO ***
if(k.value < newNode.value || k == null) {searching = false;}
else {k = k.leftChild;}
}
if ( k == null) { k = newNode;}
else if (k.rightChild == null){ k.rightChild = newNode;}
else
{
Node temp = k.rightChild;
k.rightChild = newNode;
newNode = k.rightChild;
if(temp.value > newNode.value )
{
newNode.rightChild = temp;
}
else
{
newNode.leftChild = temp;
}
}
}
}} // sorry having formatting issues
}
NODE CLASS
public class Node
{
int value;
Node leftChild;
Node rightChild;
public Node (int VALUE)
{
value = VALUE;
}
}
TEST APPLICATION
public class TestIT
{
public static void main(String[] args)
{
BinarySearchTree tree1 = new BinarySearchTree();
Node five = new Node(5);
Node six = new Node(6);
tree1.Add(five);
tree1.Add(six);
System.out.println("five value: " + five.value);
System.out.println("five right: " + five.rightChild.value);
}
}
The conditional statement is checked from left to right, so you need to check whether k is null before you check whether k.value > newNode.value because if k is null, then it doesn't have a value.