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

Datenstrukturen

Datenstrukturen sind organisierte Methoden und Formate zur Speicherung, Verwaltung und Organisation von Daten in einem Computer oder einem anderen digitalen System. Sie ermöglichen effizienten Zugriff, Manipulation und Verarbeitung von Daten. Datenstrukturen sind ein grundlegendes Konzept in der Informatik und spielen eine entscheidende Rolle bei der Lösung von Problemen und der Entwicklung von Algorithmen.

Es gibt verschiedene Arten von Datenstrukturen, die jeweils für verschiedene Zwecke und Anforderungen optimiert sind. Hier sind einige wichtige Arten von Datenstrukturen:

  1. Arrays: Eine sequenzielle Anordnung von Elementen im Speicher. Der Zugriff auf Elemente erfolgt über Indizes.
  2. Listen: Eine geordnete Sammlung von Elementen. Es gibt verschiedene Arten von Listen wie verkettete Listen und doppelt verkettete Listen.
  3. Stacks: Ein Last-In-First-Out (LIFO) Datenstruktur, bei der Elemente in umgekehrter Reihenfolge abgerufen werden.
  4. Queues: Eine First-In-First-Out (FIFO) Datenstruktur, bei der Elemente in der Reihenfolge, in der sie hinzugefügt wurden, abgerufen werden.
  5. Bäume: Hierarchische Datenstrukturen, die aus Knoten bestehen. Beispiele sind Binärbäume, AVL-Bäume und B-Bäume.
  6. Graphen: Sammlungen von Knoten, die durch Kanten verbunden sind. Graphen können gerichtet oder ungerichtet sein.
  7. Hash-Tabellen: Datenstrukturen, die schnellen Zugriff auf Daten anhand von Schlüsseln ermöglichen.
  8. Heaps: Spezielle Bäume, die in der Regel zur Implementierung von Prioritätswarteschlangen verwendet werden.

Datenstrukturen spielen eine wesentliche Rolle bei der Optimierung der Laufzeit und des Speicherbedarfs von Algorithmen. Die Wahl der richtigen Datenstruktur hängt von den Anforderungen des Problems ab, das gelöst werden muss, sowie von Faktoren wie Speicherbedarf, Zugriffszeit und Einfüge-/Löschvorgängen.

Stack

Ein Stack ist eine Datenstruktur in der Informatik, die nach dem Last-In-First-Out (LIFO) Prinzip funktioniert. Das bedeutet, dass das zuletzt hinzugefügte Element als erstes entfernt wird. Ein Stack kann als Stapel von Objekten betrachtet werden, bei dem neue Elemente oben auf dem Stapel platziert werden und nur das oberste Element zugänglich ist.

Ein einfaches Beispiel für einen Stack ist ein Stapel von Tellern. Wenn Sie einen neuen Teller hinzufügen, legen Sie ihn oben auf den Stapel. Wenn Sie einen Teller entfernen möchten, nehmen Sie immer den obersten Teller weg. Das bedeutet, dass der zuletzt platzierte Teller als erster genommen wird.

Die beiden grundlegenden Operationen, die in einem Stack durchgeführt werden, sind:

  1. Push: Fügt ein Element oben auf den Stapel hinzu.
  2. Pop: Entfernt das oberste Element vom Stapel.
  3. TOP:Gibt das oberste Element des Stacks zurück, ohne es zu entfernen.
  4. isEmpty: Liefert true, wenn keine Elemente auf dem Stack liegen, andernfalls false.

Ein Stack kann in der Informatik vielseitig eingesetzt werden. Beispiele sind das Speichern von Aufrufen von Funktionen oder Methoden in einem Programm (Rückverfolgung von Funktionsaufrufen), die Auswertung von mathematischen Ausdrücken (um Operatoren und Operanden in der richtigen Reihenfolge zu verarbeiten), und das Überprüfen von Syntax in Programmiersprachen (zum Beispiel in Kombination mit einer Klammerprüfung).

Die Implementierung eines Stacks kann durch Arrays oder verkettete Listen erfolgen. In vielen Programmiersprachen, wie Java, gibt es bereits vordefinierte Klassen oder Bibliotheken für die Implementierung von Stacks.

