My teacher assigned us to do the recursive version of mergesort, yet I heard that the non-recursive version (bottom up) is a bit tougher, so I decided to this one as well. My main concerns are:
- Considering the way I coded it, does it still have the same efficiency?
- Did I do this in an acceptable way? If not, why?
Main:
Random rand = new Random();
ArrayList<Integer> array = new ArrayList<Integer>();
for (int i = 0; i < 100; i++){
array.add(rand.nextInt(20));
}
System.out.println("Original:");
for (int num: array){
System.out.print(" " + num);
}
Algorithm algo = new Algorithm(array);
algo.print();
Code:
ArrayList<Integer> ar = new ArrayList<Integer>();
int loBound = 0, hiBound = 1;
public Algorithm(ArrayList<Integer> initAr){
ar = initAr;
partition();
}
public void partition(){
if (ar.size() > 1){
int partitionSize = 1;
int arraySize = ar.size();
if (ar.size() % 2 != 0) // if the size is odd make it even so loop doesn't terminate early without sorting all values
arraySize++;
while (arraySize / 2 >= partitionSize){
while (true){
ArrayList<Integer> left = new ArrayList<Integer>();
ArrayList<Integer> right = new ArrayList<Integer>();
// Variables which will be sent to 'update' method as parameters. Tells method which indexes to update (in-between low and high)
int loInd = loBound, hiInd;
for (int i = loBound; i < hiBound; i++){
left.add(ar.get(i));
}
calcBounds(partitionSize);
for (int j = loBound; j < hiBound; j++){
right.add(ar.get(j));
}
hiInd = hiBound;
if (right.size() != partitionSize){
update(left, right, loInd, hiInd);
break;
}
update(left, right, loInd, hiInd);
calcBounds(partitionSize);
}
partitionSize*=2;
loBound = 0;
hiBound = partitionSize;
}
}
}
// calculates the indexes from which I will extract from the original array
private void calcBounds(int partitionSize){
if (ar.size() - hiBound > partitionSize){
loBound = hiBound;
hiBound = loBound + partitionSize;
}else {
loBound = hiBound;
hiBound = ar.size();
}
}
// updates original ArrayList after sorting 'left' and 'right'
private void update(ArrayList<Integer> left, ArrayList<Integer> right, int loInd, int hiInd){
// sort
ArrayList<Integer> result = new ArrayList<Integer>();
int lIndex = 0, rIndex = 0, resIndex = 0;
while (lIndex < left.size() || rIndex < right.size()){
if (lIndex < left.size() && rIndex < right.size()){
if (left.get(lIndex) <= right.get(rIndex)){
result.add(resIndex, left.get(lIndex));
resIndex++;
lIndex++;
}else {
result.add(resIndex, right.get(rIndex));
resIndex++;
rIndex++;
}
}else if (lIndex < left.size()){
result.add(resIndex, left.get(lIndex));
resIndex++;
lIndex++;
}else if (rIndex < right.size()){
result.add(resIndex, right.get(rIndex));
resIndex++;
rIndex++;
}
}
// update original ArrayList using result ArrayList
int count = 0;
for (int i = loInd; i < hiInd; i ++){
ar.set(i, result.get(count));
count++;
}
}
void print(){
System.out.println();
System.out.println("Sorted:");
for (int num: ar){
System.out.print(" " + num);
}
}