Fragen über Hashing

Annalena123

Aktives Mitglied
Hallo, ich weiß nicht genau wie man mit Hashverfahren etwas im Array zufügt !Soweit habe ich private ArrayList<WortListe> _wortliste ; _wortliste=new ArrayList(groesse); zugefügt und
Code:
 public void fuegeWortHinzu(String wort)

    {

        _berechner.hashWert(wort);

        _wortliste.add(_berechner.hashWert(wort));

    }
geschrieben ! Kann jemand bitte mir weiterhelfen ?
Die Aufgabe ist :
Vervollständigt nun die Klasse HashWortschatz, indem ihr ein Hash-Verfahren implementiert. Für die Hashwertberechnung steht (über einen Konstruktor-Parameter) eine Implementierung des Interfaces HashWertBerechner bereit. Die Angabe eines Berechners erlaubt die Verwendung verschiedener HashFunktionen. Denkt daran, dass der von der Hash-Funktion gelieferte Wert noch auf die Größe der Tabelle angepasst werden muss, um einen gültigen Index in die Tabelle zu erhalten. Das ist in mehreren Methoden nötig, beispielsweise in fuegeWortHinzu.Verwendet als Überlaufbehälter Exemplare der mitgelieferten Klasse WortListe. Eure Hash-Tabelle soll also ein Array von WortListen sein. Die Größe dieser Hash-Tabelle bekommt eure Implementierung über den Konstruktor von HashWortschatz als zweiten Parameter übergeben.
Java:
class HashWortschatz implements Wortschatz
{
    private final HashWertBerechner _berechner;
 
     private ArrayList<WortListe> _wortliste ;
    /**
     * Initialisiert ein neues Exemplar von HashWortschatz.
     *
     * @param berechner der Berechner, welcher die Hashfunktion umsetzt
     * @param groesse die (initiale) Groesse der Hashtabelle
     */
    public HashWortschatz(HashWertBerechner berechner, int groesse)
    {
        _berechner = berechner;

        _wortliste=new ArrayList(groesse);
 
    }
 
    /**
     * Fuege ein Wort zum Wortschatz hinzu, sofern es noch nicht enthalten ist.
     *
     * @param wort das hinzuzufuegende Wort
     */
    public void fuegeWortHinzu(String wort)
    {
        _berechner.hashWert(wort);
        _wortliste.add(_berechner.hashWert(wort));
    }
/**
     * Gib an, ob ein Wort im Wortschatz enthalten ist.
     *
     * @param wort das zu ueberpruefende Wort
     * @return true, falls das Wort enthalten ist, false sonst
     */
    public boolean enthaeltWort(String wort)
    {
        return false;
    }
 
    /**
     * Gib an, wieviele Woerter im Wortschatz enthalten sind.
     *
     * @return die Anzahl der Woerter im Wortschatz
     */
    public int anzahlWoerter()
    {
        return 0;
    }

    /**
     * Diese Beschreibung dient zur Unterscheidung beim Messen.
     */
    public String gibBeschreibung()
    {
        return _berechner.gibBeschreibung();
    }

    /**
     * Schreibt den Wortschatz auf die Konsole (als Debugging-Hilfe gedacht).
     */
    public void schreibeAufKonsole()
    {
    }
}

Das ist die Klasse WortListe
Code:
class WortListe implements Iterable<String>
{
    private final List<String> _liste;

    /**
     * Konstruktor fuer Objekte der Klasse WortListe
     */
    public WortListe()
    {
        _liste = new ArrayList<String>();
    }

    /**
     * Fuege der Liste ein Wort hinzu.
     * @param wort das hinzuzufuegende Wort
     */
    public void fuegeWortHinzu(String wort)
    {
        _liste.add(wort);
    }

    /**
     * Loesche ein Wort aus der Liste.
     * @param wort das zu loeschende Wort
     * @return true, sofern das Wort vorher enthalten war und somit entfernt wurde, false sonst
     */
    public boolean entferneWort(String wort)
    {
        return _liste.remove(wort);
    }
 
