I have written a code of Binary Search tree that extends comparable and implements an interface. The code for leaves and the helper method countLeaves (included down here), makes sure that all of the test goes through except for one, heightIsLogOfNumLeavesTreeIsPerfect().
// TODO: Look at the Leaves and the helper method to leaves and see how I should change it so that this test goes through aswell.
//EDIT: I have added the whole tree class
java.lang.AssertionError:
Expected: <2>
but: was <0>
Expected :<2>
Actual :<0>
import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.Timeout;
import static org.junit.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
import java.util.stream.IntStream;
/**
* Test class for a tree.
*/
public class TreeTest{
#Rule public Timeout globalTimeout = Timeout.seconds(5);
Tree<Integer> tree;
int[] elementsInTree;
int[] elementsNotInTree;
#Before
public void setUp() {
/**
* This tree should look like this:
*
* 8
* / \
* 3 10
* / \ \
* 1 6 14
* / \ /
* 4 7 13
*/
tree = new Tree<>();
elementsInTree = new int[] {8, 10, 14, 13, 3, 1, 6, 4, 7};
for (int elem : elementsInTree) {
tree.insert(elem);
}
elementsNotInTree = new int[] {34, -3, -10, 12, 74, 5};
}
#Test
public void heightIsLogOfNumLeavesTreeIsPerfect() {
// For a perfect tree, tree.height() == log2(tree.leaves()
// Arrange
Tree<Integer> tree = new Tree<>();
int[] elements = new int[] {8, 3, 10, 1, 6, 9, 14};
int numLeaves = 4;
int logNumLeaves = (int) Math.round(Math.log(numLeaves) / Math.log(2));
for (int elem : elements) {
tree.insert(elem);
}
// Act
int height = tree.height();
// Assert
assertThat(height, equalTo(logNumLeaves));
}
}
**
* An interface describing a generic Comparable
*/
public interface BSTInterface <T>{
boolean search(T elem);
boolean insert(T elem);
int size();
int height();
int leaves();
}
/**
* An Binary Search tree implementation of the comparable interface.
* #param <T>
*/
public class Tree <T extends Comparable <T>> implements BSTInterface <T>{
private int size;
private Node root;
public class Node{
private Node Left;
private Node Right;
private T data;
public Node(T data){
this.data = data;
}
public Node getRight(){
return Right;
}
public Node getLeft() {
return Left;
}
public T getData() {
return data;
}
}
public Tree (){
size = 0;
root = null;
}
/**
* Test for presence of a value.
* #param elem
* #return true/false
*/
#Override
public boolean search(T elem) {
if(root == null ||elem == null){
return false;
}
Node node = root;
while(true){
if(node.data.compareTo(elem) > 0){
if(node.Right == null){
return false;
} else{
node = node.Right;
}
} else if(node.data.compareTo(elem) == 0){
break;
} else{
if(node.Left== null){
return false;
}
else{
node = node.Left;
}
}
}
return true;
}
/**
* Add value to tree; duplicates are not allowed.
* Return true if the element is not already present (and is thus inserted),
* false otherwise.
*
* #param elem
* #return true/false
*/
#Override
public boolean insert(T elem) {
if (elem == null){
return false;
}
if (root == null){
root = new Node(elem);
size++;
return true;
}
Node node = root;
while (true){
if (node.data.compareTo(elem) > 0) {
if (node.Right == null){
node.Right = new Node(elem);
size++;
break;
} else {
node = node.Right;
}
} else if (node.data.compareTo(elem) == 0) {
return false;
} else {
if (node.Left == null){
node.Left = new Node(elem);
size++;
break;
} else {
node = node.Left;
}
}
}
return true;
}
/**
* the number of elements in the tree
* #return size.
*/
#Override
public int size() {
return size;
}
/**
* The height of the tree.
* The empty tree and the tree with only the root node both have height 0.
* #return the height of the tree.
*/
#Override
public int height() {
return countHeight(root);
}
/**
* Helper method for height
*/
private int countHeight(Node node){
if(node == null) {
return 0;
}
return Math.max(countHeight(node.Left), countHeight(node.Right));
}
/**
* The number of leaves in the tree.
* #return the amount of leaves the tree have.
*/
#Override
public int leaves() {
return countLeaves(root);
}
/**
* Helper method for leaves
*/
private int countLeaves(Node node) {
if (node == null) {
return 0;
}
if (node.Left == null && node.Right == null) {
return 1;
}
return countLeaves(node.Left) + countLeaves(node.Right);
}
/**
* A string describing the tree
* #return
*/
public String toString(){
String str = "[" + helpToString(root);
if (str.length() > 1) {
str = str.substring(0, str.length() - 2);
} return str + "]";
}
/**
* Helper method for toString
*/
private String helpToString(Node node) {
String str = "";
if (node != null) {
str += helpToString(node.Right);
str += node.data + ", ";
str += helpToString(node.Left);
}
return str;
}
}
Your countHeight method can return either zero or a maximum of two returns, and there are no other operations in it. You can't get a value greater of zero out of zeros just by using max function.
You should return -1 for an empty tree and max(height(left) + 1, height(right) + 1) otherwise. Each +1 accounts for length of corresponding parent-child edge.
(Mathematically speaking, height of an "empty" tree is usually undefined, but defining it as -1 in this case helps a lot so let's stick to that.)
Related
I have implemented a Binary search tree and I have written a test class (in JUNIT testing) for it. All the test except for one test goes through. The test leavesIsCorrectWhenTreeIsPerfect() gets a message when I debug the code.
Expected: <4> but: was <5> . I do not know have to fix this.
Keep in mind that all the other tests goes through, and I do not think that it is a problem with the tree code.
How do you understand the description for the test?
/**
* A Binary Search tree.
*/
public class Tree <T extends Comparable <T>> implements BinaryTree <T>{
private int size;
private Node root;
public class Node{
private Node Left;
private Node Right;
private T data;
public Node(T data){
this.data = data;
}
}
public Tree (){
size = 0;
root = null;
}
/**
* Test for presence of a value.
* #param elem
* #return true/false
*/
#Override
public boolean search(T elem) {
if(root == null ||elem == null){
return false;
}
Node node = root;
while(true){
if(node.data.compareTo(elem) > 0){
if(node.Right == null){
return false;
} else{
node = node.Right;
}
} else if(node.data.compareTo(elem) == 0){
break;
} else{
if(node.Left== null){
return false;
}
else{
node = node.Left;
}
}
}
return true;
}
/**
* Add value to tree; duplicates are not allowed.
* Return true if the element is not already present (and is thus inserted),
* false otherwise.
*
* #param elem
* #return true/false
*/
#Override
public boolean insert(T elem) {
if (elem == null){
return false;
}
if (root == null){
root = new Node(elem);
size++;
return true;
}
Node node = root;
while (true){
if (node.data.compareTo(elem) > 0) {
if (node.Right == null){
node.Right = new Node(elem);
size++;
break;
} else {
node = node.Right;
}
} else if (node.data.compareTo(elem) == 0) {
return false;
} else {
if (node.Left == null){
node.Left = new Node(elem);
size++;
break;
} else {
node = node.Left;
}
}
}
return true;
}
/**
* The number of elements in the tree
* #return size.
*/
#Override
public int size() {
return size;
}
/**
* The height of the tree.
* The empty tree and the tree with only the root node both have height 0.
* #return the height of the tree.
*/
#Override
public int height() {
return countHeight(root);
}
/**
* Helper method for height
*/
private int countHeight(Node node){
if(node == null) {
return 0;
}
if (node.Left == null && node.Right == null) {
return 0;
}
return 1 + Math.max(countHeight(node.Left), countHeight(node.Right));
}
/**
* The number of leaves in the tree.
* #return the amount of leaves the tree have.
*/
#Override
public int leaves() {
return countLeaves(root);
}
/**
* Helper method for leaves
*/
private int countLeaves(Node node) {
if (node == null) {
return 0;
}
if (node.Left == null && node.Right == null) {
return 1;
}
return countLeaves(node.Left) + countLeaves(node.Right);
}
/**
* A string describing the tree
* #return
*/
public String toString(){
String str = "[" + helpToString(root);
if (str.length() > 1) {
str = str.substring(0, str.length() - 2);
} return str + "]";
}
/**
* Helper method for toString
*/
private String helpToString(Node node) {
String str = "";
if (node != null) {
str += helpToString(node.Right);
str += node.data + ", ";
str += helpToString(node.Left);
}
return str;
}
}
Test class:
import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.Timeout;
import static org.junit.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
import java.util.stream.IntStream;
/**
* Test class for a tree.
*/
public class TreeTest{
#Rule public Timeout globalTimeout = Timeout.seconds(5);
Tree<Integer> tree;
int[] elementsInTree;
int[] elementsNotInTree;
#Before
public void setUp() {
/**
* This tree should look like this:
*
* 8
* / \
* 3 10
* / \ \
* 1 6 14
* / \ /
* 4 7 13
*/
tree = new Tree<>();
elementsInTree = new int[] {8, 10, 14, 13, 3, 1, 6, 4, 7};
for (int elem : elementsInTree) {
tree.insert(elem);
}
elementsNotInTree = new int[] {34, -3, -10, 12, 74, 5};
}
#Test
public void leavesIsTwoWhenPerfectTreeHasThreeNodes() {
// Arrange
Tree<Integer> tree = new Tree<>();
// root must be smaller than one and larger than the other child
tree.insert(1338); // root
tree.insert(1337); // smaller child
tree.insert(1396); // larger child
// Act
int numLeaves = tree.leaves();
// Assert
assertThat(numLeaves, equalTo(2));
}
#Test
public void leavesIsCorrectWhenTreeIsPerfect() { //TEST
// A perfect tree has all leaves at the same depth, and all internal nodes
// (i.e. non-leaves) have two children
//
// This test should assert that a perfect tree with 2*n-1 nodes total,
// has exactly n leaves (i.e. that Tree.leaves() returns n).
//
// An example is the perfect three-node tree from the test above:
//
// (1338)
// / \
// (1337) (1396)
// You have to construct our own tree here, with n >= 4
int n = 4;
int nodes = 2*n-1;
for(int i = 0; i < nodes ; i++) {
tree.insert(i);
}
int leaves = tree.leaves();
assertThat(leaves,equalTo(n));
}
#Test
public void leavesIsOneWhenElementsWereInsertedInAscendingOrder() {
// Arrange
Tree<Integer> tree = new Tree<>();
// insert elements in ascending order => all elements are inserted to the right
int numElements = 100;
for (int i = 0; i < numElements; i++) {
tree.insert(i);
}
// Act
int numLeaves = tree.leaves();
// Assert
assertThat(numLeaves, equalTo(1));
}
// Tests for height
#Test
public void heightIsZeroWhenTreeIsEmpty() {
// Arrange
Tree<Integer> emptyTree = new Tree<>();
// Act
int height = emptyTree.height();
// Assert
assertThat(height, equalTo(0));
}
#Test
public void heightIsLogOfNumLeavesTreeIsPerfect() {
// For a perfect tree, tree.height() == log2(tree.leaves()
// Arrange
Tree<Integer> tree = new Tree<>();
int[] elements = new int[] {8, 3, 10, 1, 6, 9, 14};
int numLeaves = 4;
int logNumLeaves = (int) Math.round(Math.log(numLeaves) / Math.log(2));
for (int elem : elements) {
tree.insert(elem);
}
// Act
int height = tree.height();
// Assert
assertThat(height, equalTo(logNumLeaves));
}
// Tests for insert/height
#Test
public void insertValuesInAscendingOrderIncrementsHeight() {
// When inserting elements in ascending order, each element is inserted
// to the right of the deepest node, so the height should increment by
// 1 for each element inserted.
Tree <Integer> tree = new Tree<>();
int val = 100;
for(int i = 0; i < val; i++){
tree.insert(i);
}
int treeHeight = tree.height();
treeHeight++;
assertThat(val,equalTo(treeHeight));
}
}
The leaves method counts the number of leaves that you have. Your expectation is that there will be four leaves. However, the result is 5. The method that you use in order to count the leaves appears to be correct:
/**
* Helper method for leaves
*/
private int countLeaves(Node node) {
if (node == null) {
return 0;
}
if (node.Left == null && node.Right == null) {
return 1;
}
return countLeaves(node.Left) + countLeaves(node.Right);
}
It essentially counts the items (in a breadth-first-search fashion) that have no children. What could be the reason? Your main thing to find out how your tree looks alike. Based on your insert method:
#Override
public boolean insert(T elem) {
if (elem == null){
return false;
}
if (root == null){
root = new Node(elem);
size++;
return true;
}
Node node = root;
while (true){
if (node.data.compareTo(elem) > 0) {
if (node.Right == null){
node.Right = new Node(elem);
size++;
break;
} else {
node = node.Right;
}
} else if (node.data.compareTo(elem) == 0) {
return false;
} else {
if (node.Left == null){
node.Left = new Node(elem);
size++;
break;
} else {
node = node.Left;
}
}
}
return true;
}
and knowing that 2*n-1 in your test is 7, so the input numbers are 0, 1, 2, 3, 4, 5, 6, it seems to me that the tree could be
0
/
1
/
2
/
3
/
4
/
5
/
6
which would have a single leaf, because if the node has a greater value than the item you are about to insert, then you add it to the node's right. However, the results of your test are different. For some reason you have 5 leaves. You would need to check the reason of that by first finding out how your table looks alike at the end and second by looking into the insert method with a debugger for this input.
I'm having a problem with my getHeight() method, it is not returning the correct height for the tree. I really think the problem has something to do with my QueueList Class but I can not for the life of me solve the issue. I'm open to suggestions on how to better implement a Binary search. Below is my QueueList Class.
package lab5;
import java.util.NoSuchElementException;
public class QueueList<E> implements Queue<E> {
private Node<E> front;
private Node<E> rear;
private int size = 0;
public QueueList (E it){
front = rear = new Node<E>(it);
size++;
}
public QueueList(){
front = rear = new Node<E>();
size=0;
}
public boolean isEmpty() {
return size==0;
}
public void enqueue(E it) {
rear.setNext(rear);
rear.setElement(it);
size++;
}
public void clear() {
front=new Node<E>();
rear=new Node<E>();
front.setNext(null);
rear.setNext(null);
front.setNext(null);
size=0;
}
public int size() {
return size;
}
public E front() {
return front.getElement();
}
public E dequeue() {
Node<E> temp = front;
if(isEmpty()){
throw new NoSuchElementException();
}
else{
front = front.getNext();
size--;
return temp.getElement();
}
}
}
Here is my Binary search tree class, all of my BSTNode Method works correctly so just assume that is not the issue.
package lab5;
public class BinarySearchTree<E extends Comparable<E>> {
private BSTNode root;
private int size;
public BinarySearchTree() {
root = null;
size = 0;
}
public BinarySearchTree(BSTNode node) {
root = node;
size = 1;
}
/**
* searches for a node that contains it.
*
* if it finds it, it returns that node
*
* else it returns null
*
* #param it
* - the element to look for
*
* #return the node that contains it
*
*/
public BSTNode search(E it) {
BSTNode<E> parent = null;
BSTNode<E> child = null;
BSTNode<E> node = root;
while (node != null && node.getElement() != it) {
parent = node;
int compareResult = it.compareTo(node.getElement());
if (compareResult < 0) {
node = node.getLeft();
} else {
node = node.getRight();
}
}
if (node == null) {
return null;
}
return node;
}
/**
* determines if the tree contains the element
*
* #return true if it is in the tree
*
*/
public boolean contains(E it) {
return (search(it) != null);
}
/**
* Add the element to the correct location
*
* all elements to the left are less than the parent
*
* all elements to the rights are greater than the parent
*
* Do not allow duplicates
*
* #param it
* the element to insert
*
*/
public void insert(E it) {
BSTNode<E> newNode = new BSTNode<E>(it);
if (root == null) {
root = newNode;
return;
}
BSTNode<E> parent = null;
BSTNode<E> node = root;
while (node != null) {
parent = node;
int compareResult = it.compareTo(node.getElement());
if (compareResult < 0) {
node = node.getLeft();
} else if (compareResult > 0) {
node = node.getRight();
} else {
// duplicate
return;
}
}
int res = it.compareTo(parent.getElement());
if (res < 0) {
parent.setLeft(newNode);
} else {
parent.setRight(newNode);
}
size++;
}
/**
* Removes the node that contains it.
*
* If the tree does not contain it, it prints that to
*
* the user and does nothing else.
*
* Otherwise it removes the node and maintains the
*
* BST properties
*
* if removing a node with two children, replace it
*
* with its in order predecessor.
*
* #param the
* element of the node you want to remove.
*
*/
public void remove(E it) {
BSTNode<E> parent = null;
BSTNode<E> child = null;
BSTNode<E> node = root;
// Find the node that contains it
while (node != null && node.getElement() != it) {
parent = node;
int compareResult = it.compareTo(node.getElement());
if (compareResult < 0) {
node = node.getLeft();
} else {
node = node.getRight();
}
}
if (node == null) {
System.out.println("failed to find: " + it + " for removal");
return;
}
if (node.isLeaf()) {
if (parent == null) {
root = null;
} else if (it.compareTo(parent.getElement()) < 0) {
parent.setLeft(null);
} else {
parent.setRight(null);
}
} else if (node.getLeft() == null) {
child = node.getRight();
swapElements(node, child);
node.setLeft(child.getLeft());
node.setRight(child.getRight());
} else if (node.getRight() == null) {
child = node.getLeft();
} else {
child = node.getLeft();
parent = null;
while (child.getRight() != null) {
parent = child;
child = parent.getRight();
}
if (parent == null) {
swapElements(node, child);
node.setLeft(child.getLeft());
} else {
swapElements(node, child);
parent.setRight(child.getLeft());
}
}
size--;
}
/**
* Returns the height of the tree
*
* if tree is empty, height is -1
*
* if tree only has one node, height is 0
*
* #return the integer height of the tree
*
*
*
*/
public int getHeight() {
int height = -1;
QueueList<BSTNode> q = new QueueList<BSTNode>();
if (root == null) {
return height;
}
q.enqueue(root);
while (!q.isEmpty()) {
int nodeCount = q.size();
height++;
while (nodeCount > 0) {
BSTNode<E> node = q.dequeue();
if (node.hasLeft()) {
q.enqueue(node.getLeft());
}
if (node.hasRight()) {
q.enqueue(node.getRight());
}
nodeCount--;
}
}
return height;
}
/**
* Helper method
*
* For removal you need to swap elements of nodes
*
* #param node1
* , node2 the nodes whose contents you are swapping
*
*/
private void swapElements(BSTNode node1, BSTNode node2) {
BSTNode temp = null;
temp.setElement(node1.getElement());
node1.setElement(node2.getElement());
node2.setElement(temp.getElement());
}
/**
* prints each level of the tree on its own line
*
* use your Queue class
*
*/
public void printLevelOrder() {
QueueList<BSTNode> q = new QueueList<BSTNode>();
q.enqueue(root);//You don't need to write the root here, it will be written in the loop
while (q.size() > 0)
{
BSTNode n = q.dequeue();
System.out.println(n.toString()); //Only write the value when you dequeue it
if (n.hasLeft())
{
q.enqueue(n.getLeft());//enqueue the left child
}
if (n.hasRight())
{
q.enqueue(n.getRight());//enque the right child
}
}
}
/**
* prints the tree in a depth-first fashion
*
* use your Stack class
*
*/
public void printByDepth() {
StackList<BSTNode> s = new StackList<BSTNode>();
s.push(root);
while (s.isEmpty() == false) {
BSTNode x = s.pop();
if (x.getRight() != null)
s.push(x.getRight());
if (x.getLeft() != null)
s.push(x.getRight());
System.out.print(" " + x.toString());
}
}
/**
* prints the tree in an inorder fashion.
*
* uses a stack to push left children onto the stack
*
*/
public void printInOrder() {
if (root == null)
return;
StackList s = new StackList();
BSTNode currentNode = root;
while (!s.isEmpty() || currentNode != null) {
if (currentNode != null) {
s.push(currentNode);
currentNode = currentNode.getLeft();
} else {
BSTNode n = null;
n.setElement(s.pop());
System.out.printf("%d ", n.toString());
currentNode = n.getRight();
}
}
}
}
As recursion is very popular when dealing with binary trees, you can use this solution:
public int getHeight() {
return getHeight(root, 0);
}
private int getHeight(BSTNode node, int currentHeight) {
if (node == null) {
return currentHeight;
}
int rightHeight = getHeight(node.getRight(), currentHeight + 1)
int leftHeight = getHeight(node.getLeft(), currentHeight + 1);
return Math.max(rightHeight, leftHeight);
}
Note that it returns height=0 for an empty tree.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am looking for some help with a class I have designed for an assignment. It adds game scores to a linked list and lists them from highest to lowest. The max number of scores is 10. I have it almost working but I can't figure something out. I add the first score and it works, then if I add a second score, it only works if that score is higher than the first. If not, it throws a java.lang.NullPointerException. Can someone take a look at my insert(String name, int score) method and let me know what the problem is?
public class GamerList {
/**
* The node class stores a list element and a reference to the next node.
* #author johnmckillip
*
*/
private class Node {
String name;
int score;
Node next;
/**
* Constructor.
* #param val The element to store in the node.
* #param n The reference to the successor node.
*/
Node(String val1, int val2, Node n) {
name = val1;
score = val2;
next = n;
}
/**
* Constructor.
* #param val The element to store in the node.
*/
Node(String val1, int val2) {
this(val1, val2, null);
}
}
private Node head;
private Node tail;
/**
* Constructor.
*/
public GamerList() {
head = null;
tail = null;
}
/**
* The isEmpty method checks to see if the list is empty.
* #return true if the list is empty, false otherwise.
*/
public boolean isEmpty() {
return head == null;
}
/**
* The size method returns the length of the list.
* #return The number of elements in the list.
*/
public int size() {
int count = 0;
Node p = head;
while(p != null) {
count++;
p = p.next;
}
return count;
}
public void insert(String name, int score) {
Node node = new Node(name, score);
if(isEmpty()) {
head = node;
tail = node;
}
else if(head.score <= node.score) {
node.next = head;
head = node;
}
else {
Node frontPtr = head.next;
Node backPtr = head;
while(frontPtr.score > node.score && frontPtr.next != null) {
backPtr = backPtr.next;
frontPtr = frontPtr.next;
}
if(frontPtr != null && frontPtr.score <= node.score) {
backPtr.next = node;
node.next = frontPtr;
}
else {
frontPtr.next = node;
tail = node;
}
}
if(size() > 10) {
Node currentPtr = head;
while(currentPtr.next != tail) {
currentPtr = currentPtr.next;
}
tail = currentPtr;
currentPtr.next = null;
}
}
public void printList() {
Node temp = head;
while(temp != null) {
System.out.print(temp.name + " " + temp.score + " ");
System.out.println("");
temp = temp.next;
}
}
}
Here is my class to test GamerList:
public class TestGamerList {
/**
* #param args
*/
public static void main(String[] args) {
GamerList list1 = new GamerList();
list1.insert("Fry", 89);
list1.insert("Bender", 25);
list1.insert("Leela", 90);
list1.insert("Zoidburg", 23);
list1.insert("Amy", 34);
list1.insert("Hermes", 96);
list1.insert("Zapp",123);
list1.insert("Nibbler", 56);
list1.insert("Calculon", 12);
list1.insert("Hypnotoad", 189);
list1.insert("Lrrr", 5);
list1.insert("Scruffy", 28);
System.out.println("Top 10 Scores: ");
list1.printList();
}
}
Looks like you don't set head's next. That's one problem. The second is, even if you do that, you'll get into infinite loop, 'cause you have done the insertion logic incorrectly. I've changed you insert() a bit to make it work, but that still lacks elegance and is far from effective implementation. For example, on every insertion after you've got 10 elements you are running size() which makes your code complexity increase by a factor of approx. N = size(). If you really want to do that, make size a variable and just increase it at the end of every insert(). Anyway, edited code:
public class GamerList {
private class Node {
String name;
int score;
Node next;
Node(String val1, int val2, Node n) {
name = val1;
score = val2;
next = n;
}
Node(String val1, int val2) {
this(val1, val2, null);
}
}
private Node head;
private Node tail;
/**
* Constructor.
*/
public GamerList() {
head = null;
tail = null;
}
/**
* The isEmpty method checks to see if the list is empty.
* #return true if the list is empty, false otherwise.
*/
public boolean isEmpty() {
return head == null;
}
/**
* The size method returns the length of the list.
* #return The number of elements in the list.
*/
public int size() {
int count = 0;
Node p = head;
while(p != null) {
count++;
p = p.next;
}
return count;
}
public void insert(String name, int score) {
Node node = new Node(name, score);
if(isEmpty()) {
head = node;
head.next = tail;
}
else if(head.score <= node.score) {
node.next = head;
head = node;
}
else {
Node beforeNode = head;
while(beforeNode.score > node.score && beforeNode.next != null) {
beforeNode = beforeNode.next;
}
node.next = beforeNode.next;
beforeNode.next = node;
}
if(size() > 10) {
Node currentPtr = head;
for (int i = 0; i < 9; i++) {
currentPtr = currentPtr.next;
}
currentPtr.next = null;
}
}
public void printList() {
Node temp = head;
while(temp != null) {
System.out.print(temp.name + " " + temp.score + " ");
System.out.println("");
temp = temp.next;
}
}
}
Without stack trace is complex.
but probably error is here
while(frontPtr.score > node.score && frontPtr.next != null)
since frontPtr is null.
add a check on the
if (frontPtr!=null)
while(frontPtr.score > node.score && frontPtr.next != null)
I know how to find if a binary tree has a certain path with a given sum (If this is not the best way please let me know):
int pathSum(MyNode root, int sum)
{
if(root == null)
return -1;
int temp = sum - root.value;
return(pathSum(root.left,temp) || pathSum(root.right,temp));
}
What I am not able to figure out is how to print the particular path.
My Node class looks like this:
class MyNode {
int value;
MyNode left;
MyNode right;
MyNode(int value)
{
this.value = value;
}
}
Try this, use overloading:
public void pathToSum(int sum) {
pathToSum(root, sum);
}
private boolean pathToSum(Node n, int sum) {
if (null != n) {
sum -= n.data;
boolean found = pathToSum(n.left, sum);
if (!found) {
found = pathtoSum(n.right, sum);
}
if (found) {
println(n.data);
return found;
}
}
return 0 == sum ? true : false;
}
This code is tested with the following classes:
import java.util.LinkedList;
import java.util.Queue;
public class BST {
Node root;
public BST(){
root = null;
}
public void insert(int el){
Node tmp = root, p=null;
while(null!=tmp && el != tmp.data){
p=tmp;
if(el<tmp.data)
tmp=tmp.left;
else
tmp=tmp.right;
}
if(tmp == null){
if(null == p)
root = new Node(el);
else if(el <p.data)
p.left= new Node(el);
else
p.right=new Node(el);
}
}//
public void pathToSum(int sum) {
pathToSum(root, sum);
}//
private boolean pathToSum(Node n, int sum) {
if (null != n) {
sum -= n.data;
boolean found = pathToSum(n.left, sum);
if (!found) {
found = pathToSum(n.right, sum);
}
if (found) {
System.out.println(n.data);
return found;
}
}
return 0 == sum ? true : false;
}
public static void main(String[] args){
int[] input={50,25,75,10,35,60,100,5,20,30,45,55,70,90,102};
BST bst = new BST();
for(int i:input)
bst.insert(i);
bst.pathToSum(155);
}
}
class Node{
public int data;
public Node left;
public Node right;
public Node(int el){
data = el;
}
}
Result:
45
35
25
50
I suggest to alter your MyNode class to include a parent node:
MyNode left;
MyNode right;
MyNode parent;
MyNode(int value, MyNode parent)
{
this.value = value;
this.parent = parent;
}
and then when you hit a node with correct sum, you can pass that node to another function that goes throug the ancestry until it hits node with null parent (the root).
Nice puzzle, I liked it. You almost had it, just some confusion over int vs boolean, and not checking end condition of sum being zero.
public class NodeSums {
static boolean pathSum(MyNode root, int sum) {
boolean ret;
if (root == null) {
ret = sum == 0;
} else {
int remain = sum - root.value;
ret = pathSum(root.left,remain) || pathSum(root.right, remain);
}
return ret;
}
static class MyNode {
int value;
MyNode left;
MyNode right;
MyNode(int value) {
this.value = value;
}
}
public static void main(String[] args) {
/**
* Valid sums will be 3, 8, and 9
*
* 1 -- 2
* --
* -- 3 -- 4
* --
* -- 5
*/
MyNode root = new MyNode(1);
root.left = new MyNode(2);
root.right = new MyNode(3);
root.right.left = new MyNode(4);
root.right.right = new MyNode(5);
for (int i = 1; i < 10; i++) {
System.out.println("Path sum " + i + " " + pathSum(root, i));
}
}
}
Output
Path sum 1 false
Path sum 2 false
Path sum 3 true
Path sum 4 false
Path sum 5 false
Path sum 6 false
Path sum 7 false
Path sum 8 true
Path sum 9 true
If you store the parent of each node in MyNode, you can find the (reversed) path from the root to any node by getting the parent in a loop until it is null.
Also, your code for pathSum seems to be mixing booleans and ints, and you never check the value of sum.
I have been trying to write a Java function IntList get(int i) that is supposed to return a reference to the i-th element in a singly linked integer list.
My problem is that the function returns null, even if I try to reference an existing element!
public class IntList {
private int info; //the int data of this list element
private IntList next; //the rest of the list
/**
* Sets up a new instance of IntList corresponding to the given info and next.
* #param info the int data of this list element
* #param next the rest of the list
*/
public IntList(int info, IntList next) {
this.info = info;
this.next = next;
}
/**
* A new list where the given info has been prepended.
* #param info the int data of the new list element
* #return a new instance of IntList
*/
/*
public IntList prepend(int info) {
return new IntList(info, this);
}
*/
/**
* A new list where the given info has been appended.
* #param info the int data of the new list element
* #return a new instance of IntList
*/
public IntList append(int info) {
if(next == null) {
return new IntList(this.info, new IntList(info, null));
} else {
return new IntList(this.info, next.append(info));
}
}
/**
* Commputes the sum of all elements of this list.
* #return the sum of all elements
*/
public int sum() {
if(next == null) {
return info;
} else {
return info + next.sum();
}
}
/**
* Auxiliary function for the reversal of this list.
* #param acc the list elements accumulated so far
* #return a new instance of IntList
*/
private IntList reverseAux(IntList acc) {
if(next == null) {
return new IntList(info, acc);
} else {
return next.reverseAux(new IntList(info, acc));
}
}
/**
* A new list with the elements of this list in reverse order.
* #return a new instance of the IntList
*/
public IntList reverse() {
return reverseAux(null);
}
/**
* String representation of this list.
*/
#Override
public String toString() {
if(next == null) {
return "" + info;
} else {
return info + " , " + next;
}
}
/**
* An integer array is converted to a list
* #param values is an array containing integer elements
* #return a new instance of IntList
*/
public static IntList fromArray(int[] values) {
int n = values.length;
IntList res = new IntList(values[0] , null);
for(int i = 1; i < n ; i ++) {
res = res.append(values[i]);
}
return res;
}
/**
* The length of a given IntList object is determined
* #return the length of the list
*/
public int length() {
int counter = 1;
while(next != null) {
counter = counter + 1;
next = next.next;
}
return counter;
}
public IntList get(int i) {
for(int k = 0 ; k < i - 1 ; k ++) {
if(next != null) {
next = next.next;
}
}
return next;
}
public static void main(String[] args) {
IntList lst = new IntList(1, null);
for(int i = 2 ; i < 10 ; i ++) {
lst = lst.append(i);
}
System.out.println(lst);
System.out.println(lst.reverse());
System.out.println(lst.sum());
int[] values = new int[4];
values[0] = 3;
values[1] = 4;
values[2] = 5;
values[3] = 8;
System.out.println(fromArray(values));
System.out.println(lst.length());
System.out.println(fromArray(values).length());
System.out.println(lst.get(2));
}
}
Since my implementation of the list does not require two separate classes for nodes and the list itself, I cannot find any valuable information on the web (most people use two classes).
This one works without checking for IndexOutOfBoundsException:
public IntList get(int i) {
IntList current = this;
for(int k = 0 ; k < i - 1 ; k ++) {
if(current.next != null) {
current = current.next;
}
}
return current;
}
Your length method modifies next. Make it recursive (or make a new variable to step through your list):
public int length() {
if(next != null) {
return 1 + next.length();
}
else {
return 1;
}
}
Your get method also modifies the original list. Recursive solution is:
public IntList get(int i) {
if (i < 0) {
throw new IndexOutOfBoundsException("Index is negative!");
}
if (i == 0) {
return this;
} else if (next != null) {
return next.get(i - 1);
}
throw new IndexOutOfBoundsException("Index exceeds bounds");
}
I think you want something like this...
public IntList append(int info) {
if(next == null) {
return new IntList(info, this);
} else {
return new IntList(info, next);
}
}