Reputation: 287
I wrote an implementation of inversion-counting. This is an assignment being carried out in an online course. But the input i get isn't correct and according to what I have the program has a correct syntax. I dont just know were I went wrong The program below is my implementation
import java.io.*;
class CountInversions {
//Create an array of length 1 and keep expanding as data comes in
private int elements[];
private int checker = 0;
public CountInversions() {
elements = new int[1];
checker = 0;
}
private boolean isFull() {
return checker == elements.length;
}
public int[] getElements() {
return elements;
}
public void push(int value) {
if (isFull()) {
int newElements[] = new int[elements.length * 2];
System.arraycopy(elements, 0, newElements, 0, elements.length);
elements = newElements;
}
elements[checker++] = value;
}
public void readInputElements() throws IOException {
//Read input from file and until the very last input
try {
File f = new File("IntegerArray.txt");
FileReader fReader = new FileReader(f);
BufferedReader br = new BufferedReader(fReader);
String stringln;
while ((stringln = br.readLine()) != null) {
push(Integer.parseInt(stringln));
}
System.out.println(elements.length);
fReader.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());
} finally {
// in.close
}
}
//Perform the count inversion algorithm
public int countInversion(int array[],int length){
int x,y,z;
int mid = array.length/2 ;
int k;
if (length == 1){
return 0;
}else{
//count Leftinversion and count Rightinversion respectively
int left[] = new int[mid];
int right[] = new int[array.length - mid];
for(k = 0; k < left.length;k++){
left[k] = array[k];
}
for(k = 0 ;k < right.length;k++){
right[k] = array[mid + k];
}
x = countInversion(left, left.length);
y = countInversion(right, right.length);
int result[] = new int[array.length];
z = mergeAndCount(left,right,result);
//count splitInversion
return x + y + z;
}
}
private int mergeAndCount(int[] left, int[] right, int[] result) {
int count = 0;
int i = 0, j = 0, k = 0;
int m = left.length, n = right.length;
while(i < m && j < n){
if(left[i] < right[j]){
result[k++] = left[i++];
}else{
result[k++] = right[j++];
count += left.length - i;
}
}
if(i < m){
for (int p = i ;p < m ;p++){
result[k++] = left[p];
}
}
if(j < n){
for (int p = j ;p < n ;p++){
result[k++] = right[p];
}
}
return count;
}
}
class MainApp{
public static void main(String args[]){
int count = 0;
CountInversions cIn = new CountInversions();
try {
cIn.readInputElements();
count = cIn.countInversion(cIn.getElements(),cIn.getElements().length);
System.out.println("Number of Inversios: " + count);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Upvotes: 0
Views: 416
Reputation: 183968
Your code works if the array length is a power of 2 (actually, I'm not sure whether if does, see second point below).
When reading the input, you double the array size when it's full, but you never resize it to the number of actually read items, which is stored in checker
. So your array length is a power of 2, and if the number of int
s read from the file is not a power of 2, you have a too long array with some trailing 0
elements corresponding to the places allocated but not filled from the file. Since you call countInversions
with the length of the array and not with the number of read items, these 0
s are sorted too, yielding some spurious inversions.
After reading the input, allocate a new array
int[] copy = new int[checker];
for(int i = 0; i < checker; ++i) {
copy[i] = elements[i];
}
elements = copy;
copy the elements, and discard the old array with the wrong capacity.
Another problem in your algorithm is that you never change the original array because you allocate a new array for the merge result,
int result[] = new int[array.length];
z = mergeAndCount(left,right,result);
so you are merging unsorted arrays, which may also skew the inversion count. Since you copied the halves of the input array to new arrays for the recursive calls, you can without problem put the merge result in the passed-in array, so replace the above two lines with
z = mergeAndCount(left,right,array);
to get a method that actually sorts the array and counts the inversions.
Upvotes: 2
Reputation: 1641
This post is tackling the problem of count inversion with Java (except for file reading, which you have done OK) - Counting inversions in an array
Upvotes: 1