    /**
     * Pruefe, ob das Wort in der Liste enthalten ist.
     * @param wort das zu ueberpruefende Wort
     * @true, falls das Wort in der Liste enthalten ist
     */
    public boolean enthaeltWort(String wort)
    {
        return _liste.contains(wort);
    }
 
    /**
     * Gib die Anzahl der Woerter in der Liste.
     * @return die Anzahl der Woerter in der Liste
     */
    public int anzahlWoerter()
    {
        return _liste.size();
    }

    /**
     * Liefere das Wort mit dem Index index.
     * @param index der Index
     * @return das Wort zu dem index
     */
    public String gibWort(int index)
    {
        return _liste.get(index);
    }
 
    /**
     * Liefere einen Iterator ueber die Liste der Woerter.
     * @return den Iterator
     */
    public Iterator<String> iterator()
    {
        return _liste.iterator();
    }
 
    /**
     * Liefere eine String-Repraesentation der Liste.
     * @return eine String-Repraesentation der Liste
     */
    public String toString()
    {
        String s = "";
        for(String wort : _liste)
        {
                s += wort +  " ";
        }
   
        return s;
    }
}
und diese Klassen(Delegation,zweiBuchstaben,Laenge) implementieren HashWertBerechner
Code:
/**
 * Delegiert die Berechnung an das String-Objekt.
 */
class Delegation implements HashWertBerechner
{
    /**
     * @see HastWertBerechner.hashWert
     */
    public int hashWert(String wort)
    {
        return wort.hashCode();
    }
 
    /**
     * @see HastWertBerechner.gibBeschreibung
     */
    public String gibBeschreibung()
    {
        return "Delegiert die Berechnung an das String-Objekt";
    }
}
/**
 * Berechnet den HashWert aus dem ersten und letzten Buchstaben.
 */
class ZweiBuchstaben implements HashWertBerechner
{
    /**
     * @see HastWertBerechner.hashWert
     */
    public int hashWert(String wort)
    {
        return wort.charAt(0) * 123456791 + wort.charAt(wort.length() - 1);
    }
 
    /**
     * @see HastWertBerechner.gibBeschreibung
     */
    public String gibBeschreibung()
    {
        return "Berechnet den HashWert aus dem ersten und letzten Buchstaben";
    }
}

/**
 * Liefert die Laenge des Strings als HashWert.
 */
class Laenge implements HashWertBerechner
{
    /**
     * @see HastWertBerechner.hashWert
     */
    public int hashWert(String wort)
    {
        return wort.length();
    }
 
    /**
     * @see HastWertBerechner.gibBeschreibung
     */
    public String gibBeschreibung()
    {
        return "Liefert die Laenge des Strings als HashWert";
    }
}
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Soweit habe ich private ArrayList<WortListe> _wortliste ; _wortliste=new ArrayList(groesse); zugefügt
Was schon einmal nicht der Anforderung entspricht, dass wortliste ein Array (keine ArrayList) sein soll.

_wortliste.add(_berechner.hashWert(wort));
_wortliste enthält mehrere Wortlisten (weshalb der Bezeichner im Plural die bessere Wahl wäre) und Du versuchst jetzt, einen Hashwert statt einer Wortliste hinzuzufügen. Das kann nicht funktionieren.

Überlege Dir mal, was da eigentlich passieren soll: Du sollst anhand eines Hashwerts den Index der Wortliste berechnen, der Du den Eintrag hinzufügen willst.
 

Annalena123

Aktives Mitglied
Was schon einmal nicht der Anforderung entspricht, dass wortliste ein Array (keine ArrayList) sein soll.


_wortliste enthält mehrere Wortlisten (weshalb der Bezeichner im Plural die bessere Wahl wäre) und Du versuchst jetzt, einen Hashwert statt einer Wortliste hinzuzufügen. Das kann nicht funktionieren.

