algorithms-for-computing-li.../src/main/java/Presenter/Algorithms/InversionCounter.java

139 lines
3.9 KiB
Java

package Presenter.Algorithms;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 18.06.2017.
*/
public class InversionCounter {
private HashMap<Integer, Integer> dictionaryTO;
private HashMap<Integer, Integer> dictionaryBACK;
private ArrayList<Integer> substituted;
private ArrayList<Pair> inversions;
private class Pair{
private Integer p1;
private Integer p2;
public Pair(Integer p1, Integer p2) {
this.p1 = p1;
this.p2 = p2;
}
public Integer getP1() {
return p1;
}
public void setP1(Integer p1) {
this.p1 = p1;
}
public Integer getP2() {
return p2;
}
public void setP2(Integer p2) {
this.p2 = p2;
}
}
public int run(List<Integer> a, List<Integer> b){
dictionaryTO = new HashMap<>();
dictionaryBACK = new HashMap<>();
substituted = new ArrayList<>();
inversions = new ArrayList<>();
ArrayList<Integer> temp = new ArrayList<>();
temp.addAll(a);
for (int i=0;i<a.size();i++){
dictionaryTO.put(a.get(i), i+1 );
dictionaryBACK.put(i+1 , a.get(i));
}
for (int j=0;j<b.size();j++){
substituted.add(dictionaryTO.get(b.get(j)));
}
int ret = countInversions(substituted, 0, substituted.size()-1, temp);
getInversionPairs();
dictionaryTO = null;
substituted = null;
inversions = null;
return ret;
}
/**
* Angepasster Merge-Sort Algorithmus.
* Die Funktion bekommt neben den standard Parametern zusätzlich eine Liste mit Elementen
* die als Groundtruth dienen.
* @param a Eingabefeld mit den Elementen die überprüft werden sollen.
* @param start Startpunkt des Eingabefeldes.
* @param end Endpunkt des Eingabefeldes.
* @param aux Groundtruth Ordnung um die Anzahl der Inversionen zu bestimmen.
* @return Anzahl der inversionen zwischen a und aux.
*/
public int countInversions(List<Integer> a, int start, int end, List<Integer> aux) {
if (start >= end) {
return 0;
}
int invCount = 0;
int mid = start + (end - start) / 2;
int invCountLeft = countInversions(a, start, mid, aux); // divide and conquer
int invCountRight = countInversions(a, mid + 1, end, aux); // divide and conquer
invCount += (invCountLeft + invCountRight);
for (int i = start; i <= end; i++) {
aux.set(i, a.get(i));
}
int left = start;
int right = mid + 1;
int index = start;
while (left <= mid && right <= end) {
if (aux.get(left) < aux.get(right)) {
a.set(index++, aux.get(left++));
} else {
for (int i=left; i<=mid;i++){
// System.out.println(aux.get(i)+" -- "+ aux.get(right));
inversions.add(new Pair(aux.get(i), aux.get(right)));
}
a.set(index++, aux.get(right++));
invCount += mid - left + 1; // number of inversions for aux[right]
}
}
while (left <= mid) {
a.set(index++, aux.get(left++));
}
// no need to copy over remaining aux[right++] because they are already inside a
return invCount;
}
public void getInversionPairs(){
ArrayList<Pair> result = new ArrayList<>();
for (int i=0;i<inversions.size();i++){
result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()), dictionaryBACK.get(inversions.get(i).getP2())));
}
//for (Pair p : result){
// System.out.println(p.getP1() + " <==> " + p.getP2());
//}
}
}