Splitting Arrays- is my implementation correct? - java

I'm writing code for a hybrid data structure for school, and am debugging the code. Basically, this structure is a combination of a Double Linked List and an Array, where each list node contains an array of set size. Since this is an ordered structure, a provision has to be made to identify and split full arrays into equally into two nodes.
This is my code for splitting a node into two and then copying the latter half of the parent node's array values to the child node.
public Chunk<E> split(Chunk<E> node) {
Chunk<E> newChunk= new Chunk<E>();
newChunk.index= node.index++;
//connect to previous node
node.next= newChunk.next;
newChunk.prev= node.prev;
//connect to next node
newChunk.next= node.next.next;
node.next.prev= newChunk.prev;
//adds the latter half of the array contents to the new node
//and erases the same contents from the old node
for (int i=chunkSize/2; i<node.numUsed; i++) {
newChunk.items[i-chunkSize/2]= node.items[i];
node.items[i]=null;
}
//update capacity counter for both chunks
node.numUsed=chunkSize/2;
newChunk.numUsed= chunkSize/2;
return newChunk;
}
The toArray() method is returning null values from the list, so I think something is going on with this split method.
Questions I have are:
Are the linking of the new node to the rest of the list correct?
Is the the nulling of values inside the loop responsible for the null printout?

To answer this question thoroughly you should write some unit tests. For example:
package so3898131;
import static org.junit.Assert.*;
import org.junit.Test;
public class ChunkTest {
/** Ensure that the simplest possible case works as expected. */
#Test
public void testEmptySplit() {
Chunk<Object> old = new Chunk<Object>();
Chunk<Object> split = old.split(old);
assertEquals(0, split.chunkSize);
assertEquals(0, split.items.length);
assertEquals(0, split.index);
assertEquals(1, old.index);
}
#Test
public void testSplitWithOneItem() {
// TODO: make sure that after splitting one of the chunks contains
// one element, the other none.
}
#Test
public void testSplitWithTwoItems() {
// TODO: make sure that after splitting a chunk with two elements
// each of the new chunks contains exactly one of the elements.
// Use assertSame(..., ...) to check it.
}
}
This throws NullPointerExceptions at me because node.next may be null, in which case you cannot access node.next.next. This probably means that your code does not work. At least it does not work as I expect it.
Update: Your code is not correct. I wrote a unit test like this:
#Test
public void testSplitLinkage() {
Chunk<Object> old = new Chunk<Object>();
assertNull(old.prev);
assertNull(old.next);
Chunk<Object> split = old.split(old);
assertNull(old.prev);
assertSame(split, old.next);
assertSame(old, split.prev);
assertNull(split.next);
}
And then I modified the code so that this test runs successfully. I had to replace some lines with:
// connect to previous and next node
Chunk<E> one = node, two = newChunk, three = node.next;
one.next = two;
two.prev = one;
two.next = three;
if (three != null)
three.prev = two;

A better question would be: "How can I isolate (track down) the location of a bug in the source code by debugging?"
First you'll want to have a way to reproduce the problem. It appears you already have that. In a non-trivial code base, you will then want to do a binary search for the problem. Having two points A and B in program execution, where the program is in valid state in A, but not in B, choose a point C between A and B and check whether everything is correct at C. If it is, the bug is between C and B, else between A and C. Recurse until you have it narrowed down into a very small part of the code, where it is usually quite obvious.
This leaves the question of how verify whether execution was correct so far. There are various ways to do that, but it is probably most instructive to execute the program in a debugger, use a break point to suspend execution, and check that the variables contain the expected values.

Related

different sort outcome(SortedSet) in debug mode vs normal run