Überlege Dir mal, was da eigentlich passieren soll: Du sollst anhand eines Hashwerts den Index der Wortliste berechnen, der Du den Eintrag hinzufügen willst.
Danke für Deine Antwort !Was meinst Du mit _wortliste enthält mehrere Wortlisten ! WortListe hat doch nur ein _list als Zustansfeld;?
ich habe jetzt so geschrieben
Code:
private WortListe[] _wortlisten
Ich habe so verstanden , dass an einem index auch mehrere Wörter , die gleiche Hashcode haben , an dem selben index zugefügt werden können ! Bei jeder index ist nur doch ein Platz für ein Element gedacht oder ? wie kann ich etwas Neues zufügen ohne das Andere zu löschen ?mit Linkedlist oder ?Aber hier muss ich doch nich LinkedListe implementieren .
meine nächste Frage : wenn ich index
Code:
int index =_berechner.hashWert(wort);
so berechnen kann, wie kann ich aber etwas an dieser Position einfügen ?
Code:
_wortlisten[index]=wort;
wenn ich so schreibe bekomme ich so einen Error incompatible Types
 

mihe7

Top Contributor
!Was meinst Du mit _wortliste enthält mehrere Wortlisten ! WortListe hat doch nur ein _list als Zustansfeld;?
Die Variable _wortlisten ist ja nicht einfach vom Typ WortListe, sondern ein WortListe-Array. _wortlisten ist ein Array, das Platz für eine feste Anzahl von Elementen bietet, die vom Typ WortListe sein müssen.

Und genau deswegen bekommst Du auch diesen Fehler:
wenn ich so schreibe bekomme ich so einen Error incompatible Types
_wortlisten[index] greift auf das Element zu, das sich an Position index befindet. Dieses Element muss - wie eben schon geschrieben - vom Typ WortListe sein.

Ich habe so verstanden , dass an einem index auch mehrere Wörter , die gleiche Hashcode haben , an dem selben index zugefügt werden können ! Bei jeder index ist nur doch ein Platz für ein Element gedacht oder ?
Völlig richtig und weil das so ist, verwaltest Du nicht einzelne Wörter im Array sondern eben Worlisten (WortListe-Objekte) :)

wie kann ich etwas Neues zufügen ohne das Andere zu löschen ?mit Linkedlist oder ?
Wenn das Array korrekt initialisiert wurde, erhältst Du mit _wortisten[index] ein Element vom Typ WortListe. Und dieser WortListe fügst Du das Wort hinzu:
Java:
WortListe wortListe = _wortlisten[index]; 
wortListe.fuegeWortHinzu(wort);
 

Annalena123

Aktives Mitglied
Die Variable _wortlisten ist ja nicht einfach vom Typ WortListe, sondern ein WortListe-Array. _wortlisten ist ein Array, das Platz für eine feste Anzahl von Elementen bietet, die vom Typ WortListe sein müssen.

Und genau deswegen bekommst Du auch diesen Fehler:

_wortlisten[index] greift auf das Element zu, das sich an Position index befindet. Dieses Element muss - wie eben schon geschrieben - vom Typ WortListe sein.


Völlig richtig und weil das so ist, verwaltest Du nicht einzelne Wörter im Array sondern eben Worlisten (WortListe-Objekte) :)


Wenn das Array korrekt initialisiert wurde, erhältst Du mit _wortisten[index] ein Element vom Typ WortListe. Und dieser WortListe fügst Du das Wort hinzu:
Java:
WortListe wortListe = _wortlisten[index];
wortListe.fuegeWortHinzu(wort);
Danke für Deine Antwort ! Wenn ich wort einfach mit fuegeWortHinzu() zufügen kann warum brauche ich den Zustandsfeld _berechner ?Ich weiß nur nicht wann und wie ich den _berechner benutzen muss und wie kann ich hier den index oder position hier bestimmen ?WortListe wortListe = _wortlisten[index]?
 

temi

Top Contributor
warum brauche ich den Zustandsfeld _berechner ?Ich weiß nur nicht wann und wie ich den _berechner benutzen muss
In _berechner ist eine konkrete Instanz eines HashWertBerechner gespeichert. Diese (bzw. deren Methode hashWert()) sollst du verwenden, um den Hashwert für ein Wort zu berechnen.

