Einführung

Die 7 wichtigsten Algorithmen für Datenstrukturen in Python

Warum sind Algorithmen für Datenstrukturen in Python wichtig?

  • Optimierte Leistung:
  • Datenorganisation:

Die 7 wichtigsten Algorithmen für Datenstrukturen in Python

Sehen wir uns nun die sieben wichtigsten Algorithmen für Datenstrukturen in Python an.

Algorithmusschritte

Variablen initialisieren:

  • Satz left auf 0 (den Startindex des Arrays).
  • Satz proper Zu n - 1 (der Endindex des Arrays, wobei n ist die Länge des Arrays).

Schleife bis left ist größer als proper:

  • Berechnen Sie die mid Index als Mindestwert von (left + proper) / 2.

Überprüfen Sie das mittlere Factor:

  • Wenn arr(mid) ist gleich dem Zielwert:
    • Zurückgeben des Indexes mid (Ziel wurde gefunden).
  • Wenn arr(mid) ist kleiner als der Zielwert:
    • Satz left Zu mid + 1 (ignorieren Sie die linke Hälfte).
  • Wenn arr(mid) ist größer als der Zielwert:
    • Satz proper Zu mid - 1 (ignorieren Sie die rechte Hälfte).

Wenn die Schleife endet, ohne das Ziel zu finden:

  • Zurückkehren -1 (Ziel ist nicht im Array vorhanden).

Code-Implementierung

def binary_search(arr, goal):
    left, proper = 0, len(arr) - 1
    
    whereas left <= proper:
        mid = (left + proper) // 2
        
        # Examine if the goal is at mid
        if arr(mid) == goal:
            return mid
        
        # If the goal is bigger, ignore the left half
        elif arr(mid) < goal:
            left = mid + 1
        
        # If the goal is smaller, ignore the best half
        else:
            proper = mid - 1
    
    # Goal will not be current within the array
    return -1

# Instance utilization:
arr = (2, 3, 4, 10, 40)
goal = 10

consequence = binary_search(arr, goal)

if consequence != -1:
    print(f"Factor discovered at index {consequence}")
else:
    print("Factor not current in array")

2. Zusammenführendes Sortieren

Algorithmusschritte

Teilen:

  • Wenn das Array mehr als ein Factor hat, teilen Sie das Array in zwei Hälften:
    • Finde den Mittelpunkt mid um das Array in zwei Hälften zu teilen: left = arr(:mid) Und proper = arr(mid:).

Erobern:

  • Mergesort rekursiv auf beide Hälften anwenden:
    • Sortieren Sie die left Hälfte.
    • Sortieren Sie die proper Hälfte.

Verschmelzen:

  • Fügen Sie die beiden sortierten Hälften zu einem einzigen sortierten Array zusammen:
    • Vergleichen Sie die Elemente von left Und proper nacheinander und platzieren Sie das kleinere Factor im ursprünglichen Array.
    • Fahren Sie fort, bis alle Elemente aus beiden Hälften wieder zum ursprünglichen Array zusammengeführt sind.

Basisfall:

  • Wenn das Array nur ein Factor hat, ist es bereits sortiert und kann sofort zurückgegeben werden.

Code-Implementierung

def merge_sort(arr):
    if len(arr) > 1:
        # Discover the center level
        mid = len(arr) // 2
        
        # Divide the array components into 2 halves
        left_half = arr(:mid)
        right_half = arr(mid:)
        
        # Recursively type the primary half
        merge_sort(left_half)
        
        # Recursively type the second half
        merge_sort(right_half)
        
        # Initialize pointers for left_half, right_half and merged array
        i = j = okay = 0
        
        # Merge the sorted halves
        whereas i < len(left_half) and j < len(right_half):
            if left_half(i) < right_half(j):
                arr(okay) = left_half(i)
                i += 1
            else:
                arr(okay) = right_half(j)
                j += 1
            okay += 1
        
        # Examine for any remaining components in left_half
        whereas i < len(left_half):
            arr(okay) = left_half(i)
            i += 1
            okay += 1
        
        # Examine for any remaining components in right_half
        whereas j < len(right_half):
            arr(okay) = right_half(j)
            j += 1
            okay += 1

