Currently I have managed to get all 4 cases of rotation code right. My problem now is to get words that are in a range defined by the system. It is inclusive of start and exclusive of end stop words provided by the system.
The method I am using to get the total numbers of words is working correctly as I am using a nodeSize method whereby it is the addition of both left and right subtree and itself [left subtree+rightsubtree+1].The difference or number of words in a range is obtained as there are overlap points for both start and end stop words.
What I am using to update for all nodes sizes in an AVL tree is to implement nodeSize method in an inorder method. This works fine as i have checked earlier for small range details. The only issue now I encounter how to make it more time efficient when there are over 10,000 nodes in the tree and over 5000 queries for it.
public int nodeSize(BSTVertex T) {
if (T == null) {
return 0;
} else {
return nodeSize(T.left) + nodeSize(T.right) + 1;
}
}
public void insert(String v) {
root = insert(root, v);
}
protected BSTVertex insert(BSTVertex T, String v) {
if (T == null) {
return new BSTVertex(v);
}
if (T.key.compareTo(v) < 0) {
T.right = insert(T.right, v);
T.right.parent = T;
} else {// search to the left
T.left = insert(T.left, v);
T.left.parent = T;
}
T.totalNode = nodeSize(T);
int balance = nodeHeight(T.left) - nodeHeight(T.right);
if (balance == 2) {
int balance2 = nodeHeight(T.left.left) - nodeHeight(T.left.right);
if (balance2 == 1) {
T = rightRotation(T);
} else {//Left Right Case 2,-1
T.left = rotateLeft(T.left);
T = rightRotation(T);
}
}
if (balance == -2) {
int balance2 = nodeHeight(T.right.left) - nodeHeight(T.right.right);
if (balance2 == -1) {
T = rotateLeft(T); //single left for -1
} else {//Right left case, -2,1
T.right = rightRotation(T.right);
T = rotateLeft(T);
}
}
inorder(T);
return T;
}
Related
I've been attempting to follow some pseudocode, namely
https://www.geeksforgeeks.org/a-search-algorithm/ &
http://mat.uab.cat/~alseda/MasterOpt/AStar-Algorithm.pdf ,
to create an A star pathfinding algorithm for a four-directional tile/cell-based map with obstacles. I understand the concept, and I could definitely explain how it should work in words/images, but putting it into code is proving challenging. For a few days now whenever I've run my program it crashes and I have to manually stop the application. I believe this is due to an infinite while-loop. This confuses me because the program should exit the while-loop once its found the end destination, but obviously that isn't working. This is the code which I think should make it exit the while-loop once the destination is found:
if (n.getX() == end.getX() && n.getY() == end.getY()) {
currentNode = n;
break;
}
I hope this isn't too much code to put in this post, but this is the meat of my algorithm with comments on what I think each piece is doing:
public void attempt2() {
double leastF = Integer.MAX_VALUE;
// Initializes the starting Node and, in the beginning, currentNode is the same
// as the starting node
Node start = new Node(r.getCell());
Node currentNode = start;
start.setParent(start);
closed.add(start);
open.add(start);
start.setEnd(destinationCP);
start.calculateH();
start.isCalculatedH();
while (open.size() > 0) {
// Finds the node with the least F score on Open
for (Node n : open) {
// Calculates the H-score if it hasn't been already
if (n.haveNotCalculatedH()) {
n.setEnd(destinationCP);
n.calculateH();
n.isCalculatedH();
}
// Calculates the g-score, with 1 being the value/distance of a cell
n.setAdditiveDistanceG(n.getAdditiveDistanceG() + 1);
// Calculates the F-score
n.calculateF();
// Actually finds the least F score in the open list and sets currentNode to the
// node with the least F
if (n.getTotalCostF() < leastF) {
leastF = n.getTotalCostF();
currentNode = n;
}
}
//
// Creates easy-access variables for the x and y values of the node on open with
// the least F score
int thisX = currentNode.getX();
int thisY = currentNode.getY();
// if this cell (cell in open w least F) is the end destination cell, stop the calculations
if (thisX == end.getX() && thisY == end.getY()) {
break;
}
//
// Generate 1-4 successors if Robot can pass into the cell
if (World.getCell(thisX + 1, thisY).canEnter(r)) {
successors.add(new Node(World.getCell(thisX + 1, thisY)));
}
if (World.getCell(thisX, thisY + 1).canEnter(r)) {
successors.add(new Node(World.getCell(thisX, thisY + 1)));
}
if (World.getCell(thisX - 1, thisY).canEnter(r)) {
successors.add(new Node(World.getCell(thisX - 1, thisY)));
}
if (World.getCell(thisX, thisY - 1).canEnter(r)) {
successors.add(new Node(World.getCell(thisX, thisY - 1)));
}
//
/*
* Loops through each of the 1-4 neighbors to currentNode (I need to add in to
* erase & add to open/closed every one in here so its empty before new ones are
* generated
*/
for (Node n : successors) {
double successorCurrentCost = 0;
// if this successor is already in the closed list, skip doing all the code for
// this node and add this successor's parent (currentNode) to the closed list
if (isInClosed(n)) {
continue;
}
// if this is the goal/end node, exit the 'successors' for-loop. the step that
// follows this (exiting the loop) is that this particular node/successor is
// added to the closed list
if (n.getX() == end.getX() && n.getY() == end.getY()) {
currentNode = n;
break;
}
//
// Calculates the F cost for each successor to currentNode
if (n.haveNotCalculatedH()) {
n.setEnd(destinationCP);
n.calculateH();
n.isCalculatedH();
}
n.setAdditiveDistanceG(n.getAdditiveDistanceG() + currentNode.getAdditiveDistanceG());
n.calculateF();
successorCurrentCost = n.getTotalCostF();
//
if (!isInOpen(n) && n.getAdditiveDistanceG() > successorCurrentCost
|| n.getAdditiveDistanceG() > successorCurrentCost && !isInClosed(n)) {
open.add(n);
if (n.haveNotCalculatedH()) {
n.setEnd(destinationCP);
n.calculateH();
n.isCalculatedH();
}
} else if (isInClosed(n) && n.getAdditiveDistanceG() <= successorCurrentCost) {
successorCurrentCost = n.getAdditiveDistanceG();
n.setParent(currentNode);
} else {
successorCurrentCost = n.getAdditiveDistanceG();
n.setParent(currentNode);
}
if (isInClosed(n)) {
closed.remove(n);
open.add(n);
}
}
closed.add(currentNode);
if (thisX == end.getX() && thisY == end.getY()) {
break;
}
}
if (currentNode.getMyCell() != this.destinationCP) {
System.out.println("ERROR: open list is empty");
return;
} else {
createPath();
}
}
I am aware that there are a few things that should be changed in this code, however I am most concerned about the while loop never being terminated. Any other comments about my code are appreciated but definitely not necessary.
We were given the Node class and we have to implement the recursive insertion. After the insertion my output is wrong and I don't know why
The function printTree was given:
public void printTree() {
printTree(root,0);
}
public void printTree(TreeNode<T> p, int depth) {
if (p != null) {
if (!(p.left == null && p.right == null))
printTree(p.right,depth+1);
for (int i = 1; i <= depth; i++)
System.out.print(" ");
if (p.left == null && p.right == null)
System.out.println(p.info + " ");
else System.out.println(p.info);
printTree(p.left,depth+1);
}
}
This is my insertion function:
public void insert(T info)
{
root = insert(root, info);
}
protected TreeNode<T> insert(TreeNode<T> node, T info)
{
if (node == null)
{
node = new TreeNode<T>(info);
}
else if (info.compareTo(node.info) < 0)
{
node.left = insert(node.left,info);
}
else
{
node.right = insert(node.right,info);
}
return node;
}
This is my main:
public static void main(String[] args) {
// TODO code application logic here
Tree<Integer> t = new Tree<Integer>();
t.insert(4);
t.insert(3);
t.insert(5);
t.insert(1);
t.printTree();
}
and the output I get is:
5
4
3
1
instead of:
4
3 5
1
The output seems ok to me.
The printTree method does not work as you expect. It prints the tree from top to bottom level, but on the screen the output is "rotated" by 90 deg
So the top level is meant to be on the first column, bottom level at the last non-empty column.
I've had a go, and it works for the left subtree but not the right.
I'm close but my logic is wrong, can anyone help correct and explain the logic to this.
public static MyNode preOrderNumbering(MyNode n) {
if (n != null) {
n.obj = 0; // Set root decoration to 0;
preOrderHelper(n, 1); // Set decorations according to preorder.
}
return n;
}
public static MyNode preOrderHelper(MyNode n, int counter) {
if (n != null) {
if (n.left != null) {
n.left.obj = counter++; // Set the left object decoration to current count + 1;
preOrderHelper(n.left, counter);
}
if (n.right != null) {
n.right.obj = counter++; // Set the left object decoration to current count + 1;
preOrderHelper(n.right, counter);
}
}
return n;
}
Before:
After:
You need to update the counter with everything that's discovered on the left before going to the right.
Something like this:
public static int preOrderNumbering(MyNode n, int count){
if(n != null){
n.obj = ++count;
count = preOrderNumbering(n.left, count);
count = preOrderNumbering(n.right, count);
}
return count;
}
You're passing counter by value, not by reference (because that's how Java works), so when the recursion unwinds, so will the counter.
You could update the counter by returning the current value from the recursive call.
So here is the Node class:
public class Node
{
private int _info;
private Node _left;
private Node _right;
public Node()
{
//this._info = Integer.MIN_VALUE;
this._left = null;
this._right = null;
}
public int getInfo()
{
return _info;
}
public void setInfo(int _info)
{
this._info = _info;
}
public Node getLeft()
{
return _left;
}
public void setLeft(Node _left)
{
this._left = _left;
}
public Node getRight()
{
return _right;
}
public void setRight(Node _right)
{
this._right = _right;
}
}
How I create the tree:
public class BalancedBinaryTree
{
private ArrayList<Integer> _numbers;
private Node _root;
public BalancedBinaryTree(ArrayList<Integer> numbers)
{
this._numbers = new ArrayList<>();
this._numbers.addAll(numbers);
Collections.sort(this._numbers);
this._root = new Node();
this.create(this._root, 0, this._numbers.size());
}
private void create(Node tree, int i, int j)
{
if (i < j)
{
int m = i + (j - i) / 2;
tree.setInfo(this._numbers.get(m));
tree.setLeft(new Node());
create(tree.getLeft(), i, m);
tree.setRight(new Node());
create(tree.getRight(), m + 1, j);
}
}
This method computes the depth:
public static int getDepth(Node node)
{
if (node == null)
{
return 0;
}
else
{
int max = 0;
if (getDepth(node.getLeft()) > getDepth(node.getRight()))
{
max = getDepth(node.getLeft());
}
else
{
max = getDepth(node.getRight());
}
return max + 1;
}
}
And these two combined should print the tree by its levels:
public static void printLevel(Node node, int levelToDisplay, int currentLevel)
{
if (node != null)
{
printLevel(node.getLeft(), levelToDisplay, currentLevel);
if (currentLevel == levelToDisplay)
{
System.out.print(node.getInfo() + " ");
}
currentLevel++;
printLevel(node.getRight(), levelToDisplay, currentLevel);
}
}
public static void printLevels(Node node)
{
for (int i = 0; i < getDepth(node); i++)
{
System.out.println("Level :" + i);
printLevel(node, i, 0);
System.out.println();
}
}
In a test class I have:
testNumbers.add(15);
testNumbers.add(20);
testNumbers.add(25);
testNumbers.add(30);
testNumbers.add(35);
testNumbers.add(40);
testNumbers.add(45);
BalancedBinaryTree tree = new BalancedBinaryTree(testNumbers);
BalancedBinaryTree.printLevels(tree.getRoot());
And I get this output:
Level :0
0 15 20 30
Level :1
0 0 25 0 35 40
Level :2
0 0 0 45
Level :3
0
I should get
Level :0
30
Level :1
20 40
Level :2
15 25 35 45
What's wrong with the getDepth method because it seems that it returns 4 levels instead of 3?
Why are there additional nodes? (those zeroes)
I'm pretty sure I solved the problems but I will need an explanation for the following:
This is the modified printlevel method:
public static void printLevel(Node node, int levelToDisplay, int currentLevel)
{
if (node.getLeft() != null && node.getRight() != null)
{
printLevel(node.getLeft(), levelToDisplay, currentLevel+1);
if (currentLevel == levelToDisplay)
{
System.out.print(node.getInfo() + " ");
}
printLevel(node.getRight(), levelToDisplay, currentLevel+1);
}
}
As you can see I test now if the current node has childs instead of checking if the current node exists and this is why those zeroes appeard because the traversal reached the leafs that had no info assigned on their right and left childs.
The thing I want to understand is the difference between incrementing currentLevel and then passing it to the call of printLevel and simply passing currentLevel+1 to the call. Shouldn't it be the same thing ?
And the getDepth function:
public static int getDepth(Node node)
{
if (node.getLeft() == null && node.getRight() == null)
{
return 0;
}
else
{
int max = 0;
if (getDepth(node.getLeft()) > getDepth(node.getRight()))
{
max = getDepth(node.getLeft());
}
else
{
max = getDepth(node.getRight());
}
return 1 + max;
}
}
Same thing here: traversal reached the leafs and got one more call for its childs thus returning one additional level so again, the solution is to test if the current node has childs instead of checking if the current node exits.
What's wrong with the getDepth method because it seems that it returns 4 levels instead of 3?
From your print method it seems, that you number the levels from 0 to n (the root of a tree beeing 0). Your getDepth method however will never return 0.
Two things: if (node != null) this check does not seem to make very much sense. Null does not seem to be an allowed input (as the root is constructed on construction of a Tree). If this is the case (and you do want to check it) an exception might be more appropriate.
The main problem seems to be this: return max + 1;
So the minimal value returned is 0 + 1, which is 1.
As a small sidenote: I would save the values of the two recursive calls of getDepth, it would greatly increase performance.
Also, if you do use short variable names such as i, m or j (in a non-loop index kind of way) it would be helpful to document their meaning.
And conserning your first question:
tree.setLeft(new Node());
What would be the value of this Node as of now? And what will happen if the i < j codition in the recurive call will not pass? If you can answer those questions, you should be able to fix the code yourself.
I have 1000 numbers and I make a binary tree and sort the tree. It prints 0 to 100 and the other 899 numbers are duplicates. How can I keep track of the frequency of each number. Like for example the number 28 appears 9 times. Keeping a count somehow. I've been working with one method but Idk if it's close or not. I'll post that method at the end.
public class bigTree {
int data;
int frequency;
bigTree Left, Right;
public bigTree makeTree(int x) {
bigTree p;
p = new bigTree();
p.data = x;
p.Left = null;
p.Right = null;
return p;
}
public void setLeft(bigTree t, int x) {
if (t.Left != null) {
// setLeft(t.Left, x);
System.out.println("Error");
}
else {
t.Left = makeTree(x);
}
}
public void setRight(bigTree t, int x) {
if (t.Right != null) {
//setRight(t.Right, x);
System.out.println("Error");
} else {
t.Right = makeTree(x);
}
}
public void insertLocation(bigTree tree, int v) {
// if (tree.data == v) {
//findDuplicate(v);
//}
if (v < tree.data) {
if (tree.Left != null){
insertLocation(tree.Left, v);
}
else {
setLeft(tree, v);
}
}
if (v > tree.data) {
if (tree.Right != null){
insertLocation(tree.Right, v);
} else {
setRight(tree, v);
}
}
}
public void sort(bigTree t) {
if (t.Left != null) {
sort(t.Left);
}
System.out.println(t.data + " freq = " + frequency);
if (t.Right != null) {
sort(t.Right);
}
}
public void dealArray( String[] x) {
int convert;
bigTree tree = makeTree(Integer.parseInt(x[0]));
for (int i = 1; i < x.length; i++){
//convert = Integer.parseInt(x[i]);
insertLocation(tree, Integer.parseInt(x[i]));
findDuplicate(Integer.parseInt(x[i]));
} sort(tree);
}
----A method that I thought could work but isnt----
public void findDuplicate(int number) {
bigTree tree, h, q;
tree = makeTree(number);
//while (//there are #'s in the list) { //1st while()
h = tree;
q = tree;
while (number != h.data && q != null) { //2nd while()
h = q;
if (number < h.data ) {
q = q.Left;
} else {
q = q.Right;
}
} //end of 2nd while()
if (number == h.data) {
//h.frequency++;
System.out.println("Duplcate: " + number + "freq = " + h.frequency++);
}
else {
if (number < h.data) {
setLeft(h,number);
}
else {
setRight(h, number);
}
}
//} // End of 1st while()
sort(h);
}
PrePost:
If you need to use the binary tree search, it appears that your code above is creating a new tree for each element that it is looking for. Instead you should have a single tree that you search, add / update for each element that you are looking for.
Previous Post:
Although #Woot4Moo's answer will work, there is the overhead of creating the count and incrementing. I would suggest using Guava's ListMultimap class to handle all this for you.
ListMultimap
ListMultimap<Integer, Integer> mymap;
for (Integer value : values){
mymap.put(value, value);
}
Map<Integer, List<Integer>> asmap = mymap.asMap();
for (Entry<Integer, List<Integer>> entry : asmap.entrySet()){
System.out.println(String.format("Value %d occurred %d times", entry.getKey(), entry.getValue().size());
}
So the first thing you need to do is select a data structure that can represent a value and the number of duplicates it has. The first thing that comes to mind is a Map
Map<Integer,Integer> // Keeps track of the integer that is the key and the count which is the value
So what needs to happen as you parse out your array (or whatever structure you are reading this values from) is do a check on the Map like so:
myMap.contains(integerToCheck);
if contains returns true you need to increment the value stored in myMap for that key. Else you need to insert a new key that uses integerToCheck and a new value of 1 .
Then to print those values you would do the following:
for(Map.Entry<Integer,Integer> entry: myMap.entrySet())
{
System.out.println(entry.getKey + " : " + entry.getValue());
}
I Think your heading in the right direction.
1) You need to sort your elements. There is a number of ways to do this.
enter link description here
2) You need to find the duplicate elements. This can be done by comparing ith element with i+1 element. You can store your answers in a Map.