Heim > Backend-Entwicklung > PHP-Tutorial > Besprechen Sie, wie PHP Hash-Konflikte löst

Besprechen Sie, wie PHP Hash-Konflikte löst

PHPz
Freigeben: 2023-04-11 16:44:01
Original
956 Leute haben es durchsucht

In der Programmierung ist die Hash-Tabelle eine sehr nützliche Datenstruktur. Es kann Elemente in O(1)-Zeit finden und einfügen, aber die Hash-Funktion kann Hash-Kollisionen verursachen, ein Problem, das auftritt, wenn zwei verschiedene Schlüsselwerte demselben Index zugeordnet werden. In diesem Artikel werden wir verschiedene Möglichkeiten zur Lösung von Hash-Kollisionsproblemen und deren Implementierung in PHP untersuchen.

  1. Kettenadressmethode
    Die Kettenadressmethode ist eine der einfachsten und gebräuchlichsten Methoden zur Lösung von Hash-Konflikten. Bei der Kettenadressmethode verweist jeder Hash-Tabellenplatz auf eine verknüpfte Liste, wobei jeder Knoten ein Schlüssel-Wert-Paar enthält. Wenn eine Hash-Kollision auftritt, wird an dieser Position ein neues Element zur verknüpften Liste hinzugefügt. Wenn Sie nach einem Element suchen, müssen Sie nur die verknüpfte Liste durchlaufen, um den Knoten zu finden.

In PHP können wir Arrays verwenden, um die Kettenadressmethode zu implementieren. Hier ist zum Beispiel eine einfache Implementierung:

class Hashtable {
    private $table = array();
  
    public function put($key, $value) {
        $hash = $this->hashFunction($key);
        if (!isset($this->table[$hash])) {
            $this->table[$hash] = array();
        }
        foreach ($this->table[$hash] as &$v) {
            if ($v['key'] == $key) {
                $v['value'] = $value;
                return;
            }
        }
        $this->table[$hash][] = array('key' => $key, 'value' => $value);
    }
  
    public function get($key) {
        $hash = $this->hashFunction($key);
        if (isset($this->table[$hash])) {
            foreach ($this->table[$hash] as $v) {
                if ($v['key'] == $key) {
                    return $v['value'];
                }
            }
        }
        return null;
    }
  
    private function hashFunction($key) {
        return crc32($key); // 简单的哈希函数
    }
}
Nach dem Login kopieren

In diesem Beispiel definieren wir eine Hash-Tabellenklasse Hashtable. Es verwendet die crc32-Hash-Funktion, um den Hash-Wert jedes Schlüssels zu berechnen, und speichert die Schlüssel-Wert-Paare in einem zweidimensionalen Array. Wenn ein Element gefunden oder eingefügt werden muss, berechnen wir zunächst seinen Hashwert und prüfen dann, ob der Ort, an dem sich der Hashwert befindet, bereits existiert. Wenn es nicht existiert, erstellen wir eine neue Liste und fügen das Element der Liste hinzu. Wenn die Position bereits vorhanden ist, durchlaufen wir die Liste, suchen das dem Schlüssel entsprechende Element und ersetzen den Wert. Diese Implementierung ist sehr einfach, aber wenn die Größe der Hash-Tabelle zunimmt, kann die Länge der verknüpften Liste sehr groß werden, was sich auf die Effizienz der Suche auswirkt.

  1. Offene Adressierung
    Offene Adressierung ist eine weitere Möglichkeit, Hash-Kollisionen aufzulösen. Wenn bei der offenen Adressierung eine Hash-Kollision auftritt, suchen wir, anstatt der verknüpften Liste ein neues Element hinzuzufügen, weiterhin nach einem freien Slot, beginnend an der ursprünglichen Position, und fügen das Element an der ersten verfügbaren Position ein. Der Vorteil dieser Methode besteht darin, dass keine verknüpfte Liste erforderlich ist und die Speichernutzung reduziert werden kann.

In PHP können wir Arrays verwenden, um eine offene Adressierung zu implementieren. Hier ist zum Beispiel eine einfache Implementierung:

class Hashtable {
    private $table = array();
  
    public function put($key, $value) {
        $i = $this->hashFunction($key);
        $j = $i;
        do {
            if (!isset($this->table[$j])) {
                $this->table[$j] = array('key' => $key, 'value' => $value);
                return;
            }
            if ($this->table[$j]['key'] == $key) {
                $this->table[$j]['value'] = $value;
                return;
            }
            $j = ($j + 1) % count($this->table);
        } while ($j != $i);
    }
  
    public function get($key) {
        $i = $this->hashFunction($key);
        $j = $i;
        do {
            if (isset($this->table[$j])) {
                if ($this->table[$j]['key'] == $key) {
                    return $this->table[$j]['value'];
                }
            } else {
                return null;
            }
            $j = ($j + 1) % count($this->table);
        } while ($j != $i);
        return null;
    }
  
    private function hashFunction($key) {
        return crc32($key); // 简单的哈希函数
    }
}
Nach dem Login kopieren