# Instance utilization
arr = (12, 11, 13, 5, 6, 7)
merge_sort(arr)
print("Sorted array is:", arr)

3. Schnelle Sortierung

Algorithmusschritte

Wählen Sie einen Pivot:

  • Wählen Sie ein Pivot-Factor aus dem Array aus. Dies kann das erste, das letzte, das mittlere oder ein beliebiges Factor sein.

Partitionierung:

  • Ordnen Sie die Elemente im Array so an, dass alle Elemente, die kleiner als der Pivot sind, auf der linken Seite und alle Elemente, die größer als der Pivot sind, auf der rechten Seite liegen. Das Pivot-Factor wird an der richtigen Place im sortierten Array platziert.

QuickSort rekursiv anwenden:

  • Wenden Sie die obigen Schritte rekursiv auf die linken und rechten Unterarrays an.

Basisfall:

  • Wenn das Array nur ein Factor hat oder leer ist, ist es bereits sortiert und die Rekursion endet.

Code-Implementierung

def quick_sort(arr):
    # Base case: if the array is empty or has one aspect, it is already sorted
    if len(arr) <= 1:
        return arr
    
    # Selecting the pivot (Right here, we select the final aspect because the pivot)
    pivot = arr(-1)
    
    # Parts lower than the pivot
    left = (x for x in arr(:-1) if x <= pivot)
    
    # Parts larger than the pivot
    proper = (x for x in arr(:-1) if x > pivot)
    
    # Recursively apply quick_sort to the left and proper sub-arrays
    return quick_sort(left) + (pivot) + quick_sort(proper)

# Instance utilization:
arr = (10, 7, 8, 9, 1, 5)
sorted_arr = quick_sort(arr)
print(f"Sorted array: {sorted_arr}")

4. Dijkstras Algorithmus

Algorithmusschritte

Initialisieren:

  • Setzen Sie den Abstand zum Quellknoten auf 0 und zu allen anderen Knoten auf unendlich ().
  • Markieren Sie alle Knoten als nicht besucht.
  • Legen Sie den Quellknoten als aktuellen Knoten fest.
  • Verwenden Sie eine Prioritätswarteschlange (Min-Heap), um Knoten zusammen mit ihren vorläufigen Entfernungen zu speichern.

Nachbarn erkunden:

  • Überprüfen Sie für den aktuellen Knoten alle seine nicht besuchten Nachbarn.
  • Berechnen Sie für jeden Nachbarn die vorläufige Entfernung vom Quellknoten.
  • Wenn die berechnete Entfernung geringer als die bekannte Entfernung ist, aktualisieren Sie die Entfernung.
  • Fügen Sie den Nachbarn mit der aktualisierten Entfernung in die Prioritätswarteschlange ein.

Wählen Sie den nächsten Knoten aus:

  • Markieren Sie den aktuellen Knoten als besucht (ein besuchter Knoten wird nicht erneut überprüft).
  • Wählen Sie den nicht besuchten Knoten mit der geringsten vorläufigen Distanz als neuen aktuellen Knoten aus.

Wiederholen:

  • Wiederholen Sie die Schritte 2 und 3, bis alle Knoten besucht wurden oder die Prioritätswarteschlange leer ist.

Ausgabe:

  • Der Algorithmus gibt die kürzeste Distanz vom Quellknoten zu jedem Knoten im Diagramm aus.

Code-Implementierung

import heapq

def dijkstra(graph, begin):
    # Initialize distances and precedence queue
    distances = {node: float('infinity') for node in graph}
    distances(begin) = 0
    priority_queue = ((0, begin))  # (distance, node)

    whereas priority_queue:
        current_distance, current_node = heapq.heappop(priority_queue)

        # If the popped node's distance is bigger than the recognized shortest distance, skip it
        if current_distance > distances(current_node):
            proceed

        # Discover neighbors
        for neighbor, weight in graph(current_node).objects():
            distance = current_distance + weight

            # If discovered a shorter path to the neighbor, replace it
            if distance < distances(neighbor):
                distances(neighbor) = distance
                heapq.heappush(priority_queue, (distance, neighbor))

    return distances