Hier ist der Pseudocode für die grundlegenden Operationen eines Stacks (Push, Pop und Top) mithilfe eines Arrays:


Klasse MyStack
    private Array stackArray
    private Integer top

    Methode MyStack(initialSize)
        stackArray = Neues Array der Größe initialSize
        top = -1

    public boolean isEmpty();


    public boolean isFull();


    public boolean push(element)
        Wenn isFull():
            Ausgabe "Stack ist voll, kann kein Element hinzufügen"
        Sonst:


    public Object pop()
        Wenn isEmpty()
            Ausgabe "Stack ist leer, kein Element zum Entfernen"
        Sonst:

// get top element
    public Object getTopElement():
        Wenn isEmpty():
            Ausgabe "Stack ist leer, kein Element zum Ansehen"
        Sonst:
            Rückgabe stackArray[top]

// Test 

public static void main(String[] args) {
                MyStack stack = new MyStack(5);

	        stack.push(10);
	        stack.push(20);
	        stack.push(30);

	        System.out.println("Top element: " + stack.getTopElement()); // 30
	        stack.pop();
	        stack.pop();
	        System.out.println("Top element: " + stack.getTopElement()); // 10
	        stack.push(40);
	        System.out.println("Top element: " + stack.getTopElement()); // 40

	        while (!stack.isEmpty()) {
	            System.out.println("Popped element: " + stack.pop());
	        }
	    }


public class StackClass {
	    private Object[] stackArray;
	    private int top;

	    public StackClass(int initialSize) {
	        stackArray = new Object[initialSize];
	        top = -1;
	    }

	    public boolean isEmpty() {
	        return top == -1;
	    }

	    public boolean isFull() {
	        return top == stackArray.length - 1;
	    }

	    public boolean push(Object element) {
	        if (isFull()) {
	            System.out.println("Stack ist voll, kann kein Element hinzufügen");
                   return false;
	        } else {
	            top = top + 1;
	            stackArray[top] = element;
                     return false;
	        }
	    }

	    public Object pop() {
	        if (isEmpty()) {
	            System.out.println("Stack ist leer, kein Element zum Entfernen");
	            return null;
	        } else {
	            Object poppedElement = stackArray[top];
	            top = top - 1;
	            return poppedElement;
	        }
	    }

	    public Object getTopElement() {
	        if (isEmpty()) {
	            System.out.println("Stack ist leer, kein Element zum Ansehen");
	            return null;
	        } else {
	            return stackArray[top];
	        }
	    }

	    public static void main(String[] args) {
               stack.push(10);
               stack.push(20);
               stack.push(30);

              System.out.println("Top element: " + stack.getTopElement()); // 30
              stack.pop();
              System.out.println("Top element: " + stack.getTopElement()); // 20
              stack.push(40);
              System.out.println("Top element: " + stack.getTopElement()); // 40

             while (!stack.isEmpty()) {
                  System.out.println("Popped element: " + stack.pop());  // 40 , 20 , 10
            }

	    }
	}

Queue

Eine Queue (Warteschlange) ist eine Datenstruktur in der Informatik, die nach dem First-In-First-Out (FIFO) Prinzip funktioniert. Das bedeutet, dass das zuerst hinzugefügte Element als erstes entfernt wird. Eine Queue kann als Warteschlange von Objekten betrachtet werden, bei der neue Elemente hinten in die Warteschlange gestellt werden und nur das vorderste Element zugänglich ist.

 

Ein einfaches Beispiel für eine Queue ist eine Warteschlange von Personen an einem Ticketschalter. Die Person, die als erste in der Warteschlange steht, wird als erstes bedient und verlässt die Schlange zuerst.

Die beiden grundlegenden Operationen, die in einer Queue durchgeführt werden, sind:

  1. Enqueue: Fügt ein Element am Ende der Warteschlange hinzu
  2. Dequeue: Entfernt das vorderste Element aus der Warteschlange

Zusätzlich gibt es oft die Möglichkeit, das vorderste Element zu betrachten, ohne es zu entfernen. Diese Operation wird oft als "Front" oder "Peek" bezeichnet.