In diesem Beispiel definieren wir eine weitere Hash-Tabellenklasse Hashtable, die die crc32-Hash-Funktion verwendet, um den Hash-Wert jedes Schlüssels zu berechnen und die Schlüssel-Wert-Paare eindimensional zu speichern Array. Wenn ein Element gefunden oder eingefügt werden muss, berechnen wir zunächst seinen Hashwert und beginnen von dieser Position aus mit dem Durchlaufen des Arrays. Wenn die Position leer ist, fügen wir das neue Element an dieser Position ein. Wenn die Position bereits belegt ist, durchlaufen wir das Array so lange, bis wir eine freie Position finden oder das gesamte Array durchlaufen. Ein Nachteil dieser Implementierung besteht darin, dass bei zunehmender Größe der Hash-Tabelle der Speicher neu zugewiesen und vorhandene Elemente in ein neues Array kopiert werden müssen.

  1. Double Hashing
    Double Hashing ist eine Methode, die mithilfe einer Hash-Funktion eine Reihe von Hash-Werten erzeugt, um im Falle einer Hash-Kollision eine neue Position zu finden. Beim Doppel-Hashing verwenden wir zwei verschiedene Hash-Funktionen, um den Hash-Wert jedes Schlüssels zu berechnen und der Reihenfolge der Hash-Werte zu folgen, um eine leere Position zu finden. Durch die Verwendung mehrerer Hash-Funktionen wird die Anzahl der Hash-Kollisionen reduziert und die Sucheffizienz verbessert.

In PHP können wir Arrays verwenden, um doppeltes Hashing zu implementieren. Hier ist zum Beispiel eine einfache Implementierung:

class Hashtable {
    private $table = array();
  
    public function put($key, $value) {
        $i = $this->hashFunction1($key);
        $j = $this->hashFunction2($key);
        $k = $i;
        do {
            if (!isset($this->table[$k])) {
                $this->table[$k] = array('key' => $key, 'value' => $value);
                return;
            }
            if ($this->table[$k]['key'] == $key) {
                $this->table[$k]['value'] = $value;
                return;
            }
            $k = ($k + $j) % count($this->table);
        } while ($k != $i);
    }
  
    public function get($key) {
        $i = $this->hashFunction1($key);
        $j = $this->hashFunction2($key);
        $k = $i;
        do {
            if (isset($this->table[$k])) {
                if ($this->table[$k]['key'] == $key) {
                    return $this->table[$k]['value'];
                }
            } else {
                return null;
            }
            $k = ($k + $j) % count($this->table);
        } while ($k != $i);
        return null;
    }
  
    private function hashFunction1($key) {
        return crc32($key);
    }
  
    private function hashFunction2($key) {
        return ((int)(crc32($key) / count($this->table)) + 1) % count($this->table);
    }
}
Nach dem Login kopieren

In diesem Beispiel definieren wir eine andere Hash-Tabellenklasse Hashtable, die zwei Hash-Funktionen verwendet, um den Hash-Wert jedes Schlüssels zu berechnen und das Schlüssel-Wert-Paar zu kombinieren. In einem eindimensionalen Array gespeichert . Wenn ein Element gefunden oder eingefügt werden muss, berechnen wir zunächst seinen Hash-Wert und verwenden den ersten Hash-Wert als Anfangsposition und den zweiten Hash-Wert, um die Schrittgröße jeder Suche zu berechnen. Wenn die Position leer ist, fügen wir das neue Element an dieser Position ein. Wenn die Position bereits belegt ist, durchlaufen wir das Array so lange, bis wir eine freie Position finden oder das gesamte Array durchlaufen. Ein Vorteil dieser Implementierung besteht darin, dass die Verwendung zweier verschiedener Hash-Funktionen die Anzahl der Hash-Kollisionen reduzieren kann, während die Verwendung der zweiten Hash-Funktion das Auftreten von „Clustering“-Situationen reduzieren kann.

Fazit
Die Implementierung einer Hash-Tabelle in PHP ist eine unterhaltsame und nützliche Übung. Während der Code-Implementierung haben wir drei häufig verwendete Methoden zur Lösung von Hash-Konflikten gesehen: die Kettenadressmethode, die offene Adressierungsmethode und die Doppel-Hash-Methode. Jede Methode hat ihre Vor- und Nachteile, und wir sollten die Methode wählen, die am besten zum aktuellen Anwendungsszenario passt.

Abschließend müssen wir beachten, dass Hash-Tabellen zwar bei Such- und Einfügevorgängen sehr effizient sind, ihre Leistung jedoch stark abnimmt, wenn der Auslastungsfaktor der Hash-Tabelle zu hoch ist. Daher müssen wir beim Einfügen von Elementen den Auslastungsfaktor überprüfen und bei Bedarf Speicher neu zuweisen, um einen effizienten Betrieb der Hash-Tabelle sicherzustellen.

Das obige ist der detaillierte Inhalt vonBesprechen Sie, wie PHP Hash-Konflikte löst. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage