Professionelle Java-Schulung – Vor Ort und Online.

  • Einführung in die Welt der Java-Programmierung
  • Konzepte und Techniken von Algorithmen kennenlernen
  • Datenbanken und ihren Einsatz in der digitalen Welt

Suche



In der Informatik bezieht sich "Suche" auf den Prozess des Findens eines bestimmten Elements oder einer bestimmten Information in einem gegebenen Datensatz, sei es in einer Liste, einem Array, einer Datenbank oder einem anderen Datenstruktur.

Suchen ist ein grundlegender Aspekt der Informatik, da er in vielen Anwendungen und Algorithmen verwendet wird. Es gibt verschiedene Arten von Suchalgorithmen, die je nach Kontext und den Eigenschaften der Datenstruktur verwendet werden. Einige der häufigsten Suchalgorithmen sind:

  1. Sequentielle Suche:Hier wird hier jedes Element nacheinander überprüft, bis das gesuchte Element gefunden wird oder festgestellt wird, dass es nicht vorhanden ist.
  2. Binäre Suche: Diese Suche funktioniert nur in geordneten Listen. Sie teilt die Liste in zwei Hälften und vergleicht den gesuchten Wert mit dem mittleren Wert. Basierend auf dem Ergebnis des Vergleichs wird die Suche in der linken oder rechten Hälfte fortgesetzt.
  3. Baumstrukturen: In Baumstrukturen wie binären Suchbäumen wird der Datensatz in einer hierarchischen Struktur organisiert, die die Suche effizienter macht.
  4. Sortierte Liste: Wenn die Liste bereits sortiert ist, können spezielle Algorithmen wie Interpolationssuche oder exponentielle Suche verwendet werden, um die Suche zu beschleunigen.
  5. Reguläre Ausdrücke: In Textsuchen können reguläre Ausdrücke verwendet werden, um Muster in Texten zu suchen.
  6. Hashing: Hier wird der gesuchte Wert in eine Hashfunktion eingegeben, die den Index oder die Adresse des Wertes in einer Datenstruktur wie einem Array oder einer Hashtabelle bestimmt.

Die Wahl des richtigen Suchalgorithmus hängt von verschiedenen Faktoren wie der Art der Datenstruktur, der Anzahl der Daten und der Art der gesuchten Informationen ab. Jeder Algorithmus hat Vor- und Nachteile hinsichtlich Geschwindigkeit und Speicherplatzanforderungen.



Sequentielle Suche

Die sequentielle Suche, auch lineare Suche genannt, ist ein grundlegendes Suchverfahren in der Informatik. Es handelt sich um eine Methode, um in einer ungeordneten oder geordneten Liste nach einem bestimmten Element zu suchen. Dabei werden die Elemente der Liste nacheinander überprüft, bis das gesuchte Element gefunden wird oder festgestellt wird, dass es nicht vorhanden ist.

Hier ist eine einfache Implementierung der sequentiellen Suche in Java:


public class SequentialSearch {

    public static int sequentialSearch(int[] array, int target) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == target) {
                return i; // Index des gefundenen Elements
            }
        }
        return -1; // Element nicht gefunden
    }

    public static void main(String[] args) {
        int[] numbers = { 12, 45, 67, 89, 34, 56, 23 };
        int target = 56;

        int index = sequentialSearch(numbers, target);

        if (index != -1) {
            System.out.println("Das Element " + target + " wurde an Index " + index + " gefunden.");
        } else {
            System.out.println("Das Element " + target + " wurde nicht gefunden.");
        }
    }
}


In diesem Beispiel wird die Methode sequentialSearch verwendet, um nach einem Zielwert in einem Array zu suchen. Die Schleife durchläuft das Array und vergleicht jedes Element mit dem Zielwert. Wenn das Element gefunden wird, wird der Index zurückgegeben. Andernfalls wird -1 zurückgegeben, um anzuzeigen, dass das Element nicht gefunden wurde.



binäre Suche

Die binäre Suche, auch als binaere Suche oder binary search bekannt, ist ein effizienter Suchalgorithmus, der auf bereits sortierten Listen oder Arrays angewendet wird. Sie nutzt den Vorteil der Sortierung, um die Suche schneller durchzuführen, indem sie die Liste in jedem Schritt halbiert.

