Struggling With Btree Algorithm - java

I've tried using Java to implement algorithms from the textbook Introduction to Algorithms, 3rd edition, without a lot of success. Almost every time I try to implement them I encounter a multitude of errors, to the point where I'm not sure if the authors themselves have tried implementing their own pseudocode. But specifically, in this case, I'm having problems with the Btree algorithm. I think the problem lies somewhere in the B-Tree-Insert-Nonfull method. When I try to run the program, this line causes a Null Pointer Exception:
int i = x.totalKeys - 1;
However, that doesn't make any sense. All Nodes, like x in this case, are initialized with a value of 0 in their constructors, so how is his error even occurring? I'm going to enclose the function below:
public void bTreeInsertNonfull(Node x, Integer k)
{
int i = x.totalKeys - 1;
if (x.leaf || (x.children[i] == null))
{
while( (i >= 0) && (k < x.keys[i]) )
{
x.keys[i+1] = x.keys[i];
i = i - 1;
}
x.keys[i+1] = k;
x.totalKeys = x.totalKeys + 1;
}
else
{
while ( (i >= 0) && x.keys[i] != null)
{
if (k < x.keys[i])
{
i = i - 1;
}
}
i = i + 1;
if ((x.children[i] != null) && (x.children[i].totalKeys == tUpper))
{
bTreeSplitChild( x, i, x.children[i] );
if (k > x.keys[i])
{
i = i + 1;
}
}
bTreeInsertNonfull(x.children[i], k);
}
}

Elaborating on the idea from Alex: if you look at the last part of the algorithm, there is a line that says:
if ((x.children[i] != null) && (x.children[i].totalKeys == tUpper))
That hints that x.children[i] == null is a possibility. The last line of the algorithm calls bTreeInsertNonfull(x.children[i], k); without checking if the first parameter is null.

Related

