1

I have a class Card which contains value (int), suit (String) and faceValue (String). It seems like a regular insertion sort on Card.value should work fine. I just use the whole object when moving things around. For some reason, this crashes and burns. It ends up duplicating the highest card into every element except for a random element that I can't understand.

value, suit, and faceValue are pulic, also.

This is my code:

public static void insertionSort(ArrayList<Card> Array) {

    int i,j;
    Card key = new Card(0, "","");

    for (i = 1; i < Array.size(); i++) {
        key.value = Array.get(i).value;
        key.suit = Array.get(i).suit;
        key.faceValue = Array.get(i).faceValue;
        j = i;
        while((j > 0) && (Array.get(j - 1).value > key.value)) {
            Array.set(j,Array.get(j - 1));
            j--;
        }
        Array.set(j,key);
    }


}

I checked this against Wikipedia's pseudo code, and I can't find any fundamental difference. I've been through the debugger a dozen times, and I can't see any reason for the compiler to do what it's doing. Does anyone have an idea why it's not working?

Thanks.

12
  • 1
    Is using the language features an option? Having Card implement Comparable and using Collections.sort Commented May 6, 2014 at 20:11
  • @oschlueter I think that he uses this algorithm for practice. Commented May 6, 2014 at 21:01
  • Array.set(j,key); is probably not what you want to do. Commented May 6, 2014 at 21:02
  • also, Array.set(j,Array.get(j - 1)); does not swap Commented May 6, 2014 at 21:03
  • you probably want to remove and insert. Commented May 6, 2014 at 21:04

5 Answers 5

4

I would like to extend ginz's answer.

Java objects are passed by reference. So you are changing one object and setting it to multiple indexes.

To visualize (before and after):

visual representation

For after: Please note that not all indexes must reference to same object. Some of them could remain unchanged.


Better approach would be to move objects, instead of trying to duplicate them.

Also, by Java standard, name of properties (variables) should always start with small letter.

Here is working code:

public static void insertionSort(ArrayList<Card> array) {
    int i, j;
    for (i = 1; i < array.size(); i++) {
        Card tmp = array.get(i);
        j = i;
        while ((j > 0) && (array.get(j - 1).value > tmp.value)) {
            array.set(j, array.get(j - 1));
            j--;
        }
        array.set(j, tmp);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, normally I'm pretty good with the lowercase names, I'm not sure why I differed this time. Thanks for pointing that out. =)
3

At every cycle, you insert the object "key" into the list (Array.set(j,key);). So, at the end your whole list will be made of references to the object "key". So when you set key.value, key.suit and key.faceValue at the end, you are setting the fields of every element of your list, because your list consists of references of the same object.

move Card key = new Card(0, "",""); inside the for loop. Like this:

public static void insertionSort(ArrayList<Card> Array) {

    int i, j;

    for (i = 1; i < Array.size(); i++) {
        Card key = new Card(0, "","");
        key.value = Array.get(i).value;
        key.suit = Array.get(i).suit;
        key.faceValue = Array.get(i).faceValue;
        j = i;
        while((j > 0) && (Array.get(j - 1).value > key.value)) {
            Array.set(j,Array.get(j - 1));
            j--;
        }
        Array.set(j,key);
    }


}

gl with your studies :)

4 Comments

again, set is not insert.
Thanks! Wow, I never thought of that, but it actually makes sense. I really appreciate that! Thanks for the well wishes. =)
Keep in mind, that this code makes unnecessary object duplicates.
also this does not scale. How does it work if you have tens of properties in your object? not to mention that you destroy the initial objects and replace then by new ones. good way to break things elsewhere in your code.
3

You're setting all the fields of Array(OMG, please rename it!) with the same element: key. So, all the elements would be the same.

1 Comment

Piling on the "rename it, for the sake of all that is holy!" bandwagon along with you...
2

The basic algorithm is

  • for each element
  • search for the first smaller element going downward
  • insert element right after that

So, in your case:

public static void insertionSort(ArrayList<Card> cards) {

    for (int i = 1; i < cards.size(); i++) {
        int value = cards.get(i).value;
        for (int j = i-1; j >= 0; j--) {
            if (cards.get(j).value <= key.value) {
                break;
            }
        }
        cards.add(j,cards.remove(i));
    }
}

One important point here is that at no point does the array contains duplicated values (which happens when you use set)

4 Comments

make sure that it should be int j = 1 not j=i
@SnappyRiffs cards from 0 to i are sorted, since they have been inserted in order
you did not set j to an integer. The compiler will not work unless you set j to int
that's weird... thanks
0

Use Iterator for getting the elements.

public static void insertionSort(ArrayList<Integer> arrL) {
    Iterator<Integer> it = arrL.iterator();

    while(it.hasNext()){
        int new_element = it.next();

        int j = arrL.indexOf(new_element);
        while(j>0 && arrL.get(j-1)>new_element){
            arrL.set(j, arrL.get(j-1));
            j--;
        }

        arrL.set(j, new_element);
    }
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.