Hier ist das grundlegende Konzept der binären Suche:

  1. Vorbereitung: Die Liste muss zuerst in aufsteigender Reihenfolge sortiert sein, da die binäre Suche auf dieser Eigenschaft aufbaut.
  2. Suchprozess: Die Suche beginnt damit, den mittleren Wert der Liste zu überprüfen. Wenn dieser mittlere Wert gleich dem gesuchten Wert ist, ist die Suche abgeschlossen. Wenn der mittlere Wert kleiner ist als der gesuchte Wert, wird die Suche nur in der rechten Hälfte der Liste fortgesetzt. Ist der mittlere Wert größer, wird die Suche nur in der linken Hälfte fortgesetzt.
  3. Wiederholung: Dieser Schritt wird wiederholt, bis der gesuchte Wert gefunden wird oder bis die beiden Suchgrenzen sich überschneiden und der gesuchte Wert nicht gefunden wurde.



Das Prinzip soll anhand eines Beispiels verdeutlicht werden. Wir gehen von der sortierten Folge in dieser Abbildung aus und suchen nach dem Element 8.

  1. Die untere Grenze u ist zunächst 1, die obere Grenze o wird auf 10 gesetzt. Daraus ergibt sich für die mittlere Position entsprechend 5.
  2. Da der Such- Schlüssel größer als das Element an dieser Position ist, müssen wir in der rechten Hälfte weitersuchen.
  3. Für den nächsten Schritt wird demnach u = 6 und m = 8 gesetzt.
  4. Da 8 kleiner als das Element F [8] ist, wird der Suchbereich auf den linken Teil ([6, 7]) eingeschränkt, wo das gesuchte Element schließlich gefunden wird.

Algorithmus dazu


anf=1;
end=n;
while  anf<= end do
   mitte= (anf+end)/2;
   if a[mitte] = key then
       return mitte;
   else if key < a[mitte] then
      end = mitte -1;
   else
      anf = mitte +1;
end do;
return -1 // nicht gefunden


Die binäre Suche hat eine Laufzeitkomplexität von O(log n), was bedeutet, dass sie sehr effizient ist, insbesondere für große Datensätze. Da sie die Liste in jedem Schritt halbiert, wird die Anzahl der verbleibenden Elemente sehr schnell reduziert. Dies ist im Vergleich zur sequentiellen Suche, die eine Laufzeitkomplexität von O(n) hat, deutlich schneller. Allerdings funktioniert die binäre Suche nur auf bereits sortierten Listen und erfordert zusätzlichen Aufwand, um die Liste zu sortieren, wenn sie nicht bereits sortiert ist.


public class BinarySearchExample {
    public static int binarySearch(int[] array, int target) {
        int left = 0;
        int right = array.length - 1;

        while (left <= right) {
            int middle = left + (right - left) / 2;

            if (array[middle] == target) {
                return middle; // Zielwert gefunden, gib den Index zurück
            } else if (array[middle] < target) {
                left = middle + 1; // Suche in der rechten Hälfte
            } else {
                right = middle - 1; // Suche in der linken Hälfte
            }
        }

        return -1; // Zielwert nicht gefunden
    }

    public static void main(String[] args) {
        int[] sortedArray = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
        int target = 10;

        int result = binarySearch(sortedArray, target);

        if (result != -1) {
            System.out.println("Zielwert " + target + " gefunden an Index " + result);
        } else {
            System.out.println("Zielwert " + target + " nicht gefunden.");
        }
    }
}


In diesem Beispiel wird die Methode binarySearch verwendet, um nach einem Zielwert in einem sortierten Array zu suchen. Die Schleife führt die binäre Suche durch, indem sie die linke und rechte Suchgrenze anpasst und den mittleren Index berechnet. Basierend auf dem Vergleich des mittleren Werts mit dem Zielwert wird entschieden, ob die Suche in der linken oder rechten Hälfte fortgesetzt wird. Wenn der Zielwert gefunden wird, wird der Index zurückgegeben, andernfalls wird -1 zurückgegeben, um anzuzeigen, dass der Zielwert nicht im Array vorhanden ist.



Regulären Ausdrücke

Reguläre Ausdrücke, auch als Regex oder RegExp abgekürzt, sind eine mächtige und flexible Methode zur Mustererkennung und Textverarbeitung in verschiedenen Programmiersprachen und Texteditoren. Sie ermöglichen es, komplexe Suchmuster in Texten zu definieren und diese Muster dann in einem Text zu suchen, zu extrahieren, zu ersetzen oder zu validieren.

