-1

Still newish to Java; our professor wants us to use a non-recursive binary search AT THE TIME OF ADDING elements to this ArrayList. I keep getting outofbounds exceptions, and I just can not find out why. I also notice unusual behavior while debugging and going step by step. For the life of me, I just can't seem to logically figure this out. He also wants us to use the compare method for this as well. My issue is figuring out why/how this keeps getting array out of bounds. Any pointers and advice will be greatly appreciated.....our professor is older and takes DAYS to get back via email, and I don't have that long to figure this problem out. This is the only thing holding me back for the rest of the assignment.

    public void enqueue(E item) {
    if(arr.size() == 0) {
        arr.add(item);
    }else {
        int low = 0;
        int high = (arr.size());
        while (low <= high){
            int mid = (low + high)>>1;
            if(arrComp.compare(arr.get(mid), item) < 0){
                low = (mid + 1);
            }
            else if (arrComp.compare(arr.get(mid), item) > 0){
                high = (mid - 1);
            }
            else{
                arr.add(mid,item);
            }
        }
    }
}   

***Edit When I do this:

int low = 0;
int high = (arr.size() - 1);
while (low <= high){
    int mid = (low + high) / 2;
    if(arrComp.compare(arr.get(mid), item) < 0){
        low = (mid + 1);
    }
    else if (arrComp.compare(arr.get(mid), item) > 0){
        high = (mid - 1);
    }
    else{
        arr.add(mid,item);
    }
}

}

Or this:

            if(arr.size() == 0){
                     arr.add(item)
}
            int low = 0;
            int high = (arr.size() - 1);
            while (low <= high){
                int mid = (low + high) / 2;
                if(arrComp.compare(arr.get(mid), item) < 0){
                    low = (mid + 1);
                }
                else if (arrComp.compare(arr.get(mid), item) > 0){
                    high = (mid - 1);
                }
                else{
                    arr.add(mid,item);
                }
            }

    }

Both get the method to run, neither actually fills the arraylist. I don't understand why this is not working, logically it should be filling the array should it not? It ran this time without error, but essentially did nothing. Array size is 0 and there are no elements after running, but at least it runs now.


Almost fully fixed my problem, but now a new issue cropped up that I can not figure out!!!!

        public void enqueue(E item) {
        int low = 0;
        int high = (arr.size());
        int mid =0;
        int cmp;
        if(arr.size()==0) {
            arr.add(item);
        }/**
        else if(arr.size()==1) {
            cmp = arrComp.compare(arr.get(0), item);
            if(cmp < 0){
                arr.add(item);
            }
            else {
                arr.add(0,item);
            }
        } **/
        else {
            while (low < high){
                mid = (low + high) / 2;
                cmp = arrComp.compare(arr.get(mid), item);
                if(cmp < 0){
                    low = (mid + 1);
                }
                else if (cmp > 0){
                    high = (mid - 1);
                }                   
            }
            arr.add(mid, item);
        }

}

My initialization for loop is elsewhere. As of right now, my output is {2, 3, 4, 5, 6, 1} using the above enqueue method as I initialize the arraylist. I can not for the life of me get this to fill it in order. GRANTED, my initialization is such that it is already in sequential order, but as per our assignment, we MUST initialize this using a binary search method when adding to the list.

WHY does the first initialized item stay at the end of the list? (the 1), when all other values get added in their correct location? Is it ONLY because the .add method of ArrayLists adds to the END of the list, even though it is the first value I am adding (using the .add method if the list size is currently 0)? How can I get around that?

My initial solution, the commented out part of the code, did nothing except make the output {3, 4, 5, 6, 1, 2} so I was even more confused, and I am now seeking advice.

Dragon Wolf
  • 61
  • 1
  • 2
  • 11

1 Answers1

2
 int high = (arr.size());// the why

Perhaps you should update your code in these ways:

  1. high = arr.size() - 1;
  2. mid = low + (high - low) / 2; // otherwise when low and high is big (if size is big) it might overflow the integer;
  3. int cmp = arrComp.compare(arr.get(mid), item); // to avoid senseless comparison;
Hearen
  • 7,420
  • 4
  • 53
  • 63
  • 1
    Specifically is his `while (low <= high)` Since the OP is using `<=` when the high is already out of bounds – gtgaxiola Jul 31 '18 at 15:22
  • Yes and no, @gtgaxiola. Other aspects of the code presented suppose that `high` is the largest index in the sub-array currently under consideration, not the index one past it. I'm looking specifically at `high = (mid - 1)`. It doesn't *have* to be that way, but everything does need to work together properly. – John Bollinger Jul 31 '18 at 15:28
  • @JohnBollinger indeed. – gtgaxiola Jul 31 '18 at 15:30
  • So bit shift for division by 2 wont work (the >>1 part)? Also, the get and add methods of ArrayList only use (int index) as a parameter. If I change to long, won't it break then anyway? I am doing up to 400,000 elements for complexity analysis. – Dragon Wolf Jul 31 '18 at 15:31
  • 1
    @DragonWolf it works but not **robust** `low + high` will overflow the integer before `shifting` and this will happen if you pass your method to some OJ, which will test that case. If you fully understand your case, like `size` will not be quite big then it's okay. But still I will think it's not good practice. – Hearen Jul 31 '18 at 15:33
  • @DragonWolf If you are okay with it, please do remember to mark it as an answer. And if it's good, please remember to upvote it for others' reference and also for my solution. Thank you ~ BE NICE in StackOverflow ;) – Hearen Jul 31 '18 at 15:42
  • 1
    Oh I will for certain once the correct answer is found. Your solution got the method to run, but now it does nothing (i.e. the array remains size 0 with no elements) But your solution at least got the method to run. Now I need it to run AND actually fill the array! – Dragon Wolf Jul 31 '18 at 15:50