How to convert recursion to iteration? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
This question is asked few times but I still find it quite difficult to convert easily readable and intuitive code into iterative code. For example I was practicing a coding question and I am given 26 integers which indicate how many times each character appears in the string. I should print all possible strings. Following is my recursive code
private static void combinatorial(String prefix, ArrayList<Integer> remainingToFill,
int totalLength) {
if (prefix.length() == totalLength) {
System.out.println(prefix);
}
for (int i = 0; i < remainingToFill.size(); i++) {
if (remainingToFill.get(i) > 0) {
ArrayList<Integer> toFill = new ArrayList<>(remainingToFill);
toFill.set(i, toFill.get(i) - 1);
combinatorial(prefix + (char) ('a' + i), toFill, totalLength);
}
}
}
I coded iterative version of this but the resultant function is much more complex and not readable and took more time for me to code it. How do I tackle this kind of problem? Is there any simple technique I can follow which would lead to easy and readable code?
Well, the reason programming languages support recursive expression of programs is that it's often simpler than explicit iterative forms. So your question is almost self-answering.
However, there really is a methodical way to convert recursive forms to iterative forms that always works. It helps to have a language with goto, which Java doesn't.
First let's clean up the java. We want to use a minimum number of arguments and local variables because what's left must go on our explicit stack. Here we go. We do away with all except i and prefix.
class CombinationLister {
private final int[] counts;
private final int length;
CombinationLister(int[] counts) {
this.counts = counts.clone();
this.length = Arrays.stream(counts).sum();
}
private void list(String prefix) {
if (prefix.length() == length) {
System.out.println(prefix);
}
for (int i = 0; i < counts.length; i++) {
if (counts[i] > 0) {
--counts[i];
list(prefix + (char) ('a' + i));
++counts[i];
}
}
}
void run() {
list("");
}
}
Now let's transcribe to C, which has goto. Here it's easy to eliminate even prefix by adding a global string buffer.
#include <stdio.h>
char str[100];
int counts[] = { 1, 2, 3 };
int n_counts = 3;
int total_count = 6;
int len = 0;
void list(void) {
if (len == total_count) printf("%.*s\n", total_count, str);
for (int i = 0; i < n_counts; i++) {
if (counts[i] > 0) {
str[len] = 'a' + i;
--counts[i];
++len;
list();
--len;
++counts[i];
}
}
}
Now, the rules are:
Build a stack of records with one field for each local variable and parameter. Here we have only i left, so we don't even need records. A stack of ints will do.
Replace the recursive call site with
a push onto the stack, then
reset the parameters to their new values (here we don't have any), then
jump to the start of the function, and
immediately after the jump, put a label rtn:.
At the end of the function, add an epilog that checks whether the stack is empty. If not, it pops the stack and jumps to rtn:.
These rules essentially mimic the code the compiler will generate to handle recursive calls.
Putting it all together, we have:
int stk[100];
int p = 0; // stack pointer
void list(void) {
int i;
start:
if (len == total_count) printf("%.*s\n", total_count, str);
for (i = 0; i < n_counts; i++) {
if (counts[i] > 0) {
str[len] = 'a' + i;
--counts[i];
++len;
stk[p++] = i; // push i on stack
goto start;
rtn:
--len;
++counts[i];
}
}
// epilog
if (p > 0) {
i = stk[--p]; // restore i from stack
goto rtn;
}
}
If you follow the steps carefully, your code will run first try every time. The only additional tip is that when there is more than one recursive call site, you'll need one return label for each rtn1:, rtn2:, etc. and an extra int field in the stack that connotes the return site, with a switch statement in the epilog to jump to the correct one.
Of course this isn't pretty code. We'd like to get rid of the gotos. It turns out this is always possible by doing "algebra" to convert the gotos to loops. There are a couple of dozen transformation techniques...too many to describe here. It's a lot like simplifying an equation in math class. Sometimes it's necessary to add Boolean flags. In this case, though, we don't need to. I finished with this:
void list(void) {
for (int i = 0;;) {
while (i < n_counts && counts[i] == 0) i++;
if (i < n_counts) {
--counts[i];
str[len] = 'a' + i;
stk[p++] = i;
if (++len == total_count) printf("%.*s\n", total_count, str);
i = 0;
} else if (p > 0) {
i = stk[--p];
--len;
++counts[i++];
}
else break;
}
}
Just for fun, back to Java:
class CombinationLister {
private final int[] counts;
private final char[] str;
private final int[] stk;
private int p = 0;
private int len = 0;
CombinationLister(int[] counts) {
this.counts = counts.clone();
this.str = new char[Arrays.stream(counts).sum()];
this.stk = new int[str.length];
}
void run() {
for (int i = 0;;) {
while (i < counts.length && counts[i] == 0) i++;
if (i < counts.length) {
--counts[i];
str[len] = (char) ('a' + i);
stk[p++] = i;
if (++len == str.length) System.out.println(str);
i = 0;
} else if (p > 0) {
i = stk[--p];
--len;
++counts[i++];
} else break;
}
}
}
public static void combinatorial(ArrayList<Integer> remainingToFill, int totalLength) {
Stack st = new Stack();
st.push( new Pair<String,Integer>("", 0) );
while( !st.empty() ){
Pair<String,Integer> top = (Pair<String,Integer>) st.pop();
String prefix = top.getKey();
Integer i = top.getValue();
if (prefix.length() == totalLength) {
System.out.println(prefix);
int index= prefix.charAt(prefix.length()-1 )-'a' ;
remainingToFill.set( index , remainingToFill.get(index) + 1 );
}
else{
if( i== remainingToFill.size() ){
if( prefix.length()>0 ){
int index= prefix.charAt(prefix.length()-1 )-'a' ;
remainingToFill.set( index , remainingToFill.get(index) + 1 );
}
}
else{
st.push( new Pair<String,Integer>(prefix, i+1) );
if( remainingToFill.get(i) > 0 ){
remainingToFill.set(i, remainingToFill.get(i) - 1);
st.push( new Pair<String,Integer>(prefix+(char)('a'+i), 0) );
}
}
}
}
}

How to re-write or modify this code to work the same but without using a break statement

How can I get the following code work without using break statement?
I updated and added i = child to bottom of the while loop. I'm also adding these additional comments because someone edited my post and now I can't update it because I need to add more comments. Please don't alter my question. Those comments are there for extra insight. It also hinders my ability to edit my question or update my code.
private void percDown(int [] a, int i, int n) {
numOfCalls++;
int child = 0;
int tmp = a[i];
while(leftChild(i) < n) {
child = leftChild(i);
if( child != n - 1 && a[child] < a[child + 1]){
numOfComparisons++;
child++;
}
if( tmp < a[child]){
numOfComparisons++;
a[i] = a[child];
}
else
break;
i= child;
a[i] = tmp;
}
}
Just set n = 0; instead, or Integer.MIN_VALUE if these values can go negative. That will stop your loop. But don't be averse to break statements. They are used all the time out here in the real world.
Try this while condition:
while(leftChild(i) < n && (( leftChild(i) != n - 1 && a[leftChild(i)] < a[leftChild(i) + 1]) || tmp < a[leftChild(i)]))
Basically I have clubbed both your if conditions in the while condition. Everything else remains the same.
Your code is in structure like this:
while(A) {
B;
if(C){
D;
} else {
break;
}
E;
}
To tidy it up a bit; it can be written as
while(A) {
B;
if(C){
D;
E;
} else {
break;
}
}
To avoid using break, it can be done by:
while(A && !C) {
B;
if(C){
D;
E;
}
}
(You may make up a meaningful boolean flag to represent C so that it is more readable instead of putting a long, complex, hard-to-read predicate in while condition.)

How do I add logic to a sorted array delete algorithm to account for a "node not found" scenario?

I was assigned to write a delete algorithm for my sorted array structure. It continues to be a source of problems for my program because, in certain instances, it is completing the delete when it should be returning False for "node not found". So the delete function works, but it does it even when the node is not found. Where is the flaw in my logic?
public boolean delete(String targetListing)
{
int low = 0;
int high = next - 1;
int i = (low + high) / 2;
//check to see if target listing is the same as the current node key field
while(data[i].getName().compareToIgnoreCase(targetListing) != 0 && high != low)
{
if(data[i].getName().compareToIgnoreCase(targetListing) >= 1)
{
high = i - 1; //eliminate the bottom of the array
}
else
{
low = i + 1; //eliminate the top of the array
}
i = (low + high) / 2;
}
//this is my logic to determine if the node was found or not
//I also tried if(low == high) but sometimes that would be true at the
//at the position that the node was found
if(i == next || i < 0)
{
return false; //node not found
}
for(int j = i; j < next - 1; j++)
{
data[j] = data[j + 1];
}
next = next - 1;
data[next] = null;
return true;//node found and deleted
If anyone could also point me to a good example of a sorted array delete algorithm that accounts for a node not found scenario I would really appreciate it. I would have thought that would be a very easy thing to find, but I am having a hard time finding it.
Simplest answer: Replace your if(i == next || i < 0) with if(data[i].getName().compareToIgnoreCase(targetListing) != 0) -- in other words, check that you've actually found a match rather than simply having narrowed down to a single possibility.

Why isn't my if-else block ever getting hit, even though it should be? (Just need another pair of eyes.)

I am making a Falling Sand style game in Java, and I'm having weird issues with an if-else block that I have. In my doGravity() method, I have an various blocks of conditions that will cause different things to happen, and for some odd reason, one block is NEVER getting hit.
When I have this block count how many times each condition is hit, the left and right blocks are hit almost evenly:
else if(world[x][y+1]==EMPTY && (x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
int r = rand.nextInt(50);
if(r == 0) {
world[x-1][y+1] = world[x][y];
//System.out.println("GO: right");
countRight++;
}
else if(r == 1) {
world[x+1][y+1] = world[x][y];
//System.out.println("GO: left");
countLeft++;
}
else {
world[x][y+1] = world[x][y];
countCenter++;
}
world[x][y] = EMPTY;
}
Next comes this condition, which also equally distributes left and right.
else if((x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
if(rand.nextBoolean()) {
world[x-1][y+1] = world[x][y];
//countLeft++;
}
else {
world[x+1][y+1] = world[x][y];
//countRight++;
}
world[x][y] = EMPTY;
}
But when I count these blocks, the left block NEVER gets hit, even when the space to the left is open. I feel like its probably just some stupid typo that I can't see for some reason.
else if((x-1 >= 0) && world[x-1][y+1] == EMPTY) {
world[x-1][y+1] = world[x][y];
world[x][y] = EMPTY;
countLeft++;
System.out.println("Hit Left");
}
else if((x+1 < world.length) && world[x+1][y+1] == EMPTY) {
world[x+1][y+1] = world[x][y];
world[x][y] = EMPTY;
countRight++;
System.out.println("Hit Right");
}
UPDATE: If I remark out the left block at the end, absolutely nothing changes. The sand acts exactly the same. If I remark out the right block at the end, it acts the same as if I remark out both blocks. I cannot figure this out. It should work... but it doesn't.
UPDATE: Here's the full source code. I have no idea what this could possibly be. It will, in fact, drive me insane. http://pastebin.com/mXCbCvmb
Your pastebin code does show "Hit left", you just need to change the creation of world (line 65 pastebin) to
world = new Color[worldWidth][worldHeight+1];
Because of the y+1 part i would suppose. Other than that it grows both to the left and to the right.
EDIT: http://pastebin.com/GVmSzN4z I twiddled a little with your doGravity to make the drops a little more symmetric.
I dont see anything strange in the posted code... however the "else" at the beginning of the second block makes me think that probably the above condition is being executed in cases that insted you would like to be handled by the "left" case.
What is the condition in the if before that part?
EDIT
After checking your full source code I finally found where the problem is. Your doGravity update function always goes left->right and this introduces the asymmetry. By changing it so that the update direction is alternating between left->right and right->left for odd/even scanlines the asymmetry disappears.
private void doGravity() {
for(int i = worldHeight - 1; i >= 0; i--) {
if (i % 2 == 0)
{
for(int j = 0; j < worldWidth; j++) {
if(world[j][i] != EMPTY) {
if(hasGravity(world[j][i])) {
dropParticle(j, i);
}
}
}
}
else
{
for(int j = worldWidth-1; j >= 0; --j) {
if(world[j][i] != EMPTY) {
if(hasGravity(world[j][i])) {
dropParticle(j, i);
}
}
}
}
}
}
I downloaded your code from paste bin the first thing I did was extract this method and use it instead of all the embedded array cell checking so I could set a break point and see what the values for x and y and what the contents of that indexed cell was.
private boolean isEmpty(final int x, final int y)
{
return world[x][y] == EMPTY;
}
I would extract all the EMPTY checks to something more readable, such as isLeftEmpty(x,y) and isRightEmpty(x,y) and isNextLeftEmpty(x,y) it will help you reason about the correctness of your logic in your code.
I would also extract the (x + 1 < world.length) to isNextXOutsideWorld(x), this will help document your intentions and help with reasoning about the logic you intend as well.
This also has a side effect of simplifying the logic in the if/elseif/else statements.
I did some brief debugging and I let it run for a few minutes and came to the conclusion that the following line matches always and supersedes the next else if statement.
else if ((x + 1 < world.length) && isEmpty(x + 1, y + 1) &&
(x - 1 >= 0) && isEmpty(x - 1,y + 1))
is always true when I run it, so it never reaches the next statement
else if ((x - 1 >= 0) && isEmpty(x - 1,y + 1))
I would try and break each of the else/if statements out to method calls with descriptive names and just all them all in order using a Strategy pattern since they are all mutually exclusive. That large of a method is definitely a code smell, compounded with all those else/if blocks, the stinky factor is high.
It is very hard to extrapolate what your intended behavior is from all the noise in the if/elseif/else blocks.

When there is two for() loop, the second one doesn't work

Here are my for() loops :
public void showMovementCase(){
int movePlusAttack = moveAllowed+attackDistance;
int twiceMoveAllowed = (moveAllowed)*2;
for(int i = 0; i <= movePlusAttack*2; i++){
for(int j = 0; j <= movePlusAttack*2;j++){
boolean a = movePlusAttack <= j+i && movePlusAttack >= j-i && i <= movePlusAttack;
boolean b = movePlusAttack <= j+i && movePlusAttack >= i-j && i > movePlusAttack && j <= movePlusAttack;
boolean c = movePlusAttack*3 >= j+i && movePlusAttack >= j-i && i > movePlusAttack && j >= movePlusAttack;
if(a || b || c){
try{
actionSquare[i][j] = new JLabel();
actionSquare[i][j].setIcon(redsquare);
actionSquare[i][j].setBounds(sprite.getX()+(i-movePlusAttack)*16,sprite.getY()+(j-movePlusAttack)*16, 16, 16);
panel.add(actionSquare[i][j], new Integer(1));
}
catch(ArrayIndexOutOfBoundsException e){System.out.println("red :" + e);}
}
}
}
for(int x = 0; x <= twiceMoveAllowed; x++){
for(int y = 0; y <= twiceMoveAllowed;y++){
boolean a = moveAllowed <= y+x && moveAllowed >= y-x && x <= moveAllowed;
boolean b = moveAllowed <= y+x && moveAllowed >= x-y && x > moveAllowed && y <= moveAllowed;
boolean c = moveAllowed*3 >= y+x && moveAllowed >= y-x && x > moveAllowed && y >= moveAllowed;
if(a || b || c){
try{
actionSquare[x][y].setIcon(bluesquare);
System.out.println("Coucou !");
actionSquare[x][y].addMouseListener(mouse);
panel.repaint();
panel.revalidate();
}
catch(ArrayIndexOutOfBoundsException e){System.out.println("blue :" + e); }
}
}
}
}
if this.attackDistance is different of 0, then the second loop doesn't work (it seems to stop at the .setIcon() command).
Do you know a way to fix this ?
Thanks for reading.
Edit:
with :
try{
actionSquare[x][y].setIcon(bluesquare);
System.out.println("Coucou !");
[...]
}
On the second loop, nothing is printed.
but with :
try{
System.out.println("Coucou !");
actionSquare[x][y].setIcon(bluesquare);
[...]
}
"Coucou !" is printed once.
That's why I said that "it seems to stop at the .setIcon() command" I should have said that sooner, sorry.
Here are a few tips:
don't catch exceptions and do nothing with them. That's what you are doing here in both loops, and so it's normal you don't see the error message.
anytime you see long statements like you have, it should be a hint that you could refactor it. For example, create a separate method that validates whether or not you're going to do something in your loop, and then inside the main method you'd call it like if(shouldPerformAction())
consider using less than 8 spaces for indentation. This just eats up your screen real estate.
consider making computations before the loops instead of inside the loop conditions, if the computation is supposed to be fixed (for example this.moveAllowed*2)
imho, no point in prefixing all your methods/fields with this, it just clutters everything. Just call the methods directly.
This is a very, very bad idea:
catch(ArrayIndexOutOfBoundsException e){}
You effectively tell the JVM to ignore any problems with your arrays that it detects. And worse than that: you don't even print anything when that happens.
Put at least a e.printStackTrace() in there to see if a problem occurs and where.
And as a further step: fix your array access to not exceed any limits. Catching an ArrayIndexOutOfBoundsException is a terribly bad idea. Avoid having it thrown at all!
Hmmm... where to begin...
I would first suggest putting something (System.err.println(...)?) inside of your catch blocks. Or just commenting them out entirely so you'd see the full stacktrace. What if you're hitting an exception and just not seeing it?
catch(ArrayIndexOutOfBoundsException e){}
This is a bad practice for two reasons:
You should never catch RuntimeException. It is just a very helpful indicator for errors in code logic (i.e. developer errors) which ought be solved by writing good code.
You should never ignore e unless you know perfectly what you're doing. Add at least an e.printStackTrace() so that you at least know that something failed.
I cleaned up your code for you. Generally, when you have two sections of code that are supposed to be doing the exact same thing, but are not, then rolling them into one method can eliminate that possibility.public void showMovementCase(){
// probably want to remove anything left over from the last invocation
panel.removeAll();
for (JLabel[] array : actionSquare) Arrays.fill(array, null);
colorSquares(moveAllowed + attackDistance, redsquare, null);
colorSquares(moveAllowed * 2, bluesquare, mouse);
for (int x = 0; x < actionSquare.length; x++)
for (int y = 0; y < actionSquare[x].length; y++)
if (actionSquare[x][y] != null) panel.add(actionSquare[x][y], 1);
}
private void colorSquares(int move, Icon color, MouseListener mouse) {
int xMax = Math.min(2 * move, actionSquare.length);
int yMax = Math.min(2 * move, actionSquare[0].length);
for (int x = 0; x < xMax; x++) {
for (int y = 0; y < yMax; y++) {
if (isLegal(x, y, move)) {
if (actionSquare[x][y] == null)
actionSquare[x][y] = new JLabel();
actionSquare[x][y].setIcon(color);
actionSquare[x][y].setBounds(
sprite.getX() + (x - move) * 16,
sprite.getY() + (y - move) * 16, 16, 16 );
if (mouse != null) actionSquare[x][y].addMouseListener(mouse);
}
}
}
}
private static boolean isLegal(int x, int y, int move) {
// informative comment explaining why this mess makes sense
if (move <= y+x && move >= y-x && x <= move) return true;
// informative comment explaining why this mess makes sense
if (move <= y+x && move >= x-y && x > move && y <= move) return true;
// informative comment explaining why this mess makes sense
if (move * 3 >= y+x && move >= y-x && x > move && y >= move) return true;
return false;
}

Categories

Resources