Mit regulären Ausdrücken können Sie nach bestimmten Mustern in Texten suchen, die mehr sind als einfache Zeichenfolgen. Sie können Zeichenklassen, Quantoren, Gruppierung und andere spezielle Zeichen verwenden, um komplexere Muster zu erstellen.

Hier sind einige häufige Verwendungen von regulären Ausdrücken:

  1. Textsuche: Sie können nach bestimmten Wörtern, Phrasen oder Mustern in einem Text suchen.
  2. Validierung: Sie können prüfen, ob eine Zeichenfolge einem bestimmten Muster entspricht, z. B. ob eine E-Mail-Adresse oder eine Telefonnummer gültig ist.
  3. Extraktion: Sie können Teile eines Texts extrahieren, die einem bestimmten Muster entsprechen, z. B. das Extrahieren von URLs aus einem Text.
  4. Ersetzung: Sie können Teile eines Texts durch andere Zeichenfolgen ersetzen, die einem bestimmten Muster entsprechen, z. B. das Maskieren von sensiblen Daten wie Kreditkartennummern.

Ein einfaches Beispiel für die Verwendung eines regulären Ausdrucks könnte sein, nach allen Wörtern zu suchen, die mit "Java" beginnen:


import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegularExpressionExample {
    public static void main(String[] args) {
        String text = "Java ist eine beliebte Programmiersprache. JavaScript ist auch verbreitet.";
        String pattern = "\\bJava\\w*"; // Muster für Wörter, die mit "Java" beginnen

        Pattern regex = Pattern.compile(pattern);
        Matcher matcher = regex.matcher(text);

        while (matcher.find()) {
            System.out.println("Gefunden: " + matcher.group());
        }
    }
}

In diesem Beispiel wird der reguläre Ausdruck `"\\bJava\\w*"` verwendet, um nach Wörtern zu suchen, die mit "Java" beginnen. Die Methode `find()` des Matchers durchsucht den Text nach Übereinstimmungen und die Methode `group()` gibt die gefundenen Übereinstimmungen aus.

Hier ist eine Tabelle mit einigen grundlegenden Elementen und Zeichenfolgen, die in regulären Ausdrücken verwendet werden können:


| Symbol | Beschreibung                                      | Beispiel                    |
|--------|---------------------------------------------------|-----------------------------|
| `.`    | Jedes Zeichen außer Zeilenumbruch                 | `a.b` passt auf "acb", "aab"|
| `*`    | Null oder mehr Vorkommen                          | `a*b` passt auf "ab", "aaab"|
| `+`    | Ein oder mehr Vorkommen                           | `a+b` passt auf "ab", "aab" |
| `?`    | Null oder ein Vorkommen                           | `a?b` passt auf "ab", "b"   |
| `[]`   | Zeichenklasse                                     | `[aeiou]` passt auf Vokale  |
| `[^]`  | Negierte Zeichenklasse                            | `[^0-9]` Nicht-Zahlen       |
| `()`   | Gruppierung                                       | `(abc)+` passt auf "abcabc" |
| `|`    | Oder                                              | `a|b` passt auf "a" oder "b"|
| `\`    | Escape-Zeichen für spezielle Zeichen              | `\.` passt auf Punkt `.`    |
| `\d`   | Eine Ziffer                                       | `\d{3}` passt auf "123"     |
| `\w`   | Ein Wortzeichen (Buchstabe, Zahl oder Unterstrich)| `\w+` passt auf "word123"   |
| `\s`   | Ein Leerzeichen, Tabulator oder Zeilenumbruch     | `\s+` passt auf Leerzeichen |
| `^`    | Zeilenanfang                                      | `^start` Anfang der Zeile   |
| `$`    | Zeilenende                                        | `end$` Ende der Zeile       |




Bitte beachten Sie, dass dies nur einige grundlegende Elemente sind. Reguläre Ausdrücke können viel komplexer werden und erfordern möglicherweise tiefere Kenntnisse, um effizient und korrekt eingesetzt zu werden.

Aufgabe: Überprüfung von E-Mail-Adressen

Schreiben Sie ein Java-Programm, das eine Liste von E-Mail-Adressen überprüft und nur die gültigen E-Mail-Adressen ausgibt.

  1. Erstellen Sie eine Liste von E-Mail-Adressen, die sowohl gültige als auch ungültige Adressen enthält.
  2. Verwenden Sie reguläre Ausdrücke, um die Gültigkeit jeder E-Mail-Adresse zu überprüfen.
  3. Geben Sie nur die gültigen E-Mail-Adressen in der Konsole aus.