Diese Instanz wird im Konstruktor übergeben und ganz oben sind drei unterschiedliche Implementationen dafür angegeben, die auf jeweils anderer Basis einen Hashwert berechnen (abhängig davon welche Implementation dem Konstruktor zuvor übergeben wurde).
 

Annalena123

Aktives Mitglied
In _berechner ist eine konkrete Instanz eines HashWertBerechner gespeichert. Diese (bzw. deren Methode hashWert()) sollst du verwenden, um den Hashwert für ein Wort zu berechnen.

Diese Instanz wird im Konstruktor übergeben und ganz oben sind drei unterschiedliche Implementationen dafür angegeben, die auf jeweils anderer Basis einen Hashwert berechnen (abhängig davon welche Implementation dem Konstruktor zuvor übergeben wurde).
Danke Für Deine Antwort !Ja das habe ich verstanden , aber was muss dann passieren wenn man das berechnet ?Es wird doch nichts an _wortlisten danach etwas übermittelt! Und wie kann ich position hier _wortlisten[index] bestimmen ?
Java:
  public void fuegeWortHinzu(String wort)
    {
      
        int hashwert =_berechner.hashWert(wort);
      
         _wortlisten[index].fuegeWortHinzu(wort);
        
    
        
    }
 

temi

Top Contributor
Aus dem Hashwert ermittelst du den Index der gespeicherten Wortliste. Mit dem Index der Wortliste kannst du dieser Liste anschließend das entsprechende Wort hinzufügen.

Die Aufgabe ist es nun den erhaltenen Hashwert einem Index zuzuordnen. Naiv gedacht könntest du z. B. einfach den höchsten möglichen Hashwert durch die Anzahl der Wortlisten (die Größe des Arrays) teilen und damit den jeweiligen Hashwert einem Index zuordnen.
 
Zuletzt bearbeitet:

Annalena123

Aktives Mitglied
Aus dem Hashwert ermittelst du den Index der gespeicherten Wortliste. Mit dem Index der Wortliste kannst du dieser Liste anschließend das entsprechende Wort hinzufügen.

Die Aufgabe ist es nun den erhaltenen Hashwert einem Index zuzuordnen. Naiv gedacht könntest du z. B. einfach den höchsten möglichen Hashwert durch die Anzahl der Wortlisten (die Größe des Arrays) teilen und damit den jeweiligen Hashwert einem Index zuordnen.
Java:
   /**
     * Fuege ein Wort zum Wortschatz hinzu, sofern es noch nicht enthalten ist.
     *
     * @param wort das hinzuzufuegende Wort
     */
    public void fuegeWortHinzu(String wort)
    {
        //_berechner.hashWert(wort);
        
        int hashwert =_berechner.hashWert(wort);
        int size=_wortlisten.length;
        int index=hashwert/size;
       
      for(WortListe word :_wortlisten)
      {
            if (word!=null &&  wort!=null  && !(wort.equals(word)))
            {
             _wortlisten[index].fuegeWortHinzu(wort);
           
       
           
        }
       }
}
Ich bekomme jetzt NullPointerException "this._wortlisten[index]" is null
 

mihe7

Top Contributor
Ich bekomme jetzt NullPointerException "this._wortlisten[index]" is null
Ja:
Wenn das Array korrekt initialisiert wurde
Mit new Wortliste[10] erstellst Du z. B. ein Array, das Platz für 10 Wortliste-Objekte bietet. Es ist aber noch keine Wortliste im Array, daher verweisen die Einträge auf "nichts" (null). Es reicht also nicht, nur den Platz zu schaffen, Du musst die Wortlisten schon auch erstellen und in das Array eintragen.
 

Annalena123

Aktives Mitglied
Ja:

Mit new Wortliste[10] erstellst Du z. B. ein Array, das Platz für 10 Wortliste-Objekte bietet. Es ist aber noch keine Wortliste im Array, daher verweisen die Einträge auf "nichts" (null). Es reicht also nicht, nur den Platz zu schaffen, Du musst die Wortlisten schon auch erstellen und in das Array eintragen.
Java:
_wortlisten[index].fuegeWortHinzu(wort);
mit diesem Code will ich dort etwas zufügen damit es nicht leer ist ... aber bevor ich zufüge, muss ich auch die Duplikaten überprüfen , deswegen habe ich die for- schleife mit if- statment geschrieben und das wird problematisch ! es wird iteriert obwohl nichts daran steht für das erste mal ... Ich weiß nicht wie ich genau eintragen kann , kannst du bitte mehr darüber erklären ?
 

KonradN

Super-Moderator
Mitarbeiter
Java:
_wortlisten[index].fuegeWortHinzu(wort);
mit diesem Code will ich dort etwas zufügen damit es nicht leer ist ... aber bevor ich zufüge, muss ich auch die Duplikaten überprüfen , deswegen habe ich die for- schleife mit if- statment geschrieben und das wird problematisch ! es wird iteriert obwohl nichts daran steht für das erste mal ... Ich weiß nicht wie ich genau eintragen kann , kannst du bitte mehr darüber erklären ?
Du musst Dir das doch wirklich einmal Bildlich vorstellen! Du hast ganz offensichtlich die absoluten Grundlagen nicht verstanden! Und das führt zu sinnlosen überprüfungen!

Wie funktioniert denn so eine Einsortierung über Hashcodes in "Buckets"?

Wir machen es einfach einmal ganz trivial: Du hast Worte und willst diese in 26 Ablagen einsortieren. Dazu hast Du ein Hängeregister in das Du 26 von diesen Hängeteilen rein tun kannst. ==> Das ist Dein Array. Das ist also der Stahlschrank mit den Schubladen, die links und rechts so Schinen haben für die Hängetaschen. (Ich hoffe, so ein Hängeregister kennst Du noch? Oder bin ich jetzt zu altmodisch? Such mal nach Hängeregister, wenn Dir sowas nichts sagt!)

Wenn Du nun ein Wort ablegen willst, dann gehst Du hin und nimmst davon den ersten Buchstaben. Das gibt Dir hier das Bucket. Wenn Du also das Wort "Zebrastreifen" ablegen willst, dann hast Du hier das Z.
Das entspricht bei den Objekten den Weg übver Hashcode und dann Modulo Anzahl Buckets -> Das gibt dir dann auch, in welches Bucket das Objekt rein gehört.

Nun machst Du den Schrank auf und schaust als erstes: Gibt es denn da schon die Hängemappe für Z? Am Anfang ist der Schankt leer. Da ist nichts, wo Du einen Zettel rein packen kannst! Du musst also prüfen: Gibt es die Hängemappe für Z? Wenn nicht, dann musst Du erst einmal eine Hängemappe für Z erzeugen.
Das ist also diese null Prüfung. Wenn Du noch keine Wortliste hast (dann ist das Element im Array null), dann musst Du die erst einmal erzeugen!

Wenn Du dann die Hängemappe für Z hast, dann musst Du dir diese Hängemappe nehmen und schauen: Ist da schon ein Zettel mit "Zebrastreifen" drin. Du gehst also die Zettel in der Hängemappe mit Z Worten durch und schaust nach "Zebrastreifen".

Ist das vom Vorgehen her jetzt verstanden?

Denn dann wird Dir hoffentlich klar sein, dass Du nur Quatsch gemacht hast. Du bist die Hängemappen, die in dem Hängeregister durchgegangen und hast geprüft: Ist die Hängemappe ein Zettel mit "Zebrastreifen". Was Quatsch ist! Eine Hängemappe ist eine Hängemappe und kein Zettel!

Also daher einfach noch einmal das, was ich doch wirklich immer sage; Versteh doch erst einmal die fachliche Anforderung! Dann beschreibe es in Worten! Erst wenn Du das verstanden hast kannst Du anfangen mit irgend welchen Codezeilen!
 

Neue Themen


Oben