# Instance utilization:
graph = {
    'A': {'B': 1, 'C': 4},
    'B': {'A': 1, 'C': 2, 'D': 5},
    'C': {'A': 4, 'B': 2, 'D': 1},
    'D': {'B': 5, 'C': 1}
}

start_node="A"
distances = dijkstra(graph, start_node)

print("Shortest distances from node", start_node)
for node, distance in distances.objects():
    print(f"Node {node} has a distance of {distance}")

5. Breitensuche (BFS)

ist eine Technik zum Durchlaufen oder Durchsuchen von Baum- oder Graphendatenstrukturen. Dieser Graphenalgorithmus verwendet eine Baumsuchstrategie; er beginnt mit einem beliebigen Knoten oder Wurzelknoten und verzweigt sich zu allen Randknoten und dann zu allen Knoten auf der nächsten Ebene. Dieser Algorithmus für Datenstrukturen in Python wird für kurze Distanzen in ungewichteten Graphen verwendet. Durchläufe sind

Algorithmusschritte

Initialisieren:

  • Erstellen einer leeren Warteschlange q.
  • Den Startknoten in die Warteschlange einreihen s hinein q.
  • Markieren Sie den Startknoten s wie besucht.

Schleife, bis die Warteschlange leer ist:

  • Einen Knoten aus der Warteschlange entfernen v aus q.
  • Für jeden nicht besuchten Nachbarn n von v:
    • Markieren n wie besucht.
    • In die Warteschlange einreihen n hinein q.

Wiederholen Sie Schritt 2, bis die Warteschlange leer ist.

Beenden Sie den Vorgang sobald alle Knoten auf allen Ebenen besucht wurden.

Code-Implementierung

from collections import deque

def bfs(graph, begin):
    # Create a queue for BFS
    queue = deque((begin))
    
    # Set to retailer visited nodes
    visited = set()
    
    # Mark the beginning node as visited
    visited.add(begin)
    
    # Traverse the graph
    whereas queue:
        # Dequeue a vertex from the queue
        node = queue.popleft()
        print(node, finish=" ")
        
        # Get all adjoining vertices of the dequeued node
        # If an adjoining vertex hasn't been visited, mark it as visited and enqueue it
        for neighbor in graph(node):
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)

# Instance utilization:
graph = {
    'A': ('B', 'C'),
    'B': ('D', 'E'),
    'C': ('F', 'G'),
    'D': (),
    'E': (),
    'F': (),
    'G': ()
}

bfs(graph, 'A')

6. Tiefensuche (DFS)

Algorithmusschritte

Initialisierung:

  • Erstellen Sie einen Stapel (oder verwenden Sie Rekursion), um den Überblick über die zu besuchenden Knoten zu behalten.
  • Markieren Sie alle Knoten als unbesucht (oder initialisieren Sie einen visited Satz).

Beginnen Sie beim Quellknoten:

  • Schieben Sie den Quellknoten auf den Stapel und markieren Sie ihn als besucht.

Knoten verarbeiten, bis der Stapel leer ist:

  • Einen Knoten aus dem Stapel entfernen (aktueller Knoten).
  • Verarbeiten Sie den aktuellen Knoten (z. B. drucken Sie ihn, speichern Sie ihn usw.).
  • Für jeden nicht besuchten Nachbarn des aktuellen Knotens:
    • Markieren Sie den Nachbarn als besucht.
    • Schieben Sie den Nachbarn auf den Stapel.

Wiederholen Sie den Vorgang, bis der Stapel leer ist.

Code-Implementierung

