I am trying to implement a splay(Node x) method for a Binary Search Tree. I have the leftRotation(Node x) and rightRotation(Node x) methods implemented correctly (atleast, I think they are...), but when I try to implement them in a splay(Node x) method, it calls itself in an infinite loop. Now, I know why it's doing that, but can't seem to figure out how to fix it.
Here is the leftRotation(Node x) method:
public void leftRotation(Node<E> x) {
if (x.getRightChild() == null) {
return;
}
Node<E> y = x.getRightChild();
x.setRightChild(y.getLeftChild());
if (y.getLeftChild() != null) {
y.getLeftChild().setParent(x);
}
y.setParent(x.getParent());
if (x.getParent() == null) {
root = y;
} else {
if (x == x.getParent().getLeftChild()) {
x.getParent().setLeftChild(y);
} else {
x.getParent().setRightChild(y);
}
}
y.setLeftChild(x);
x.setParent(y);
}
Here's the rightRotation(Node x) method:
public void rightRotation(Node<E> x) {
if (x.getLeftChild() == null) {
return;
}
Node<E> y = x.getLeftChild();
x.setRightChild(y.getRightChild());
if (y.getRightChild() != null) {
y.getRightChild().setParent(x);
}
y.setParent(x.getParent());
if (x.getParent() == null) {
root = y;
} else {
if (x == x.getParent().getRightChild()) {
x.getParent().setRightChild(y);
} else {
x.getParent().setLeftChild(y);
}
}
x.setRightChild(x);
x.setParent(y);
}
And here's the splay(Node x) method:
public void splay(Node<E> x) {
while (x.getParent() != null) {
if (x.isLeftChild && x.getParent().isLeftChild) {
this.rightRotation(x.getParent());
this.rightRotation(x);
} else if (x.isRightChild && x.getParent().isRightChild) {
this.leftRotation(x.getParent());
this.leftRotation(x);
} else if (x.isLeftChild && x.getParent().isRightChild) {
this.rightRotation(x);
this.leftRotation(x);
} else if (x.isRightChild() && x.getParent().isLeftChild()) {
this.leftRotation(x);
this.rightRotation(x);
} else if (x.isLeftChild && x.getParent() == root) {
this.rightRotation(x);
} else if (x.isRightChild && x.getParent() == root) {
this.leftRotation(x);
}
}
}
Any ideas on how to fix the infinite loop? It seems to be something to do with it not breaking out of the while(x.getParent() != null) statement in the splay(Node x) method, but when I went through the code using the debugger, the properties of the node seemed to be changing, so I don't really know where it's going wrong?
setLeftChild(Node leftChild) method:
public void setLeftChild(Node<E> leftChild) {
this.leftChild = leftChild;
if (leftChild != null) {
leftChild.setIsRightChild(true);
leftChild.setParent(this);
}
}
Apart from all the mistakes/bad things I pointed out in your code, here is the biggest one, in rightRotation :
x.setRightChild(x);
This creates a cycle in your tree, hence the infinite loop. You should have unit tested your methods. One other major error in your code is that your if - else if instructions do not have an else so there might be cases where nothing happens during an iteration... hence the infinite loop. It's not the case here because you considered all the cases (actually, you considered even more, and the two last ones will never be executed because the four first cases cover every possible case) but as a general remark, this was really dangerous to code it that way.
Here is the code of my own implementation of all these methods, which I deem cleaner :
public class BinaryTree<T extends Comparable<T>> {
private Node<T> root;
public void rebalance(Node<T> node) {
while (!node.isRoot()) rotation(node.getParent(), node.getChildKind().opposite());
}
private void rotation(Node<T> node, Side side) {
if (node.getChild(side.opposite()) == null) return;
Node<T> sideChild = node.getChild(side.opposite());
node.setChild(sideChild.getChild(side), side.opposite());
if (node.getParent() == null) setRoot(sideChild);
else node.getParent().setChild(sideChild, node.getChildKind());
sideChild.setChild(node, side);
}
private void setRoot(Node<T> root) {
this.root = root;
if (root != null) root.setRoot();
}
private static enum Side {
LEFT, RIGHT;
public Side opposite() { return this == LEFT ? RIGHT : LEFT; }
}
private static class Node<T extends Comparable<T>> {
private T value;
private Node<T> left, right, parent;
public Node(T value) { this(value, null, null, null); }
public Node(T value, Node<T> left, Node<T> right, Node<T> parent) {
setValue (value );
setLeft (left );
setRight (right );
setParent(parent);
}
public Node<T> setLeft(Node<T> left) {
this.left = left;
if (left != null) left.parent = this;
return this;
}
public Node<T> setRight(Node<T> right) {
this.right = right;
if (right != null) right.parent = this;
return this;
}
public Node<T> setChild(Node<T> child, Side side) { return side == Side.LEFT ? setLeft(child) : setRight(child); }
public Node<T> setRoot() { return setParent(null); }
private Node<T> setParent(Node<T> parent) {
this.parent = parent;
return this;
}
public Node<T> setValue(T value) {
this.value = notNull(value);
return this;
}
public boolean isRoot() { return parent == null; }
public boolean isLeftChild () { return isRoot() || getParent().getValue().compareTo(getValue()) > 0; }
public boolean isRightChild() { return isRoot() || !isLeftChild() ; }
public Node<T> getChild(Side side) { return side == Side.LEFT ? getLeft() : getRight(); }
public Side getChildKind() {
Check.isFalse(isRoot(), "This method is not defined on root nodes");
return isLeftChild() ? Side.LEFT : Side.RIGHT;
}
public T getValue () { return value ; }
public Node<T> getLeft () { return left ; }
public Node<T> getRight () { return right ; }
public Node<T> getParent() { return parent; }
}
}
Note : my tree is not always optimally rebalanced. I did this out of my head but I will check at Wikipedia to see what they say, I probably did not apply the right algorithm, but it works pretty fine already expect in pathologic cases.
Related
hey I am new in the binary trees world and I am trying to compare to values to know which direction should I place the newly added node next.
for now, I tried to do CompareTo method but didn't succeed very much I am now trying to make a private method that will give me the value of the Nodes i would love some help
this is my code now I need to add to the if statement the comparing of nodes so I can proceed :
public void add(E data) {
if(root == null) {
return ;
}
if(root.getLeftSon() == null) {
root.setLeftSon((Node<E>) data);
}
else if(root.getRightSon() == null) {
root.setRightSon((Node<E>) data);
}
}
you have to use generics correctly. Parameter has to extend comparable so you can determinate how to sort it.
class BinaryTree<T extends Comparable<T>> {
Node<T> root;
public Node<T> addRecursive(Node<T> current, T value) {
if (current == null) {
return new Node<T>(value);
}
int ord = value.compareTo(current.value);
if (ord > 0) {
current.left = addRecursive(current.left, value);
} else if (ord < 0) {
current.right = addRecursive(current.right, value);
} else {
// value already exists
return current;
}
return current;
}
static class Node<T extends Comparable<T>> {
T value;
Node<T> left;
Node<T> right;
Node(T value) {
this.value = value;
right = null;
left = null;
}
}
}
Implementing LinkedList in a recursive approach was a bit challenging to me, which I get stuck in implementing of its remove method and wonder how to keep reference to previous item in recursive?
MyLinkedList class
package linkedlist;
public class MyLinkedList {
private Integer value;
private MyLinkedList next;
public MyLinkedList() {
}
public MyLinkedList(Integer value) {
this.value = value;
}
public void add(Integer value) {
if (this.value == null) {
this.value = value;
} else if (this.next == null) {
this.next = new MyLinkedList(value);
} else {
this.next.add(value);
}
}
public MyLinkedList remove(Integer index) {
//
// if (index < 0) {
// return this;
// }
// if (index == 0) {
// return this.next;
// }
// this.next = remove(index - 1);
return this;
}
public Integer indexOf(Integer value) {
if (this.value.equals(value)) {
return 0;
} else if (this.next == null) {
return null;
} else {
return 1 + this.next.indexOf(value);
}
}
}
MyLinkedListTester class
package linkedlist;
public class MyLinkedListTester {
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.add(1);
myLinkedList.add(2);
myLinkedList.add(3);
myLinkedList.add(4);
System.out.println("Index Of Array: " + myLinkedList.indexOf(3));
MyLinkedList linkedList = myLinkedList.remove(3);
}
}
As mentioned in the comments the iterative approach is easier and more efficient most of the time. Anyway I think you do this as an exercise because in Java you already have a LinkedList.
So first you have a kind of error in your thinking (as far as I'm aware of it). It's also a kind of bad design choice. You create your MyLinkedList and save the data right into it and the next is also of the class MyLinkedList but it's not a list, it's a Node. There should only be one List, and 0 - many nodes.
For example I can't figure out how to do a remove function that will return the removed Node (in your case MyLinkedList) and as well let you keep the list in case you remove the first element in your list.
If you are looking in the implementation that's why they use Nodes and it's also more logical (a list doesn't contain "List elements") and so on...
Some other remark: your indexOf funtion will return an error if you try to get a element that does not exist (1 + null => error).
So anyway. What you have to do is to create a Node. (btw if you really want a real LinkedList you can use generic instead of int/Integer).
Below I post my solution how to do it (may be better out there but that is how I would do it). I also wrote a toString method to see how the List looks like (and it works as far as I can say). In case you want to still use your code without the Node it should give you an idea how to solve your problem with remove. You can also put some of the logic into the Node class but for me Node is only a container and doesn't really contain any logic.
public class MyLinkedList {
private Node head;
public MyLinkedList() {
}
public class Node{
private int value;
private Node next = null;
public Node(int value){
this.value = value;
}
public int getValue(){
return value;
}
public Node getNext(){
return next;
}
public void setNext(Node next){
this.next = next;
}
}
public void add(int value) {
Node next = new Node(value);
if(head == null){
head = next;
} else {
addRecursive(head,next);
}
}
private void addRecursive(Node node, Node next) {
if(node.next == null){
node.setNext(next);
} else {
addRecursive(node.getNext(),next);
}
}
public Node remove(int index){
Node removeNode = head;
if(index == 0){
head = head.getNext();
} else {
removeNode = removeRecursive(head,index-1);
}
return removeNode;
}
private Node removeRecursive(Node node, int index){
Node removeNode = node.getNext();
if(index == 0){
node.setNext(removeNode.getNext());
} else {
removeNode = removeRecursive(node.getNext(),index-1);
}
return removeNode;
}
public int indexOf(int value) {
if (head == null){
return -1;
} else if (head.getValue() == value){
return 0;
} else {
return indexOfRecursive(head,value,0);
}
}
private int indexOfRecursive(Node node, int value, int index) {
if(node.getNext() == null){
return -1;
} else if(node.getNext().getValue() == value){
return index + 1;
} else {
return indexOfRecursive(node.getNext(),value,index+1);
}
}
#Override
public String toString(){
if(head == null){
return "";
} else {
return toStringRecursive(head,"["+head.getValue());
}
}
private String toStringRecursive(Node node, String output){
if(node.getNext() == null){
return output + "]";
} else {
return toStringRecursive(node.getNext(),output + ", " + node.getNext().getValue());
}
}
}
I am implementing WAVL tree and WAVL node classes. In the WAVL node class I should create a method that counts how much internal nodes exist in the subtree of the node. I should do that in time complexity of O(1). Any suggestions?
The class I wrote is:
package coding_ex1;
public class WAVLNode
{
WAVLNode left;
WAVLNode right;
WAVLNode parent;
int rank;
int key;
String value;
public WAVLNode() //*constructor
{
this.left=null;
this.right=null;
this.parent=null;
this.rank=0;
this.key=0;
this.value=null;
}
public int getKey() //*gets WAVLNode. if external leaf, return -1. else, return key
{
if (this.rank==-1)
{
return -1;
}
return key;
}
public String getValue()//*gets WAVLNode. if external leaf, returns null. else, returns value
{
if (this.rank==-1)
{
return null;
}
return value;
}
public WAVLNode getLeft()//* get WAVLNode. returns left (if there is no left, the value of left is null)
{
return left;
}
public WAVLNode getReft()//* get WAVLNode. returns right (if there is no right, the value of right is null)
{
return right;
}
public boolean isInnerNode()//*gets WAVLNode. returns true for internal leaf. else, returns false
{
if(this.right!=null || this.left!=null)
{
return true;
}
return false;
}
}
You should add a filed and methods.
private int internalNodeCount = 0; // initially count as leaf
public int internalNodeCount() {
return internalNodeCount;
}
public void setLeft(WAVLNode node) {
this.left = node;
setInternalNodeCount();
}
public void setRight(WAVLNode node) {
this.right = node;
setInternalNodeCount();
}
void setInternalNodeCount() {
if (isInnerNode()) {
internalNodeCount = 1; // count for self
if (left != null)
internalNodeCount += left.internalNodeCount;
if (right != null)
internalNodeCount += right.internalNodeCount;
} else
internalNodeCount = 0;
}
I've just created a method to test the height of my binary tree implementation as follows:
public int height() {
return height(rootNode);
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
But it returns a height of 6, and not 7 when i add the nodes 1-6.
Here is my Binary Tree code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<E extends Comparable<E>>
{
private class BinaryTreeNode
{
private E value;
private BinaryTreeNode leftChild, rightChild;
public BinaryTreeNode(E value) {
this(value, null, null);
}
public BinaryTreeNode(E value, BinaryTreeNode leftChild, BinaryTreeNode rightChild) {
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
public E getValue() {
return value;
}
public BinaryTreeNode getLeftChild() {
return leftChild;
}
public BinaryTreeNode getRightChild() {
return rightChild;
}
public void setLeftChild(BinaryTreeNode newLeftChild) {
this.leftChild = newLeftChild;
}
public void setRightChild(BinaryTreeNode newRightChild) {
this.rightChild = newRightChild;
}
}
private BinaryTreeNode rootNode;
public BinaryTree() {
this.rootNode = null;
}
public void addNode(E value) {
if(rootNode == null)
rootNode = new BinaryTreeNode(value);
else
addNode(value, rootNode);
}
//TODO: Implement removeNode()
public void printLevelOrder() {
printLevelOrder(rootNode);
}
public int height() {
return height(rootNode);
}
public void inOrderTraversal() {
if(rootNode != null) inOrderTraversal(rootNode);
else System.out.println("The tree is empty!");
}
private void addNode(E value, BinaryTreeNode node) {
if(node.getValue().compareTo(value) > 0) {
if(node.getLeftChild() != null)
addNode(value, node.getLeftChild());
else
node.setLeftChild(new BinaryTreeNode(value));
} else {
if(node.getRightChild() != null)
addNode(value, node.getRightChild());
else
node.setRightChild(new BinaryTreeNode(value));
}
}
private void printLevelOrder(BinaryTreeNode node) {
Queue<BinaryTreeNode> currentLevel = new LinkedList<BinaryTreeNode>();
Queue<BinaryTreeNode> nextLevel = new LinkedList<BinaryTreeNode>();
currentLevel.add(node);
while (!currentLevel.isEmpty()) {
Iterator<BinaryTreeNode> iter = currentLevel.iterator();
while (iter.hasNext()) {
BinaryTreeNode currentNode = iter.next();
if (currentNode.leftChild != null) {
nextLevel.add(currentNode.leftChild);
}
if (currentNode.rightChild != null) {
nextLevel.add(currentNode.rightChild);
}
System.out.print(currentNode.value + " ");
}
System.out.println();
currentLevel = nextLevel;
nextLevel = new LinkedList<BinaryTreeNode>();
}
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
private void inOrderTraversal(BinaryTreeNode node) {
if(node != null) {
inOrderTraversal(node.leftChild);
System.out.println(node.getValue() + " ");
inOrderTraversal(node.getRightChild());
}
}
public BinaryTreeNode getRoot() {
return rootNode;
}
}
I think the problem is adding my node into the tree, but I've taken a look at other examples but they all seem to be doing the same thing I am.. So i can't realise the problem!
Thanks!
private int height(BinaryTreeNode node) {
if(node == null) return 0;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
You were returning -1 on node==null when you should return 0.
The condition is true when we arrive to leaf so for example if we add 1-2 then we have height as 1+Max(leftof(1),rightof(1))=
1+Max(height(null),height(2))=
1+Max(0,1+Max(leftof(2),rightof(2)))=
1+Max(0,1+Max(height(null),height(null)))=
1+Max(0,1+Max(0,0))=
1+Max(0,1+0)=
1+1=2.
Try to replace height(null) with -1 in the previous example to see by yourself.
By the way your BinaryTree implementation is actually a binary search tree since you're putting less elements on the left and bigger elements on the right, If a search tree is your intention then Ok but if you want to implement a general binary tree then you should change the add function.
So the idea is to make a Double Ended Priority Queue so far I have got a tree like structure using 2 Linked Lists, I have and interface I have to stick with with no alterations to it. The problem I have got is I have to make 2 methods called getMost and getLeast which gets the most or least node and then makes that node null. But these 2 methods are proving quite difficult to make. How would you go about doing it?
I have tried using recursion but this is proving difficult as I have to select the tree by going tree.root but passing in tree.root into a recursive method always starts it from tree.root
Also I have tried what i have written in inspectLeast() and inspectMost() but Java passes by value not by reference. Any tips?
P.S Not allowed to use anything from java collections or java util.
public class PAS43DPQ implements DPQ
{
//this is the tree
TreeNode tree = new TreeNode();
//this is for the size of the array
int size = 0;
#Override
public Comparable inspectLeast() {
return tree.inspectLeast(tree.root);
}
#Override
public Comparable inspectMost() {
return tree.inspectMost(tree.root);
}
#Override
public void add(Comparable c)
{
tree.add(c);
size++;
}
#Override
public Comparable getLeast() {
if (tree.root != null){
}
return getLeast();
}
#Override
public Comparable getMost(){
Comparable most = getMost();
return most;
}
#Override
public boolean isEmpty() {
return (size > 0)?true:false;
}
#Override
public int size() {
return this.size;
}
class TreeNode{
private Comparable value;
private TreeNode left, right, root;
//constructors
public TreeNode() {}
public TreeNode(TreeNode t) {
this.value = t.value;
this.left = t.left;
this.right = t.right;
this.root = t.root;
}
public TreeNode(Comparable c) {
this.value = (int) c;
}
public void add(Comparable input){
if(root == null){
root = new TreeNode(input);
return;
} else {
insert(root, input);
}
}
public Comparable inspectLeast(TreeNode n){
if (n == null)
return null;
if (n.left == null){
TreeNode least = n;
return least.value;
}
return inspectLeast(n.left);
}
public Comparable inspectMost(TreeNode n){
if (n == null)
return null;
if (n.right == null){
TreeNode most = n;
return most.value;
}
return inspectMost(n.right);
}
public Comparable getMost(TreeNode n){
if(n.right == null)
return n.value;
return tree.getMost(right);
}
public void insert(TreeNode n, Comparable input){
if(input.compareTo(n.value) >= 0){
if (n.right == null) {
n.right = new TreeNode(input);
return;
}
else
insert(n.right, input);
}
if(input.compareTo(n.value) < 0){
if(n.left == null) {
n.left = new TreeNode(input);
return;
}
else
insert(n.left, input);
}
}
}
}
You should be able to modify your TreeNode.getMost(TreeNode n) and TreeNode.getLeast(TreeNode n) similar to the following:
public class TreeNode{
// Also, your parameter here seems to be superfluous.
public TreeNode getMost(TreeNode n) {
if (n.right == null) {
n.root.right = null;
return n;
}
return n.getMost(n);
}
}
Get least should be able to be modified in a similar fashion, but using left rather than right obviously.