Sortieren in Abhängigkeit von einer anderen Sortierung

djoledjoxn

Mitglied
Guten Abend alle miteinander,

ich bin ein JAVA Einsteiger und stehe nun vor einem mir unlösbaren Problem.
Ich habe ein Programm geschrieben, welches zählt wie oft jeder Buchstabe in einer Textdatei vorkommt.
Ich hab das so in etwa gemacht:

Java:
int[] anzahl = new int [26];
char[] alphabet = new char [] {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int counter = 0;
/*Mithilfe einer doppelten for-Schleife überprüfe ich an jeder Stelle ob der char bei dieser Position mein jetziger Buchstabe ist (zB string.charAt[1] == alphabet[0]) falls das der Fall ist, wird mein counter um 1 erhöht. Am Ende der Schleife ist meine zB anzahl[0] += counter */

die Anzahl der Buchstaben wird richtig gezählt. Doch jetzt muss ich beide Arrays sortieren.
Und so komm ich auch zu meiner eigentlichen Frage. Das Array anzahl[] kann ich ja leicht mit Arrays.sort() sortieren. Doch nun würde ich gerne mein Array alphabet[] genau so sortieren wie das Array anzahl. Also anders gesagt würde ich die Buchstaben nach ihrer Häufigkeit sortiert ausgeben.

Im vorhinein schon vielen Dank für eure Hilfe!

mfg,
djoxn
 
Schreib ne Klasse mit Buchstabe und Anzahl als Membervariablen. Eine Array von Instanzen dieser Klasse kannst du dann sortieren mithilfe von Arrays.sort und einer eigenen Implementierung von Comparator, welcher einfach nur die Anzahl compared.
 
hmm ich mach Java erst seit kurzem und bin noch nicht bei der Verwendung der Klassen angekommen.
Also es wäre voll Nett wenn du mir das irgendwie genauer Erläutern könntest.

Danke 🙂
 
Ist das eine Aufgabe um Sortier Algorithmen zu lernen? Dann wirst du wohl nicht sort verwenden dürfen...

Un dich denke nicht, dass wir hier jetzt die Grundlagen von Objekten diskutieren müssen, dafür gibts genug andere Quellen...
 
Bau dir eine eigene swap-Methode, die auch die Elemente des anderen Arrays vertauscht.

Oder verwende eine HashMap<Character, Integer> und sortiere diese anschließend.

Oder schreib dir eine eigene Klasse, mit Attributen / Instanzvariablen, die Comparable implementiert, oder verwende zum Sortieren einen eigenen Comparator.
 
Bau dir eine eigene swap-Methode, die auch die Elemente des anderen Arrays vertauscht.

Oder verwende eine HashMap<Character, Integer> und sortiere diese anschließend.

Oder schreib dir eine eigene Klasse, mit Attributen / Instanzvariablen, die Comparable implementiert, oder verwende zum Sortieren einen eigenen Comparator.

mit HashMap kenn ich mich garnicht aus.
ich bin grad am rumprobieren mit den Klassen.

Danke
 
Schreib doch die Sortierfunktion so, dass jede Verschiebung, die am anzahl-Array durchgeführt wird auch am alphabet-Array ausgeführt wird.
 
Die Frage von ARadauer war schon die richtige: Um hier eine passende Antwort geben zu können, müßte man wissen, das das Ziel der Übung ist. Wenn's nur um Elementares geht: Bubble- oder besser SelectionSort mit eigener Swap-Methode (die halt in beiden Arrays vertauscht), ansonsten was mit Comparator...
 
Bubblesort geht immer (hier ohne optimierungen):

Java:
		// blubb blubb
		boolean blnHasError = false;
		while (true) {
			blnHasError = false;
			for (int i = 0; i < anzahl.length - 1; i++) {
				if (anzahl[i] < anzahl[i + 1]) {
					int tmpi = anzahl[i];
					anzahl[i] = anzahl[i + 1];
					anzahl[i + 1] = tmpi;
					char tmpc = alphabet[i];
					alphabet[i] = alphabet[i + 1];
					alphabet[i + 1] = tmpc;
					blnHasError = true;
				}
			}
			if (!blnHasError) break;
		}
 
Wenn's unbedingt char[] und int[] sein muss, würde ich's so machen:

Java:
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author no0b
 */
public class ZeichenZählen {

    private char[] chars = new char['z' - 'a' + 1];
    private int[] counts = new int[chars.length];

    public ZeichenZählen() {
        for (int i = 0; i < chars.length; i++) {
            chars[i] = (char) ('a' + i);
        }
    }

    public void zähle(char c) {
        c = Character.toLowerCase(c);
        int index = Arrays.binarySearch(chars, c);
        if (index >= 0) {
            counts[index]++;
        }
    }

    public Object[][] getCharsAndCounts() {
        Object[][] result = new Object[chars.length][2];
        for (int i = 0; i < chars.length; i++) {
            result[i][0] = chars[i];
            result[i][1] = counts[i];
        }
        Arrays.sort(result, new Comparator<Object[]>() {

            @Override
            public int compare(Object[] o1, Object[] o2) {
                return ((Integer) o1[1]).compareTo((Integer) o2[1]);
            }
        });
        return result;
    }

    public static void main(String[] args) {
        String langerString = "Quicksort (von englisch quick ‚schnell‘ und to sort ‚sortieren‘) ist ein schneller, rekursiver, nicht-stabiler Sortieralgorithmus, der nach dem Prinzip Teile und herrsche (lat. Divide et impera!, engl. Divide and conquer) arbeitet. Er wurde ca. 1960 von C. Antony R. Hoare in seiner Grundform entwickelt[1] und seitdem von vielen Forschern verbessert. Der Algorithmus hat den Vorteil, dass er über eine sehr kurze innere Schleife verfügt (was die Ausführungsgeschwindigkeit stark erhöht) und ohne zusätzlichen Speicherplatz auskommt (abgesehen von dem für die Rekursion zusätzlichen benötigten Platz auf dem Aufruf-Stack).";
        ZeichenZählen zz = new ZeichenZählen();
        for (char c : langerString.toCharArray()) {
            zz.zähle(c);
        }
        System.out.println(Arrays.deepToString(zz.getCharsAndCounts()));
    }
}

Erzeugt dann so eine schöne Ausgabe:
Code:
[[j, 0], [x, 0], [y, 1], [q, 3], [w, 4], [b, 6], [p, 6], [z, 8], [f, 9], [k, 10], [m, 10], [g, 11], [v, 11], [c, 19], [l, 19], [o, 20], [d, 22], [u, 22], [a, 23], [h, 23], [s, 34], [t, 34], [i, 40], [n, 40], [r, 47], [e, 72]]

Aber wenn nicht auf Arrays.sort zurückgegriffen werden darf, würde ich einen eigene Sortiermethode schreiben (z.B. Selectionsort), dieser ist relativ einfach zu schreiben und benötigt nicht so viele Vertauschungen wie Bubblesort. Natürlich gibt es ein paar schnellere Sortierverfahren und auch viele langsamere.

PS. Umlaute sollte man (eigentlich) im Quelltext vermeiden, sonst habe ich mich aber (einigermaßen) an die Konventionen gehalten.
 
Ich hab's nochmal erweitert, es werden jetzt auch Umlaute gezählt:

Java:
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author no0b
 */
public class ZeichenZählen {

    private final char[] chars;
    private final int[] counts;

    public ZeichenZählen() {
        chars = new char['z' - 'a' + 1];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = (char) ('a' + i);
        }
        counts = new int[chars.length];
    }

    public ZeichenZählen(char[] charsParam) {
        chars = new char[charsParam.length];
        System.arraycopy(charsParam, 0, chars, 0, charsParam.length);
        Arrays.sort(chars);
        counts = new int[chars.length];
    }

    public void zähle(char c) {
        int index = Arrays.binarySearch(chars, Character.toLowerCase(c));
        if (index >= 0) {
            counts[index]++;
        }
    }

    public Object[][] getCharsAndCounts() {
        Object[][] result = new Object[chars.length][2];
        for (int i = 0; i < chars.length; i++) {
            result[i][0] = chars[i];
            result[i][1] = counts[i];
        }
        Arrays.sort(result, new Comparator<Object[]>() {

            @Override
            public int compare(Object[] o1, Object[] o2) {
                return ((Integer) o1[1]).compareTo((Integer) o2[1]);
            }
        });
        return result;
    }

    public static void main(String[] args) {
        String langerString = "....";
        ZeichenZählen[] zzs = {new ZeichenZählen(), new ZeichenZählen("äöü".toCharArray()), new ZeichenZählen(Character.toChars(32))};
        for (char c : langerString.toCharArray()) {
            for (ZeichenZählen zz : zzs) {
                zz.zähle(c);
            }
        }
        for (ZeichenZählen zz : zzs) {
            System.out.println(Arrays.deepToString(zz.getCharsAndCounts()));
        }
    }
}