so i wrote a comparator to sort out objects of the type Polynom (polynomials but in my lang basically). when i iterate slowly over it with a debugger i seem to get the result im expecting. yet when i run it, one of them craps out and returns the wrong value in the comparison which should be very straight forward.
the Polynom object is as follows:
public class Polynom<E> implements IPolynom<E> , Comparable<Polynom<E>>{
private SortedMap<Integer, FieldMember<E>> coefficients = new TreeMap<>();
while IPolynom is just an interface to define the methods
E can be either a complex number (which i also wrote and includes its methods and two fields real and image but its irrelevant to the error)
public int compareTo(Polynom<E> o) {
Polynom<E> p1 = new Polynom<>(this);
Polynom<E> p2 = new Polynom<>(o);
int deg,co;
while(!p1.coefficients.isEmpty() && !p2.coefficients.isEmpty())
{
deg = p1.degree() - p2.degree();
if(deg != 0)
return deg;
co = p1.getCoefficient(p1.degree()).compareTo(p2.getCoefficient(p2.degree()));
if(co != 0)
return co;
p1.coefficients.remove(p1.degree());
p2.coefficients.remove(p2.degree());
}
return (p1.degree() - p2.degree());
}
this is the compareTo method that i wrote
and the method degree() simply returns the degree of x in this scenario
the coefficient part is never reached in this example so ill skip over it
the objects being compared are as follows:
p1 = Polynom: (1.00+0.00i)x^5
p2 = Polynom: (-1.00-5.00i)x^7
the comparison should be straight forward and indicate that p2 is greater than p1
however when i run the opposite is returned
when i debug (and specifically iterate over the lines as they happen) the method returns the correct result. if i skip over it even in debug it still returns the wrong result
in my main method im adding a bunch of Polynom type objects to a SortedSet and the ordering turns out to be wrong only on a single object (the one being p1 in this case which should be the "smallest" of them and go first up in the sorted set)
im really at loss here...
please tell me if theres any other details that i need to add that would make the situation clearer as this is a fairly large project
p.s. all of this is done in eclipse (without any extensions)
My mistake was making .toString() change the state of the object so the debugger didn't tell the whole story.
Thanks a lot guys!

How do I recursively append two linked lists in Java? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
So basically my code iterates through the list and the original method is supposed to return the linked list however it doesn't seem to be adding the nodes that I link in the recursive method and I'm confused as to why. Can anyone help me?
// Append MyStringBuilder2 b to the end of the current MyStringBuilder2, and
// return the current MyStringBuilder2. Be careful for special cases!
public MyStringBuilder2 append(MyStringBuilder2 b)
{
//Test if Invalid
if(b.firstC==null){
return this;
}
//Test if condition is met
else {
CNode lastNode =firstC;
recurseAppendBuild(lastNode, b);
return this;
}
}
private void recurseAppendBuild(CNode lastNode, MyStringBuilder2 BPoint) {
//Test if all nodes have been added
if(lastNode.next==null&&BPoint.firstC==null) {
System.out.println("finished");
}
//Tests if all nodes in the original linked list have been passed through
else if(lastNode.next==null) {
lastNode.next= new CNode(BPoint.firstC.data);
BPoint.firstC=BPoint.firstC.next;
recurseAppendBuild(lastNode.next, BPoint);
}
//Recurse until condition is met
else {
recurseAppendBuild(lastNode.next, BPoint);
}
}
```
Okay, your code needs some work. Let's look at your first method. I'm going to rewrite it.
public MyStringBuilder2 append(MyStringBuilder2 fromBuilder)
{
if (fromBuilder.firstC != null) {
recurseAppendBuild(fromBuilder.firstC);
}
return this;
}
I changed a number of things.
I used a more meaningful name on the argument. It's a good idea to give your variables meaningful names, not just 'b'. Note that I never use one-character names. If nothing else, it can be really hard to search on that. If you do "int i" and then search for i, you'll get a LOT of hits that aren't i at all.
This is a very trivial thing and doesn't affect the quality of your code.
In all cases, you always return yourself, so the return statement can be after the if-else structure, which is easier to see that it's the same.
That eliminates the top if-block entirely, so I reversed the logic.
And I changed the method signature of your recursive method, for reasons I'll describe below.
The end result is short and sweet and easily understood.
Now, let's look at your second method:
private void recurseAppendBuild(CNode lastNode, MyStringBuilder2 BPoint) {
//Test if all nodes have been added
if(lastNode.next==null&&BPoint.firstC==null) {
System.out.println("finished");
}
//Tests if all nodes in the original linked list have been passed through
else if(lastNode.next==null) {
lastNode.next= new CNode(BPoint.firstC.data);
BPoint.firstC=BPoint.firstC.next;
recurseAppendBuild(lastNode.next, BPoint);
}
//Recurse until condition is met
else {
recurseAppendBuild(lastNode.next, BPoint);
}
}
Your variable named BPoint breaks JAVA naming standards. It should start with a lower case letter.
If you pass in a MyStringBuilder2 as the second argument, then as you move things from BPoint to the end of your list and recurse, you have to remove them from BPoint, which is a pain in the ass. So instead, I didn't point to the wrapper. In my code above, I passed in the head of the list (fromBuilder.firstC).
You are finished when your list-to-append-from (BPoint) is empty, not when lastNode is null. Your first if is flawed.
You aren't recursively adding items. You're recursively looking for the end of the list. I don't think that's what you really want.
You're messing up the integrity of BPoint. You're making a copy of the nodes as you add them, but you're then dropping the old ones from BPoint but NOT maintaining lastC at all.
And you have a significant problem if your list starts as empty, as firstC and lastNode will both be empty.
So let's think about it this way. First, doing this recursively is silly, but that's the assignment, so we'll work with it.
A recursive definition is:
AppendedList = OriginalList + firstItem + Append Tail of List.
private void recurseAppendBuild(CNode headToAppend) {
if (headToAppend == NULL) {
// All done.
return;
}
CNode nodeToAppend = new CNode(headToAppend.data);
if (lastC == nullptr) {
// Original list is empty.
firstC = lastC = nodeToAppend;
else {
lastC.next = nodeToAppend;
lastC = nodeToAppend; // Point the tail at the new tail
}
// And here you recurse, always.
recurseAppendBuild(headToAppend.next);
}
Let's look at this.
I'm assuming you keep both a firstC and lastC in your builder. It would be deeply inefficient otherwise. So you only need to pass in the chain of nodes, not the surrounding wrapper.
By putting a null-check at the top of this method, you eliminate other null checks. Note -- this means we can eliminate the null check in the first method.
Create the new copy right away. That part's easy, right?
If lastC is null, you have an empty list, so you just point both front and back of the list to your new node.
Otherwise you point the old tail's next pointer to your new node and update the tail pointer to remain pointed at the tail.
Either way, you can safely recurse with the next object in the original list.
Advantages of this method, aside from working, is that you don't destroy the original list, and it's pretty clear to read.

How to implement Union-Find using linked lists?

I need to write a piece of code using the Kruskal algorithm, which in turn needs the Union-Find algorithm.
This includes the methods Make-Set(x), Find-Set(x) and Union(x, y).
I need to implement them using linked lists, but I am not sure of how to start with the Make-Set method.
The Make-Set Method should create a set and make the first element into a key (to compare sets). How exactly would I declare a key using linked lists?
Shortly put: How do I implement this pseudo code for linked lists in Java?
Make-Set(x)
x.p = x
x.rank = 0
Thanks for your help in advance!
I've heard this referred to in the past not as "Union-Find" but as a disjoint set. It isn't exactly a linked list, since the nodes do have a link, but they aren't necessarily linked up in a linear fashion. It's more like a tree where each node has a pointer to its parent and you can walk up the tree to the root.
I don't have much time right now, but here's a quick sketch of how I would implement it in Java:
class Disjoint {
Disjoint next;
Disjoint findSet() {
Disjoint head = this;
if (next != null) {
head = next.findSet();
next = head;
}
return head;
}
void union(Disjoint other) {
Disjoint us = this.findSet();
Disjoint them = other.findSet();
us.next = them;
}
}
Creating an instance is your Make-Set. What you call Find-Set I would call find head or find leader, maybe find identity. I've called it findSet here, though. It walks the chain to find the root of the tree. It also performs an optional operation; it snaps all the links on the way back out of the recursive call so that they all point directly at the root. This is an optimization to keep the chains short.
Finally, Union is implemented just by assigning one root's next pointer to point at the other set. I'm not sure what you intended with rank; if it's the size of the set, you can add a field for that and simply sum them when you union two sets. But you initialize it to 0 for a new set when I would expect it to be initialized to 1.
Two nodes a and b belong to the same set if a.findSet() == b.findSet(). If you need the nodes to carry some data, make the class generic and provide the data to the constructor, and add a getter:
class Disjoint<T> {
Disjoint<T> next;
T data;
public Disjoint(final T data) {
this.data = data;
}
public T getData() {
return data;
}
// rest of class identical except Disjoint replaced with Disjoint<T> everywhere
}

I can't get to modify my static variable in java

You give a grid (4x4 here). you need to find out the total no of unique paths from (0,0) to (4,4). main() call a function pathify for this. It finds the possible "next steps" and calls it again. When (4,4) is reached noOfPaths++; is supposed to execute. This doesn't happen and I can't find the problem.
import java.util.ArrayList;
public class NoOfPaths {
static int xRows = 4;
static int yColumns = 4;
static int noOfPaths = 0;
/*A robot is located in the upper-left corner of a 4×4 grid.
* The robot can move either up, down, left, or right,
* but cannot go to the same location twice.
* The robot is trying to reach the lower-right corner of the grid.
* Your task is to find out the number of unique ways to reach the destination.
**/
static ArrayList validNeighbours (int x,int y, ArrayList visited) {
ArrayList valid = new ArrayList();
if((x+1 <= xRows) && !visited.contains(((x+1)*10)+y) ) {
valid.add(((x+1)*10)+y);
}
if((x-1 >= 0) && !visited.contains(((x-1)*10)+y) ) {
valid.add(((x-1)*10)+y);
}
if((y+1 <= yColumns) && !visited.contains(x*10+y+1) ) {
valid.add(x*10+y+1);
}
if((y-1 >= 0) && !visited.contains(x*10+y-1) ) {
valid.add(x*10+y-1);
}
return valid;
}
static void pathify(int x,int y, ArrayList alreadyVisited) {
if(x == xRows && y == yColumns) {
noOfPaths++;
} else {
alreadyVisited.add(x*10+y);
ArrayList callAgain = new ArrayList();
callAgain = validNeighbours(x,y,alreadyVisited);
for (int t=0,temp; t<callAgain.size(); t++) {
temp=(int) callAgain.get(t);
pathify(temp/10, temp%10, alreadyVisited);
}
}
}
public static void main(String[] args) {
ArrayList alreadyVisited = new ArrayList();
pathify(0, 0, alreadyVisited);
System.out.println(noOfPaths);
}
}
The error is in how you're handling alreadyVisited. The first time pathify is called, this list will contain only the initial square (0,0), which is fine. Here's the important part of your code:
for (int t=0,temp; t<callAgain.size(); t++) {
temp=(int) callAgain.get(t);
pathify(temp/10, temp%10, alreadyVisited);
}
You've found the neighbors of the initial cell. Your code will pick the first neighbor; then it will find paths starting with that neighbor, and the recursive calls to pathify will add cells to alreadyVisited.
Now, after all the recursive calls come back, you're ready to find cells starting with the second neighbor of the initial cell. But you have a problem: alreadyVisited still has all the cells it's collected from the paths it found starting with the second neighbor. So you won't find all possible paths starting with the second neighbor; you won't find any path that includes any cell in any path you've previously found. This isn't what you want, since you only want to avoid visiting the same cell in each path--you don't want to avoid visiting the same cell in all your previous paths. (I simplified this a little bit. In reality, the problem will start occurring deeper down the recursive stack, and you won't even find all the paths beginning with the first neighbor.)
When implementing a recursive algorithm, I've found that it's generally a bad idea to keep an intermediate data structure that is shared by recursive invocations that will be modified by those invocations. In this case, that's the list alreadyVisited. The problem is that when an invocation deeper down the stack modifies the structure, this affects invocations further up, because they will see the modifications after the deeper invocations return, which is basically data they need changing underneath them. (I'm not talking about a collection that is used to hold a list of results, if the list is basically write-only.) The way to avoid it here is that instead of adding to alreadyVisited, you could create a clone of this list and then add to it. That way, a deeper invocation can be sure that it's not impacting the shallower invocations by changing their data. That is, instead of
alreadyVisited.add(x*10+y);
write
alreadyVisited = [make a copy of alreadyVisited];
alreadyVisited.add(x*10+y);
The add will modify a new list, not the list that other invocations are using. (Personally, I'd declare a new variable such as newAlreadyVisited, since I don't really like modifying parameters, for readability reasons.)
This may seem inefficient. It will definitely use more memory (although the memory should be garbage-collectible pretty quickly). But trying to share a data structure between recursive invocations is very, very difficult to do correctly. It can be done if you're very careful about cleaning up the changes and restoring the structure to what it was when the method began. That might be necessary if the structure is something like a large tree, making it unfeasible to copy for every invocation. But it can take a lot of skill to make things work.
EDIT: I tested it and it appears to work: 12 if xRows=yColumns=2, 8512 if both are 4 (is that correct?). Another approach: instead of copying the list, I tried
alreadyVisited.remove((Object)(x*10+y));
at the end of the method ((Object) is needed so that Java doesn't think you're removing at an index) and that gave me the same results. If you do that, you'll make sure that alreadyVisited is the same when pathify returns as it was when it started. But I want to emphasize that I don't recommend this "cleanup" approach unless you really know what you're doing.

Efficient search in datastructure ArrayList

I've an ArrayList which contains my nodes. A node has a source, target and costs. Now I have to iterate over the whole ArrayList. That lasts for for over 1000 nodes a while. Therefore I tried to sort my List by source. But to find the corresponding pair in the List I tried the binary search. Unfortunately that works only if I want to compare either source or target. But I have to compare both to get the right pair. Is there another possibility to search an ArrayList efficient?
Unfortunately, no. ArrayLists are not made to be efficiently searched. They are used to store data and not search it. If you want to merely know if an item is contained, I would suggest you use HashSet as the lookup will have a time complexitiy of O(1) instead of O(n) for the ArrayList (assuming that you have implemented a functioning equals method for your objects).
If you want to do fast searches for objects, I recommend using an implementation of Dictionnary like HashMap. If you can afford the space requirement, you can have multiple maps, each with different keys to have a fast lookup of your object no matter what key you have to search for. Keep in mind that the lookup also requires implementing a correct equals method. Unfortunately, this requires that each key be unique which may not be a brilliant idea in your case.
However, you can use a HashMapto store, for each source, a List of nodes that have the keyed source as a source. You can do the same for cost and target. That way you can reduce the number of nodes you need to iterate over substantially. This should prove to be a good solution with a scarcely connected network.
private HashMap<Source, ArrayList<Node>> sourceMap = new HashMap<Source, ArrayList<Node>>();
private HashMap<Target, ArrayList<Node>> targetMap = new HashMap<Target, ArrayList<Node>>();
private HashMap<Cost, ArrayList<Node>> costMap = new HashMap<Cost, ArrayList<Node>>();
/** Look for a node with a given source */
for( Node node : sourceMap.get(keySource) )
{
/** Test the node for equality with a given node. Equals method below */
if(node.equals(nodeYouAreLookingFor) { return node; }
}
In order to be sure that your code will work, be sure to overwrite the equals method. I know I have said so already but this is a very common mistake.
#Override
public boolean equals(Object object)
{
if(object instanceof Node)
{
Node node = (Node) object;
if(source.equals(node.getSource() && target.equals(node.getTarget()))
{
return true;
}
} else {
return false;
}
}
If you don't, the test will simply compare references which may or may not be equal depending on how you handle your objects.
Edit: Just read what you base your equality upon. The equals method should be implemented in your node class. However, for it to work, you need to implement and override the equals method for the source and target too. That is, if they are objects. Be watchful though, if they are Nodes too, this may result in quite some tests spanning all of the network.
Update: Added code to reflect the purpose of the code in the comments.
ArrayList<Node> matchingNodes = sourceMap.get(desiredSourde).retainAll(targetMap.get(desiredTarget));
Now you have a list of all nodes that match the source and target criteria. Provided that you are willing to sacrifice a bit of memory, the lookup above will have a complexity of O(|sourceMap| * (|sourceMap|+|targetMap|)) [1]. While this is superior to just a linear lookup of all nodes, O(|allNodeList|), if your network is big enough, which with 1000 nodes I think it is, you could benefit much. If your network follows a naturally occurring network, then, as Albert-László Barabási has shown, it is likely scale-free. This means that splitting your network into lists of at least source and target will likely (I have no proof for this) result in a scale-free size distribution of these lists. Therefore, I believe the complexity of looking up source and target will be substantially reduced as |sourceMap| and |targetMap| should be substantially lower than |allNodeList|.
You'll need to combine the source and target into a single comparator, e.g.
compare(T o1, T o2) {
if(o1.source < o2.source) { return -1; }
else if(o1.source > o2.source) { return 1; }
// else o1.source == o2.source
else if(o1.target < o2.target) { return -1; }
else if(o1.target > o2.target) { return 1; }
else return 0;
}
You can use the .compareTo() method to compares your nodes.
You can create two ArrayLists. The first sorted by source, the second sorted by target.
Then you can search by source or target using binarySearch on the corresponding List.
You can make a helper class to store source-target pairs:
class SourceTarget {
public final Source source; // public fields are OK when they're final and immutable.
public final Target target; // you can use getters but I'm lazy
// (don't give this object setters. Map keys should ideally be immutable)
public SourceTarget( Source s, Target t ){
source = s;
target = t;
}
#Override
public boolean equals( Object other ){
// Implement in the obvious way (only equal when both source and target are equal
}
#Override
public int hashCode(){
// Implement consistently with equals
}
}
Then store your things in a HashMap<SourceTarget, List<Node>>, with each source-target pair mapped to the list of nodes that have exactly that source-target pair.
To retrieve just use
List<Node> results = map.get( new SourceTarget( node.source, node.target ) );
Alternatively to making a helper class, you can use the comparator in Zim-Zam's answer and a TreeMap<Node,List<Node>> with a representative Node object acting as the SourceTarget pair.

Categories