Eine Queue kann in der Informatik vielseitig eingesetzt werden. Beispiele sind die Verwaltung von Aufgaben in einem Betriebssystem (Prozessplanung), die Implementierung von Warteschlangen in Netzwerkprotokollen, und die Verwaltung von Druckaufträgen.

Die Implementierung einer Queue kann durch Arrays oder verkettete Listen erfolgen. In vielen Programmiersprachen gibt es bereits vordefinierte Klassen oder Bibliotheken für die Implementierung von Queues.

Hier ist der Pseudocode für die grundlegenden Operationen einer Queue (Enqueue, Dequeue und Peek) mithilfe eines Arrays:


Klasse MyQueue:
    private int[] array;
    private int front;
    private int rear;
    private int maxSize;
    private int currentSize;

// Konstruktor der Klasse
    public MyQueue(int maxSize) {
        this.array = new int[maxSize];
        this.front = 0;
        this.rear = -1;
        this.maxSize = maxSize;
        this.currentSize = 0;
     }

   public boolean isEmpty() 
      // TODO
     
   public boolean isFull()
      // TODO

   public void enqueue(int element) 
      Wenn nicht isFull()
       // TODO

   public void dequeue()
      Wenn nicht isEmpty()
      // TODO

    public int front()
      Wenn nicht istLeer()
       // TODO


// Test
    public static void main(String[] args) {
        MyQueue queue = new MyQueue(5);

        queue.enqueue(10);
        queue.enqueue(20);
        queue.enqueue(30);

        System.out.println("Front element: " + queue.front()); // Ausgabe: Front element: 10
        queue.dequeue();
        System.out.println("Front element after dequeue: " + queue.front()); // Ausgabe: Front element after dequeue: 20
    }

Dieser Pseudocode beschreibt die Funktionsweise einer Queue, die mithilfe eines Arrays implementiert wird. Die Data ist das Array, das die Elemente der Queue speichert, Front ist der Index des vordersten Elements und Rear ist der Index des hintersten Elements.

Beachten Sie, dass dieser Pseudocode eine einfache Implementierung einer Queue darstellt. In der Praxis sollten Sie möglicherweise weitere Überlegungen berücksichtigen, wie zum Beispiel die Behandlung von Überlauf (wenn die Queue voll ist) oder Unterlauf (wenn die Queue leer ist). Es gibt auch andere Möglichkeiten zur Implementierung einer Queue, wie zum Beispiel mithilfe von verketteten Listen.

Hier ist ein einfacher Java-Code, der die Implementierung einer Queue mithilfe eines Arrays zeigt:


public class MyQueue {
    private int[] array;
    private int front;
    private int rear;
    private int maxSize;
    private int currentSize;

    public MyQueue(int maxSize) {
        this.array = new int[maxSize];
        this.front = 0;
        this.rear = -1;
        this.maxSize = maxSize;
        this.currentSize = 0;
    }

    public boolean isEmpty() {
        return currentSize == 0;
    }

    public boolean isFull() {
        return currentSize == maxSize;
    }

    public void enqueue(int element) {
        if (!isFull()) {
            rear = (rear + 1) % maxSize;
            array[rear] = element;
            currentSize++;
        }
    }

    public void dequeue() {
        if (!isEmpty()) {
            front = (front + 1) % maxSize;
            currentSize--;
        }
    }

    public int front() {
        if (!isEmpty()) {
            return array[front];
        }
        return -1; // oder eine andere geeignete Fallback-Wert
    }

    public static void main(String[] args) {
        MyQueue queue = new MyQueue(5);

        queue.enqueue(10);
        queue.enqueue(20);
        queue.enqueue(30);

        System.out.println("Front element: " + queue.front()); // 10

        queue.dequeue();

        System.out.println("Front element after dequeue: " + queue.front()); // 20
    }
}


Dieser Code zeigt die Grundfunktionalitäten einer Queue in Java. Beachten Sie, dass dies nur eine einfache Implementierung ist und in der Praxis zusätzliche Funktionen und Fehlerbehandlungen hinzugefügt werden könnten.