Aber mit den ganzen Arrays ist das mehr oder weniger nur ein Notlösung.

Grüße
 
hier mal ne viel einfachere Lösung mit HashMap. Es werden alle Zeichen unterstützt.
Java:
		String s = "asDSAsdSAaddsASASASASDASDASSDasdas  ASDassd asd ASDSADA555%%5%555%%5%5%%%%        asdSASD";

		HashMap<Character, Integer> amounts = new HashMap<>();
		for(char c : s.toCharArray()) {
			if(!amounts.containsKey(c)) {
				amounts.put(c, 1);
			}
			else {
				amounts.put(c, amounts.get(c)+1);
			}
		}

		Object[] amountsArray = amounts.entrySet().toArray();
		Arrays.sort(amountsArray, new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2) {
				return ((Entry<Character, Integer>) o1).getValue().compareTo(((Entry<Character, Integer>) o2).getValue());
			}
		});
 
Zuletzt bearbeitet:
Ich danke euch sehr, ich hab es in der Nacht irgendwie geschafft es Fertig zu stellen bin nur leider erst jetzt dazu gekommen ins Forum zu schauen. Ich werde Morgen meinen Code posten, weil wenn ich es jetzt posten würde, würde es als Plagiat gehandhabt werden.

Trotzdem vielen Dank euch allen!
 

Zurück
Oben