def dfs_iterative(graph, begin):
    visited = set()  # To maintain monitor of visited nodes
    stack = (begin)  # Initialize the stack with the beginning node

    whereas stack:
        # Pop the final aspect from the stack
        node = stack.pop()

        if node not in visited:
            print(node)  # Course of the node (e.g., print it)
            visited.add(node)  # Mark the node as visited

            # Add unvisited neighbors to the stack
            for neighbor in graph(node):
                if neighbor not in visited:
                    stack.append(neighbor)

# Instance utilization:
graph = {
    'A': ('B', 'C'),
    'B': ('D', 'E'),
    'C': ('F'),
    'D': (),
    'E': ('F'),
    'F': ()
}

dfs_iterative(graph, 'A')

7. Hashen

Algorithmusschritte

Eingang: Ein Datenelement (z. B. Zeichenfolge, Zahl).Wählen Sie eine Hash-Funktion: Wählen Sie eine Hash-Funktion aus, die Eingabedaten einem Hash-Wert (häufig eine Ganzzahl) zuordnet.Hash-Wert berechnen:

  • Wenden Sie die Hash-Funktion auf die Eingabedaten an, um den Hash-Wert zu erhalten.

Einfügen oder Nachschlagen:

  • Einfügung: Speichern Sie die Daten in einer Hash-Tabelle und verwenden Sie den Hash-Wert als Index.
  • Nachschlagen: Verwenden Sie den Hashwert, um die Daten schnell in der Hashtabelle zu finden.

Kollisionen behandeln:

  • Wenn zwei verschiedene Eingaben denselben Hash-Wert erzeugen, verwenden Sie eine Methode zur Kollisionsauflösung, z. B. Verkettung (Speichern mehrerer Elemente am selben Index) oder offene Adressierung (Suchen eines anderen freien Steckplatzes).

Code-Implementierung

class HashTable:
    def __init__(self, measurement):
        self.measurement = measurement
        self.desk = (() for _ in vary(measurement))
    
    def hash_function(self, key):
        # A easy hash operate
        return hash(key) % self.measurement
    
    def insert(self, key, worth):
        hash_key = self.hash_function(key)
        key_exists = False
        bucket = self.desk(hash_key)
        
        for i, kv in enumerate(bucket):
            okay, v = kv
            if key == okay:
                key_exists = True
                break
        
        if key_exists:
            bucket(i) = (key, worth)  # Replace the present key
        else:
            bucket.append((key, worth))  # Insert the brand new key-value pair
    
    def get(self, key):
        hash_key = self.hash_function(key)
        bucket = self.desk(hash_key)
        
        for okay, v in bucket:
            if okay == key:
                return v
        return None  # Key not discovered
    
    def delete(self, key):
        hash_key = self.hash_function(key)
        bucket = self.desk(hash_key)
        
        for i, kv in enumerate(bucket):
            okay, v = kv
            if okay == key:
                del bucket(i)
                return True
        return False  # Key not discovered

# Instance utilization:
hash_table = HashTable(measurement=10)

# Insert information into the hash desk
hash_table.insert("apple", 10)
hash_table.insert("banana", 20)
hash_table.insert("orange", 30)

# Retrieve information from the hash desk
print(hash_table.get("apple"))   # Output: 10
print(hash_table.get("banana"))  # Output: 20

# Delete information from the hash desk
hash_table.delete("apple")
print(hash_table.get("apple"))   # Output: None

Lesen Sie auch: Möglichkeiten zum Berechnen von Hashing in Datenstrukturen

Abschluss

Die Beherrschung von Algorithmen in Verbindung mit Datenstrukturen ist für jeden Python-Entwickler, der effizienten und skalierbaren Code schreiben möchte, unerlässlich. Diese Algorithmen sind grundlegende Werkzeuge, die die Datenverarbeitung optimieren, die Leistung verbessern und komplexe Probleme in verschiedenen Anwendungen lösen. Durch das Verstehen und Implementieren dieser Algorithmen können Entwickler das volle Potenzial der Datenstrukturen von Python freisetzen, was zu effektiveren und robusteren Softwarelösungen führt.

Lesen Sie auch: Vollständiger Leitfaden zu Sortiertechniken in Python (Ausgabe 2024)

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert