<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[C++ DoubleHashing]]></title><description><![CDATA[<p>Hallo liebe Leute,</p>
<p>das ist mein erster Eintrag in diesem Forum, also habt ein bisschen Nachsicht mit mir falls etwas nicht funktionieren sollte. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /></p>
<p>Ich programmiere gerade eine Hashtabelle mit Double Hashing mein Problem ist allerdings es klappt irgendwie nicht so wie ich möchte.</p>
<p>1. Das erste Problem liegt in der Exception Defintion der min- &amp; max-Methode<br />
und zwar bekomme ich hier diese Fehlermeldung:<br />
DoubleHashing.h: In member function ‘E DoubleHashing&lt;E&gt;::min() const [with E = TestKey]’:<br />
testcfull.C:1206: instantiated from here<br />
DoubleHashing.h:124: error: no type named ‘Exception’ in ‘class Container&lt;TestKey&gt;’</p>
<p>Dies kann aber meiner Meinung nach nicht sein, weil die Exception-Zeile:</p>
<pre><code>[cpp]throw typename Container&lt;E&gt;::Exception(&quot;DoubleHashing&lt;E&gt;::min(): container empty&quot;);
</code></pre>
<p>[/cpp]</p>
<p>eigentlich in Ordnung sein sollte.</p>
<p>2. Mein zweites Problem findet sich in add:<br />
Hier wird einfach niemals die erste Hashfunktion aufgerufen, sondern immer auf das Linear Probing zurück gegriffen.</p>
<p>3. Ich hoffe meine Frage wirkt nicht zu blöd, aber muss ich in der remove-Methode ebenfalls die Hashfunktionen durchlaufen oder kann ich einfach jeden Wert durchgehen?? Da bin ich mir wirklich nicht sicher.</p>
<p>4. In der apply Methode, also bei ascending und descending wird anscheinend auf einen unerwünschten Speicher im Hauptspeicher zugegriffen.</p>
<p>Kann mir jemand weiterhelfen, bzw. einen Tipp für zumindest eine der Problematiken geben?</p>
<p>PS: DoubleHashing.h habe ich selbst erstellt; Container.h wurde mir vorgegeben und wird nicht verändert, bzw. simpelest.cpp ist das zugehörige, ebenfalls vorgegebene Testprogramm.</p>
<p>Meine erstellte Klasse:</p>
<pre><code>[cpp]
#ifndef DOUBLEHASHING_H
#define DOUBLEHASHING_H

#include &lt;iostream&gt;
#include &quot;Container.h&quot;

template &lt;typename E&gt;
class DoubleHashing : public Container&lt;E&gt; {

  class HashElements {
  public:
    unsigned int key;
    E element;
    int status;

    /*Konstruktor*/
    HashElements() : element() {
      key = 0;
      status = 0;
    }

    /*Destruktor*/
    ~HashElements() {/*delete [] element;*/}

    /*Hilfsfunktion fuer add*/
    void fill(const E a, unsigned int schluessel) {
      element = a;
      key = schluessel;
      status = 1;
    }

  };

  HashElements *value;
  size_t maxV; //maximal moegliche Eintraege
  size_t entries;//tatsaechliche Eintragsanzahl

  public:

    //TO DO: PROBLEMBESCHREIBUNG SIEHE METHODE
    using Container&lt;E&gt;::add; //add-Methode
    virtual void add (const E*e, size_t s);
    //void add_single (const E&amp; e);
    void selectionSort(E* newHash, size_t traversePosition) const;
    virtual size_t apply (const Functor&lt;E&gt;&amp;, Order=dontcare) const;

    //implemented
    virtual ~DoubleHashing&lt;E&gt;(); //Destruktor
    virtual std::ostream&amp; print(std::ostream&amp; o) const; //print
    virtual bool member (const E&amp; e) const; //member-Methode
    using Container &lt;E&gt;::remove;
    virtual void remove(const E[], size_t);
    virtual E min() const;
    virtual E max() const;
     //void expand();
    //void swap(E&amp; object1, E&amp; object2) const;
    virtual size_t size() const {
      //liefert tatsaechliche Eintragszahl des Hashing-Verfahrens zurueck
      return entries;
    }

    virtual bool empty() const {
      if(entries!=0) {
        return false;
      }

      else {
        return true;
      }  
    }

    DoubleHashing&lt;E&gt;() {
      entries = 0;
      maxV = 7;
      value = new HashElements[7];
  }
};

  bool isprim(int number) {
    int temp = 2;
    for(; temp&lt;number; ++temp) {
      if(number%temp == 0) {
        return false;
      }
    }

    return true;
  }

  int prim(int number) {
    int next = number+1;
    int last = number*2;
    while(next &lt; last) {
        if(isprim(next) == true) {
          return next;
        }

        else {
          last++;
        }

        next++;
    } 
  }

      //Methode liefert kleinsten Wert des Hashing-Verfahrens zurueck
  template &lt;typename E&gt;
  E DoubleHashing&lt;E&gt;::min() const {
    E minimum;  
    if(entries!=0) {
        minimum = value[0].element;
        for(size_t i=0; i&lt;maxV; i++) {
          if(minimum &gt; value[i].element &amp;&amp; value[i].status==1) {
            minimum = value[i].element;
          }
        }

        return minimum;
      }

      else {
        throw typename Container&lt;E&gt;::Exception(&quot;DoubleHashing&lt;E&gt;::min(): container empty&quot;);
      }
    } 

    //Methode liefert groessten Wert des Hashing-Verfahrens zurueck
    template &lt;typename E&gt;
    E DoubleHashing&lt;E&gt;::max() const {
      E maximum;
      if(entries==0) {
        throw Container&lt;E&gt;::Exception(&quot;DoubleHashing&lt;E&gt;::max(): container empty&quot;);
      }
      else {
        maximum = value[0].element;
        for(size_t i=0; i&lt;maxV; i++) {
          if(value[i].element &gt; maximum &amp;&amp; value[i].status==1) {
            maximum = value[i].element;
          }
        }

        return maximum;
      }
    }

  template&lt;typename E&gt;
  DoubleHashing&lt;E&gt;::~DoubleHashing() {
    delete[]value;
  }

  //Problem: rehashing nach Vergroesserung
  //Problem_2: es werden nicht alle Werte hinzugefuegt
  template&lt;typename E&gt;
  void DoubleHashing&lt;E&gt;::add(const E e[], size_t len) {
    size_t newMax=maxV;
    size_t tempMax;
    unsigned int temp =0;
    HashElements *neu;

    if((entries+len) &gt; ((newMax) * 0.7)) {
      HashElements *expand;
      do {
        newMax = prim(newMax);
      } while(newMax &lt; ((entries+len)*10));

      expand = new HashElements[newMax];

      for(size_t i=0; i&lt;maxV; ++i) {
          if(value[i].status==1) {
              temp = value[i].key % newMax;
              if(expand[temp].status==0) {
                expand[temp].fill(value[i].element, value[i].key);  
              }

              else {
                tempMax = newMax;
                for(size_t k=(temp+1); k&lt;tempMax; ++k) {
                  if(expand[k].status == 0) {
                    expand[k].fill(value[i].element, value[i].key);
                    k=k+newMax;
                  }

                  if(k==newMax-1) {
                    k=0;
                    tempMax = temp;
                  }
                }
              }
            }

        }

      delete[] value;
      value = expand;
      maxV = newMax;
      }

      for(size_t j=0; j&lt;len; ++j) {
        if(!member(e[j])) {
          temp = hashValue(e[j]) % maxV;
          neu = &amp;value[temp];
          if(neu-&gt;status==0) {
            value[temp].fill(e[j],hashValue(e[j]));
            entries++;
          }

          else {
            for(size_t i=temp%maxV; i&lt;maxV; ++i) {
              neu = &amp;value[i];
              if(neu-&gt;status==0) {
                value[i].fill(e[j],hashValue(e[j]));
                i=i+maxV;
                entries++;
              }
            }
          }
        }
      }
    }

  template&lt;typename E&gt;
  bool DoubleHashing&lt;E&gt;::member(const E&amp; e) const {
    unsigned int pos = hashValue(e) % maxV;
    unsigned int temp = maxV;
    for(unsigned int j=pos; j&lt;temp; ++j) {
		if(value[j].status == 1) {
			if(value[j].element==e) {
				return true;
			}

			if(j==maxV-1) {
				temp = pos;
				j = 0;
			}
		}
    }
    return false;
  }

  template &lt;typename E&gt;
  std::ostream&amp; DoubleHashing&lt;E&gt;::print(std::ostream&amp; o) const {
    HashElements *eintrag;
    o&lt;&lt; &quot;[values= &quot;;
    for (size_t i=0; i&lt;maxV; ++i) {
      eintrag = &amp;value[i];
      o &lt;&lt; ' ' &lt;&lt; eintrag-&gt;element;
      eintrag = 0;
    }
    o &lt;&lt;&quot; ] &quot;;

    return o;
  }

  template&lt;typename E&gt;
  void DoubleHashing&lt;E&gt;::remove(const E e[], size_t s) {
    for(size_t i=0; i&lt;s; i++) {
      for(size_t j=0; j&lt;maxV; j++) {
        if(value[j].element == e[i] &amp;&amp; value[j].status == 1) {
          value[j].status = 0;
          //value[j].element = 0;
          value[j].key = 0;
          --entries;
          break;
        }
      }
    }
  }

  template &lt;typename E&gt;
  size_t DoubleHashing&lt;E&gt;::apply(const Functor &lt;E&gt;&amp; f, Order order) const {
    if(size()&gt;0) {
      //selectionSort array
      E*newHash = new E[entries];
      size_t traversePosition = 0;
      size_t rc = 0;

      for(size_t i=0; i&lt;maxV; i++) {
        //if(value[i].element&gt;0) {
            newHash[traversePosition] = value[i].element;
            traversePosition++;
        //}
      }

      //ToDO: Fehler beim Sortieren  
      if(order==ascending) {
        selectionSort(newHash, traversePosition);
        for(size_t i=0; i&lt;traversePosition; i++) {
          rc++;
          if(!f(newHash[i])) break;
        }
      }

      /*Problem: letzter Wert des Arrays wird nicht ausgegeben */
      if(order==descending) {
        selectionSort(newHash,traversePosition);
        //wenn i&gt;=0 -&gt; dann Zugriff auf nicht zugelassenen Hauptspeicher
        //wenn i&gt;0 -&gt; letzer Wert des Arrays wird nicht ausgegeben
        for(size_t i=traversePosition-1; i&gt;0; i--) {
          rc++;
          if(!f(newHash[i])) break;
        }

      }

      if(order==dontcare) {
        for(size_t i=0; i&lt;traversePosition; i++) {
          rc++;
          if(!f(newHash[i])) break;
        }
      }

      delete [] newHash;
      return rc;
    }
    return 0;
  }

  template &lt;typename E&gt;
  void DoubleHashing&lt;E&gt;::selectionSort(E* newHash, size_t traversePosition) const {
    //E minimum;
    size_t i, j, minIndex; 
    E temp;

    for(i=0; i&lt;traversePosition-1; i++) {
      minIndex = i;
      for(j=i+1; j&lt;traversePosition; j++) {
        if(newHash[minIndex] &gt; newHash[j]) {
          minIndex = j;
        }
      }

      if(minIndex != i) {
        temp = newHash[i];
        newHash[i] = newHash[minIndex];
        newHash[minIndex] = temp;
      }
    }

   /* for(i=0; i&lt;traversePosition-1; i++) {
      elementOne = i;
      minimum = newHash[i];

      for(j=i+1; j&lt;traversePosition; j++) {
        if(minimum &gt; newHash[j]) {
          elementTwo = j;
        }
      }
      swap(newHash[elementOne],newHash[elementTwo]);

    }
    */
  }

#endif
[/cpp]
</code></pre>
<p>Testprogramm:</p>
<pre><code class="language-cpp">// simpletest.C
 // 
 // UE Algorithmen und Datenstrukturen - SS 2012 Universitaet Wien
 // Container - Projekt
 // http://www.pri.univie.ac.at/courses/ADS/ss12/
 //Beim Kompilieren kann mittels Option -DETYPE=&lt;typ&gt; der Elementdatentyp des 
 //Containers festgelegt werden, also zB -DETYPE=Person (Defaulttyp ist int). 
 // Simples Testprogramm zur Ueberpruefung der Container-Funktionalitaet
 // Die Zeichenfolge Hashing ist in der ganzen Datei durch den Klassennamen 
 // der Datenstruktur zu ersetzen.
 // 
 // Der Elementdatentyp kann mit Compileroption -DETYPE=&lt;typ&gt; festgelegt werden,
 // also zb -DETYPE=std::string

 #include &lt;iostream&gt;
 #include &lt;sstream&gt;
 #include &lt;fstream&gt;
 #include &lt;string&gt;
 #include &lt;cstring&gt;
 #include &lt;cstdlib&gt;
 #include &lt;cctype&gt;
 #include &quot;DoubleHashing.h&quot;
 #include &quot;Container.h&quot;

 #ifndef ETYPE
 #define ETYPE int
 #endif

 const char helpstr[] = 
   &quot;new ............................... create new Container\n&quot;
   &quot;delete ............................ delete Container\n&quot;
   &quot;add &lt;key&gt; [...] ................... add &lt;key&gt;(s) with Container::add( int )\n&quot;
   &quot;remove &lt;key&gt; [...] ................ remove &lt;key&gt;(s) with Container::remove( int )\n&quot;
   &quot;member &lt;key&gt; ...................... call Container::member( &lt;key&gt; )\n&quot;
   &quot;size .............................. call Container::size()\n&quot;
   &quot;empty ............................. call Container::empty()\n&quot;
   &quot;min ............................... call Container::min()\n&quot;
   &quot;max ............................... call Container::max()\n&quot;
   &quot;print ............................. print container with operator&lt;&lt;()\n&quot;
   &quot;apply [asc|desc|dontcare [&lt;n&gt;&rsqb;&rsqb; ... traverse container with PrintN functor\n&quot;
   &quot;trace ............................. toggle tracing on/off\n&quot;
   &quot;fadd &lt;filename&gt; ................... add values read from file &lt;filename&gt;\n&quot;
   &quot;fremove &lt;filename&gt; ................ remove values read from file &lt;filename&gt;\n&quot;
   &quot;radd [&lt;n&gt; [&lt;seed&gt;&rsqb;&rsqb; ............... add &lt;n&gt; random values, optionally reset generator to &lt;seed&gt;\n&quot;
   &quot;rremove [&lt;n&gt; [&lt;seed&gt;&rsqb;&rsqb; ............ remove &lt;n&gt; random values, optionally reset generator to &lt;seed&gt;\n&quot;
   &quot;quit .............................. quit program\n\n&quot;
   &quot;arguments surrounded by [] are optional\n&quot;;

 template &lt;typename E&gt;
 class PrintN : public Functor&lt;E&gt; {
   std::ostream&amp; o;
   mutable int n;
 public:
   explicit PrintN( int n = 0, std::ostream&amp; o = std::cout ) : o( o ), n( n ) { }
   explicit PrintN( std::ostream&amp; o ) : o( o ), n( 0 ) { }
   bool operator()( const E&amp; e ) const {
     o &lt;&lt; e &lt;&lt; ' ';
     return n &lt;= 0 || --n;
   }
 };

 void setrandom( int seed ) { srand( seed ); }
 template &lt;typename E&gt; E nextrandom( ) { return E( rand( ) ); }

 // Template-Spezialisierungen fuer Klasse std::string

 template &lt;&gt; inline double doubleValue( const std::string&amp; e ) { double rc = 0.; for (size_t i = e.length(); i--; ) rc /= 256., rc += e[i]; return rc; }
 template &lt;&gt; inline unsigned long hashValue( const std::string&amp; e ) { unsigned long rc = 0; for (size_t i = 0; i &lt; e.length(); ++i) rc = rc * 13 + e[i]; return rc; }
 template &lt;&gt; inline unsigned long ordinalValue( const std::string&amp; ) { return 0; }
 template &lt;&gt; std::string nextrandom( ) {
   const char* start = helpstr + rand() % sizeof helpstr;
   while (!isalpha( *start )) if (*start) ++start; else start = helpstr;
   const char* end = start + 1;
   while (isalpha( *end )) ++end;
   return std::string( start, end - start );
 }

 // Klasse Person mit allen für die Verwendung als Container-Elementdatentyp noetigen Methoden und Funktionen

 class Person {
   std::string vorname;
   std::string nachname;
 public:
   Person() { }
   Person( std::string vorname, std::string nachname ) : vorname( vorname ), nachname( nachname ) { }
   bool operator==( const Person&amp; p ) const { return vorname == p.vorname &amp;&amp; nachname == p.nachname; }
   bool operator&gt;( const Person&amp; p ) const { return nachname &gt; p.nachname || (nachname == p.nachname &amp;&amp; vorname &gt; p.vorname); }

   std::ostream&amp; print( std::ostream&amp; o ) const { return o &lt;&lt; '[' &lt;&lt; nachname &lt;&lt; &quot;, &quot; &lt;&lt; vorname &lt;&lt; ']'; }
   std::istream&amp; read( std::istream&amp; i ) { return i &gt;&gt; vorname &gt;&gt; nachname; }
   friend double doubleValue&lt;Person&gt;( const Person&amp; e );
   friend unsigned long hashValue&lt;Person&gt;( const Person&amp; e );
   friend unsigned long ordinalValue&lt;Person&gt;( const Person&amp; e );
 };

 inline std::ostream&amp; operator&lt;&lt;( std::ostream&amp; o, const Person&amp; p ) { return p.print( o ); }
 inline std::istream&amp; operator&gt;&gt;( std::istream&amp; i, Person&amp; p ) { return p.read( i ); }

 // Template-Spezialisierungen fuer Klasse Person

 template &lt;&gt; inline double doubleValue( const Person&amp; e ) { return doubleValue( e.nachname ); }
 template &lt;&gt; inline unsigned long hashValue( const Person&amp; e ) { return hashValue( e.nachname ); }
 template &lt;&gt; inline unsigned long ordinalValue( const Person&amp; ) { return 0; }
 template &lt;&gt; Person nextrandom( ) { 
   return Person( nextrandom&lt;std::string&gt;(), nextrandom&lt;std::string&gt;() );
 }

 bool match( const std::string&amp; s, const char * c ) {
   return c &amp;&amp; s.length() &lt;= std::strlen( c ) &amp;&amp; s.compare( 0, s.length(), c, s.length() ) == 0;
 }

 int main() {

   Container&lt;ETYPE&gt;* c = 0;
   bool traceIt = false;
   std::cout.setf( std::ios_base::boolalpha );

   while (true) {
     if (traceIt) {
       if (c) {
         std::cout &lt;&lt; std::endl &lt;&lt; &quot;container: &quot; &lt;&lt; *c;
       } else {
         std::cout &lt;&lt; std::endl &lt;&lt; &quot;no container&quot;;
       }
     }
     std::cout &lt;&lt; std::endl &lt;&lt; &quot;&gt; &quot;;

     std::string cmdline;
     if (!std::getline( std::cin, cmdline )) break;

     std::istringstream cmdstream( cmdline );
     std::string cmd;

     cmdstream &gt;&gt; cmd;

     try {
       if (cmd.length() == 0) {
       } else if (match( cmd, &quot;quit&quot; )) {
         break;
       } else if (match( cmd, &quot;new&quot; )) {
         if (c) {
           std::cerr &lt;&lt; &quot;container exists, 'delete' it first&quot;;
         } else {
           std::string typ;
           cmdstream &gt;&gt; typ;
           if (match( typ, &quot;ContDynArray&quot; ))
             c = new DoubleHashing&lt;ETYPE&gt;;
           else
             std::cout &lt;&lt; &quot;unknown container type &quot; &lt;&lt; typ;
         }
       } else if (match( cmd, &quot;help&quot; ) || cmd == &quot;?&quot;) {
         std::cout &lt;&lt; helpstr;
       } else if (match( cmd, &quot;trace&quot; )) {
         std::cout &lt;&lt; &quot;trace &quot; &lt;&lt; ((traceIt = !traceIt) ? &quot;on&quot; : &quot;off&quot;);
       } else if (!c) {
         std::cout &lt;&lt; &quot;no container (use 'new')&quot;;
       } else {
         ETYPE key;
         if (match( cmd, &quot;delete&quot; )) {
           delete c;
           c = 0;
         } else if (match( cmd, &quot;add&quot; )) {
           while (cmdstream &gt;&gt; key) { c-&gt;add( key ); }
         } else if (match( cmd, &quot;remove&quot; )) {
           while (cmdstream &gt;&gt; key) { c-&gt;remove( key ); }
         } else if (match( cmd, &quot;member&quot; )) {
           cmdstream &gt;&gt; key;
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;member( key );
         } else if (match( cmd, &quot;size&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;size( );
         } else if (match( cmd, &quot;empty&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;empty( );
         } else if (match( cmd, &quot;min&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;min( );
         } else if (match( cmd, &quot;max&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;max( );
         } else if (match( cmd, &quot;print&quot; )) {
           std::cout &lt;&lt; *c;
         } else if (match( cmd, &quot;apply&quot; )) {
           int n = 0;
           std::string order = &quot;dontcare&quot;;
           cmdstream &gt;&gt; order &gt;&gt; n;
           size_t rc = c-&gt;apply( PrintN&lt;ETYPE&gt;( n ), match( order, &quot;ascending&quot; ) ? ascending : match( order, &quot;descending&quot; ) ? descending : dontcare );
           std::cout &lt;&lt; &quot;\nreturns &quot; &lt;&lt; rc;
         } else if (match( cmd, &quot;fadd&quot; )) {
           std::string filename;
           cmdstream &gt;&gt; filename;
           std::ifstream keystream( filename.c_str() );
           while (keystream &gt;&gt; key) { c-&gt;add( key ); }
         } else if (match( cmd, &quot;fremove&quot; )) {
           std::string filename;
           cmdstream &gt;&gt; filename;
           std::ifstream keystream( filename.c_str() );
           while (keystream &gt;&gt; key) { c-&gt;remove( key ); }
         } else if (match( cmd, &quot;radd&quot; )) {
           int seed = -1, count = 1;
           cmdstream &gt;&gt; count &gt;&gt; seed;
           if (seed != -1) setrandom( seed );
           while (count-- &gt; 0) c-&gt;add( nextrandom&lt;ETYPE&gt;() );
         } else if (match( cmd, &quot;rremove&quot; )) {
           int seed = -1, count = 1;
           cmdstream &gt;&gt; count &gt;&gt; seed;
           if (seed != -1) setrandom( seed );
           while (count-- &gt; 0) c-&gt;remove( nextrandom&lt;ETYPE&gt;() );
         } else {
           std::cout &lt;&lt; cmd &lt;&lt; &quot;? try 'help'&quot;;
         }
       }
     } catch (Container&lt;ETYPE&gt;::Exception&amp; e) {
       std::cout &lt;&lt; &quot;Container::Exception &quot; &lt;&lt; e.what();
     } catch (std::exception&amp; e) {
       std::cout &lt;&lt; &quot;Exception &quot; &lt;&lt; e.what();
     } catch (...) {
       std::cout &lt;&lt; &quot;OOPS!&quot;;
     }
   }
   return 0;
 }
</code></pre>
<p>Container-Header:</p>
<pre><code class="language-cpp">[code]
#ifndef CONTAINER_H
 #define CONTAINER_H

 // Container.h
 // 
 // UE Algorithmen und Datenstrukturen - SS 2012 Universitaet Wien
 // Container - Projekt
 // http://www.pri.univie.ac.at/courses/ADS/ss12/

 #include &lt;iostream&gt;
 #include &lt;string&gt;
 #include &quot;DoubleHashing.h&quot;

 enum Order { dontcare, ascending, descending };
 template &lt;typename E&gt; class Functor;

 template &lt;typename E&gt;
 class Container {
   Container&lt;E&gt;&amp; operator=( const Container&lt;E&gt;&amp; );
   Container&lt;E&gt;( const Container&lt;E&gt;&amp; );
 public:
   class Exception;

   Container&lt;E&gt;( ) { }
   virtual ~Container&lt;E&gt;( ) { }

   virtual void add( const E&amp; e ) { add( &amp;e, 1 ); }
   virtual void add( const E e[], size_t s ) = 0;

   virtual void remove( const E&amp; e ) { remove( &amp;e, 1 ); }
   virtual void remove( const E e[], size_t s ) = 0;

   virtual bool member( const E&amp; e ) const = 0;
   virtual size_t size( ) const = 0;

   //nicht implementiert
   virtual bool empty( ) const { return false; } //nicht implementiert

   //nicht implementiert
   virtual size_t apply( const Functor&lt;E&gt;&amp; f, Order order = dontcare ) const { return 0; }

   virtual E min( ) const = 0;
   virtual E max( ) const = 0;

   virtual std::ostream&amp; print( std::ostream&amp; o ) const = 0;
 };

 template &lt;typename E&gt;
 inline std::ostream&amp; operator&lt;&lt;( std::ostream&amp; o, const Container&lt;E&gt;&amp; c ) { return c.print( o ); }

 template &lt;typename E&gt;
 class Container&lt;E&gt;::Exception : public std::exception {
   std::string msg;
 public:
   explicit Exception( const std::string&amp; msg ) throw() : msg( msg ) {}
   virtual ~Exception() throw() {}
   virtual const char * what() const throw() { return msg.c_str(); }
 };

 template &lt;typename E&gt;
 class Functor {
 public:
   virtual bool operator( )( const E&amp; e ) const = 0;
   virtual ~Functor( ) {}
 };

 template &lt;typename E&gt; inline unsigned long hashValue( const E&amp; e ) { return (unsigned long) e * 47114711; }
 template &lt;typename E&gt; inline double doubleValue( const E&amp; e ) { return double( e ); }
 template &lt;typename E&gt; inline unsigned long ordinalValue( const E&amp; e ) { return (unsigned long) e; }

 #endif //CONTAINER_H
</code></pre>
<p>[/code]</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/304294/c-doublehashing</link><generator>RSS for Node</generator><lastBuildDate>Sun, 09 Aug 2026 20:56:29 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/304294.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 02 Jun 2012 20:52:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to C++ DoubleHashing on Sat, 02 Jun 2012 20:52:30 GMT]]></title><description><![CDATA[<p>Hallo liebe Leute,</p>
<p>das ist mein erster Eintrag in diesem Forum, also habt ein bisschen Nachsicht mit mir falls etwas nicht funktionieren sollte. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /></p>
<p>Ich programmiere gerade eine Hashtabelle mit Double Hashing mein Problem ist allerdings es klappt irgendwie nicht so wie ich möchte.</p>
<p>1. Das erste Problem liegt in der Exception Defintion der min- &amp; max-Methode<br />
und zwar bekomme ich hier diese Fehlermeldung:<br />
DoubleHashing.h: In member function ‘E DoubleHashing&lt;E&gt;::min() const [with E = TestKey]’:<br />
testcfull.C:1206: instantiated from here<br />
DoubleHashing.h:124: error: no type named ‘Exception’ in ‘class Container&lt;TestKey&gt;’</p>
<p>Dies kann aber meiner Meinung nach nicht sein, weil die Exception-Zeile:</p>
<pre><code>[cpp]throw typename Container&lt;E&gt;::Exception(&quot;DoubleHashing&lt;E&gt;::min(): container empty&quot;);
</code></pre>
<p>[/cpp]</p>
<p>eigentlich in Ordnung sein sollte.</p>
<p>2. Mein zweites Problem findet sich in add:<br />
Hier wird einfach niemals die erste Hashfunktion aufgerufen, sondern immer auf das Linear Probing zurück gegriffen.</p>
<p>3. Ich hoffe meine Frage wirkt nicht zu blöd, aber muss ich in der remove-Methode ebenfalls die Hashfunktionen durchlaufen oder kann ich einfach jeden Wert durchgehen?? Da bin ich mir wirklich nicht sicher.</p>
<p>4. In der apply Methode, also bei ascending und descending wird anscheinend auf einen unerwünschten Speicher im Hauptspeicher zugegriffen.</p>
<p>Kann mir jemand weiterhelfen, bzw. einen Tipp für zumindest eine der Problematiken geben?</p>
<p>PS: DoubleHashing.h habe ich selbst erstellt; Container.h wurde mir vorgegeben und wird nicht verändert, bzw. simpelest.cpp ist das zugehörige, ebenfalls vorgegebene Testprogramm.</p>
<p>Meine erstellte Klasse:</p>
<pre><code>[cpp]
#ifndef DOUBLEHASHING_H
#define DOUBLEHASHING_H

#include &lt;iostream&gt;
#include &quot;Container.h&quot;

template &lt;typename E&gt;
class DoubleHashing : public Container&lt;E&gt; {

  class HashElements {
  public:
    unsigned int key;
    E element;
    int status;

    /*Konstruktor*/
    HashElements() : element() {
      key = 0;
      status = 0;
    }

    /*Destruktor*/
    ~HashElements() {/*delete [] element;*/}

    /*Hilfsfunktion fuer add*/
    void fill(const E a, unsigned int schluessel) {
      element = a;
      key = schluessel;
      status = 1;
    }

  };

  HashElements *value;
  size_t maxV; //maximal moegliche Eintraege
  size_t entries;//tatsaechliche Eintragsanzahl

  public:

    //TO DO: PROBLEMBESCHREIBUNG SIEHE METHODE
    using Container&lt;E&gt;::add; //add-Methode
    virtual void add (const E*e, size_t s);
    //void add_single (const E&amp; e);
    void selectionSort(E* newHash, size_t traversePosition) const;
    virtual size_t apply (const Functor&lt;E&gt;&amp;, Order=dontcare) const;

    //implemented
    virtual ~DoubleHashing&lt;E&gt;(); //Destruktor
    virtual std::ostream&amp; print(std::ostream&amp; o) const; //print
    virtual bool member (const E&amp; e) const; //member-Methode
    using Container &lt;E&gt;::remove;
    virtual void remove(const E[], size_t);
    virtual E min() const;
    virtual E max() const;
     //void expand();
    //void swap(E&amp; object1, E&amp; object2) const;
    virtual size_t size() const {
      //liefert tatsaechliche Eintragszahl des Hashing-Verfahrens zurueck
      return entries;
    }

    virtual bool empty() const {
      if(entries!=0) {
        return false;
      }

      else {
        return true;
      }  
    }

    DoubleHashing&lt;E&gt;() {
      entries = 0;
      maxV = 7;
      value = new HashElements[7];
  }
};

  bool isprim(int number) {
    int temp = 2;
    for(; temp&lt;number; ++temp) {
      if(number%temp == 0) {
        return false;
      }
    }

    return true;
  }

  int prim(int number) {
    int next = number+1;
    int last = number*2;
    while(next &lt; last) {
        if(isprim(next) == true) {
          return next;
        }

        else {
          last++;
        }

        next++;
    } 
  }

      //Methode liefert kleinsten Wert des Hashing-Verfahrens zurueck
  template &lt;typename E&gt;
  E DoubleHashing&lt;E&gt;::min() const {
    E minimum;  
    if(entries!=0) {
        minimum = value[0].element;
        for(size_t i=0; i&lt;maxV; i++) {
          if(minimum &gt; value[i].element &amp;&amp; value[i].status==1) {
            minimum = value[i].element;
          }
        }

        return minimum;
      }

      else {
        throw typename Container&lt;E&gt;::Exception(&quot;DoubleHashing&lt;E&gt;::min(): container empty&quot;);
      }
    } 

    //Methode liefert groessten Wert des Hashing-Verfahrens zurueck
    template &lt;typename E&gt;
    E DoubleHashing&lt;E&gt;::max() const {
      E maximum;
      if(entries==0) {
        throw Container&lt;E&gt;::Exception(&quot;DoubleHashing&lt;E&gt;::max(): container empty&quot;);
      }
      else {
        maximum = value[0].element;
        for(size_t i=0; i&lt;maxV; i++) {
          if(value[i].element &gt; maximum &amp;&amp; value[i].status==1) {
            maximum = value[i].element;
          }
        }

        return maximum;
      }
    }

  template&lt;typename E&gt;
  DoubleHashing&lt;E&gt;::~DoubleHashing() {
    delete[]value;
  }

  //Problem: rehashing nach Vergroesserung
  //Problem_2: es werden nicht alle Werte hinzugefuegt
  template&lt;typename E&gt;
  void DoubleHashing&lt;E&gt;::add(const E e[], size_t len) {
    size_t newMax=maxV;
    size_t tempMax;
    unsigned int temp =0;
    HashElements *neu;

    if((entries+len) &gt; ((newMax) * 0.7)) {
      HashElements *expand;
      do {
        newMax = prim(newMax);
      } while(newMax &lt; ((entries+len)*10));

      expand = new HashElements[newMax];

      for(size_t i=0; i&lt;maxV; ++i) {
          if(value[i].status==1) {
              temp = value[i].key % newMax;
              if(expand[temp].status==0) {
                expand[temp].fill(value[i].element, value[i].key);  
              }

              else {
                tempMax = newMax;
                for(size_t k=(temp+1); k&lt;tempMax; ++k) {
                  if(expand[k].status == 0) {
                    expand[k].fill(value[i].element, value[i].key);
                    k=k+newMax;
                  }

                  if(k==newMax-1) {
                    k=0;
                    tempMax = temp;
                  }
                }
              }
            }

        }

      delete[] value;
      value = expand;
      maxV = newMax;
      }

      for(size_t j=0; j&lt;len; ++j) {
        if(!member(e[j])) {
          temp = hashValue(e[j]) % maxV;
          neu = &amp;value[temp];
          if(neu-&gt;status==0) {
            value[temp].fill(e[j],hashValue(e[j]));
            entries++;
          }

          else {
            for(size_t i=temp%maxV; i&lt;maxV; ++i) {
              neu = &amp;value[i];
              if(neu-&gt;status==0) {
                value[i].fill(e[j],hashValue(e[j]));
                i=i+maxV;
                entries++;
              }
            }
          }
        }
      }
    }

  template&lt;typename E&gt;
  bool DoubleHashing&lt;E&gt;::member(const E&amp; e) const {
    unsigned int pos = hashValue(e) % maxV;
    unsigned int temp = maxV;
    for(unsigned int j=pos; j&lt;temp; ++j) {
		if(value[j].status == 1) {
			if(value[j].element==e) {
				return true;
			}

			if(j==maxV-1) {
				temp = pos;
				j = 0;
			}
		}
    }
    return false;
  }

  template &lt;typename E&gt;
  std::ostream&amp; DoubleHashing&lt;E&gt;::print(std::ostream&amp; o) const {
    HashElements *eintrag;
    o&lt;&lt; &quot;[values= &quot;;
    for (size_t i=0; i&lt;maxV; ++i) {
      eintrag = &amp;value[i];
      o &lt;&lt; ' ' &lt;&lt; eintrag-&gt;element;
      eintrag = 0;
    }
    o &lt;&lt;&quot; ] &quot;;

    return o;
  }

  template&lt;typename E&gt;
  void DoubleHashing&lt;E&gt;::remove(const E e[], size_t s) {
    for(size_t i=0; i&lt;s; i++) {
      for(size_t j=0; j&lt;maxV; j++) {
        if(value[j].element == e[i] &amp;&amp; value[j].status == 1) {
          value[j].status = 0;
          //value[j].element = 0;
          value[j].key = 0;
          --entries;
          break;
        }
      }
    }
  }

  template &lt;typename E&gt;
  size_t DoubleHashing&lt;E&gt;::apply(const Functor &lt;E&gt;&amp; f, Order order) const {
    if(size()&gt;0) {
      //selectionSort array
      E*newHash = new E[entries];
      size_t traversePosition = 0;
      size_t rc = 0;

      for(size_t i=0; i&lt;maxV; i++) {
        //if(value[i].element&gt;0) {
            newHash[traversePosition] = value[i].element;
            traversePosition++;
        //}
      }

      //ToDO: Fehler beim Sortieren  
      if(order==ascending) {
        selectionSort(newHash, traversePosition);
        for(size_t i=0; i&lt;traversePosition; i++) {
          rc++;
          if(!f(newHash[i])) break;
        }
      }

      /*Problem: letzter Wert des Arrays wird nicht ausgegeben */
      if(order==descending) {
        selectionSort(newHash,traversePosition);
        //wenn i&gt;=0 -&gt; dann Zugriff auf nicht zugelassenen Hauptspeicher
        //wenn i&gt;0 -&gt; letzer Wert des Arrays wird nicht ausgegeben
        for(size_t i=traversePosition-1; i&gt;0; i--) {
          rc++;
          if(!f(newHash[i])) break;
        }

      }

      if(order==dontcare) {
        for(size_t i=0; i&lt;traversePosition; i++) {
          rc++;
          if(!f(newHash[i])) break;
        }
      }

      delete [] newHash;
      return rc;
    }
    return 0;
  }

  template &lt;typename E&gt;
  void DoubleHashing&lt;E&gt;::selectionSort(E* newHash, size_t traversePosition) const {
    //E minimum;
    size_t i, j, minIndex; 
    E temp;

    for(i=0; i&lt;traversePosition-1; i++) {
      minIndex = i;
      for(j=i+1; j&lt;traversePosition; j++) {
        if(newHash[minIndex] &gt; newHash[j]) {
          minIndex = j;
        }
      }

      if(minIndex != i) {
        temp = newHash[i];
        newHash[i] = newHash[minIndex];
        newHash[minIndex] = temp;
      }
    }

   /* for(i=0; i&lt;traversePosition-1; i++) {
      elementOne = i;
      minimum = newHash[i];

      for(j=i+1; j&lt;traversePosition; j++) {
        if(minimum &gt; newHash[j]) {
          elementTwo = j;
        }
      }
      swap(newHash[elementOne],newHash[elementTwo]);

    }
    */
  }

#endif
[/cpp]
</code></pre>
<p>Testprogramm:</p>
<pre><code class="language-cpp">// simpletest.C
 // 
 // UE Algorithmen und Datenstrukturen - SS 2012 Universitaet Wien
 // Container - Projekt
 // http://www.pri.univie.ac.at/courses/ADS/ss12/
 //Beim Kompilieren kann mittels Option -DETYPE=&lt;typ&gt; der Elementdatentyp des 
 //Containers festgelegt werden, also zB -DETYPE=Person (Defaulttyp ist int). 
 // Simples Testprogramm zur Ueberpruefung der Container-Funktionalitaet
 // Die Zeichenfolge Hashing ist in der ganzen Datei durch den Klassennamen 
 // der Datenstruktur zu ersetzen.
 // 
 // Der Elementdatentyp kann mit Compileroption -DETYPE=&lt;typ&gt; festgelegt werden,
 // also zb -DETYPE=std::string

 #include &lt;iostream&gt;
 #include &lt;sstream&gt;
 #include &lt;fstream&gt;
 #include &lt;string&gt;
 #include &lt;cstring&gt;
 #include &lt;cstdlib&gt;
 #include &lt;cctype&gt;
 #include &quot;DoubleHashing.h&quot;
 #include &quot;Container.h&quot;

 #ifndef ETYPE
 #define ETYPE int
 #endif

 const char helpstr[] = 
   &quot;new ............................... create new Container\n&quot;
   &quot;delete ............................ delete Container\n&quot;
   &quot;add &lt;key&gt; [...] ................... add &lt;key&gt;(s) with Container::add( int )\n&quot;
   &quot;remove &lt;key&gt; [...] ................ remove &lt;key&gt;(s) with Container::remove( int )\n&quot;
   &quot;member &lt;key&gt; ...................... call Container::member( &lt;key&gt; )\n&quot;
   &quot;size .............................. call Container::size()\n&quot;
   &quot;empty ............................. call Container::empty()\n&quot;
   &quot;min ............................... call Container::min()\n&quot;
   &quot;max ............................... call Container::max()\n&quot;
   &quot;print ............................. print container with operator&lt;&lt;()\n&quot;
   &quot;apply [asc|desc|dontcare [&lt;n&gt;&rsqb;&rsqb; ... traverse container with PrintN functor\n&quot;
   &quot;trace ............................. toggle tracing on/off\n&quot;
   &quot;fadd &lt;filename&gt; ................... add values read from file &lt;filename&gt;\n&quot;
   &quot;fremove &lt;filename&gt; ................ remove values read from file &lt;filename&gt;\n&quot;
   &quot;radd [&lt;n&gt; [&lt;seed&gt;&rsqb;&rsqb; ............... add &lt;n&gt; random values, optionally reset generator to &lt;seed&gt;\n&quot;
   &quot;rremove [&lt;n&gt; [&lt;seed&gt;&rsqb;&rsqb; ............ remove &lt;n&gt; random values, optionally reset generator to &lt;seed&gt;\n&quot;
   &quot;quit .............................. quit program\n\n&quot;
   &quot;arguments surrounded by [] are optional\n&quot;;

 template &lt;typename E&gt;
 class PrintN : public Functor&lt;E&gt; {
   std::ostream&amp; o;
   mutable int n;
 public:
   explicit PrintN( int n = 0, std::ostream&amp; o = std::cout ) : o( o ), n( n ) { }
   explicit PrintN( std::ostream&amp; o ) : o( o ), n( 0 ) { }
   bool operator()( const E&amp; e ) const {
     o &lt;&lt; e &lt;&lt; ' ';
     return n &lt;= 0 || --n;
   }
 };

 void setrandom( int seed ) { srand( seed ); }
 template &lt;typename E&gt; E nextrandom( ) { return E( rand( ) ); }

 // Template-Spezialisierungen fuer Klasse std::string

 template &lt;&gt; inline double doubleValue( const std::string&amp; e ) { double rc = 0.; for (size_t i = e.length(); i--; ) rc /= 256., rc += e[i]; return rc; }
 template &lt;&gt; inline unsigned long hashValue( const std::string&amp; e ) { unsigned long rc = 0; for (size_t i = 0; i &lt; e.length(); ++i) rc = rc * 13 + e[i]; return rc; }
 template &lt;&gt; inline unsigned long ordinalValue( const std::string&amp; ) { return 0; }
 template &lt;&gt; std::string nextrandom( ) {
   const char* start = helpstr + rand() % sizeof helpstr;
   while (!isalpha( *start )) if (*start) ++start; else start = helpstr;
   const char* end = start + 1;
   while (isalpha( *end )) ++end;
   return std::string( start, end - start );
 }

 // Klasse Person mit allen für die Verwendung als Container-Elementdatentyp noetigen Methoden und Funktionen

 class Person {
   std::string vorname;
   std::string nachname;
 public:
   Person() { }
   Person( std::string vorname, std::string nachname ) : vorname( vorname ), nachname( nachname ) { }
   bool operator==( const Person&amp; p ) const { return vorname == p.vorname &amp;&amp; nachname == p.nachname; }
   bool operator&gt;( const Person&amp; p ) const { return nachname &gt; p.nachname || (nachname == p.nachname &amp;&amp; vorname &gt; p.vorname); }

   std::ostream&amp; print( std::ostream&amp; o ) const { return o &lt;&lt; '[' &lt;&lt; nachname &lt;&lt; &quot;, &quot; &lt;&lt; vorname &lt;&lt; ']'; }
   std::istream&amp; read( std::istream&amp; i ) { return i &gt;&gt; vorname &gt;&gt; nachname; }
   friend double doubleValue&lt;Person&gt;( const Person&amp; e );
   friend unsigned long hashValue&lt;Person&gt;( const Person&amp; e );
   friend unsigned long ordinalValue&lt;Person&gt;( const Person&amp; e );
 };

 inline std::ostream&amp; operator&lt;&lt;( std::ostream&amp; o, const Person&amp; p ) { return p.print( o ); }
 inline std::istream&amp; operator&gt;&gt;( std::istream&amp; i, Person&amp; p ) { return p.read( i ); }

 // Template-Spezialisierungen fuer Klasse Person

 template &lt;&gt; inline double doubleValue( const Person&amp; e ) { return doubleValue( e.nachname ); }
 template &lt;&gt; inline unsigned long hashValue( const Person&amp; e ) { return hashValue( e.nachname ); }
 template &lt;&gt; inline unsigned long ordinalValue( const Person&amp; ) { return 0; }
 template &lt;&gt; Person nextrandom( ) { 
   return Person( nextrandom&lt;std::string&gt;(), nextrandom&lt;std::string&gt;() );
 }

 bool match( const std::string&amp; s, const char * c ) {
   return c &amp;&amp; s.length() &lt;= std::strlen( c ) &amp;&amp; s.compare( 0, s.length(), c, s.length() ) == 0;
 }

 int main() {

   Container&lt;ETYPE&gt;* c = 0;
   bool traceIt = false;
   std::cout.setf( std::ios_base::boolalpha );

   while (true) {
     if (traceIt) {
       if (c) {
         std::cout &lt;&lt; std::endl &lt;&lt; &quot;container: &quot; &lt;&lt; *c;
       } else {
         std::cout &lt;&lt; std::endl &lt;&lt; &quot;no container&quot;;
       }
     }
     std::cout &lt;&lt; std::endl &lt;&lt; &quot;&gt; &quot;;

     std::string cmdline;
     if (!std::getline( std::cin, cmdline )) break;

     std::istringstream cmdstream( cmdline );
     std::string cmd;

     cmdstream &gt;&gt; cmd;

     try {
       if (cmd.length() == 0) {
       } else if (match( cmd, &quot;quit&quot; )) {
         break;
       } else if (match( cmd, &quot;new&quot; )) {
         if (c) {
           std::cerr &lt;&lt; &quot;container exists, 'delete' it first&quot;;
         } else {
           std::string typ;
           cmdstream &gt;&gt; typ;
           if (match( typ, &quot;ContDynArray&quot; ))
             c = new DoubleHashing&lt;ETYPE&gt;;
           else
             std::cout &lt;&lt; &quot;unknown container type &quot; &lt;&lt; typ;
         }
       } else if (match( cmd, &quot;help&quot; ) || cmd == &quot;?&quot;) {
         std::cout &lt;&lt; helpstr;
       } else if (match( cmd, &quot;trace&quot; )) {
         std::cout &lt;&lt; &quot;trace &quot; &lt;&lt; ((traceIt = !traceIt) ? &quot;on&quot; : &quot;off&quot;);
       } else if (!c) {
         std::cout &lt;&lt; &quot;no container (use 'new')&quot;;
       } else {
         ETYPE key;
         if (match( cmd, &quot;delete&quot; )) {
           delete c;
           c = 0;
         } else if (match( cmd, &quot;add&quot; )) {
           while (cmdstream &gt;&gt; key) { c-&gt;add( key ); }
         } else if (match( cmd, &quot;remove&quot; )) {
           while (cmdstream &gt;&gt; key) { c-&gt;remove( key ); }
         } else if (match( cmd, &quot;member&quot; )) {
           cmdstream &gt;&gt; key;
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;member( key );
         } else if (match( cmd, &quot;size&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;size( );
         } else if (match( cmd, &quot;empty&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;empty( );
         } else if (match( cmd, &quot;min&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;min( );
         } else if (match( cmd, &quot;max&quot; )) {
           std::cout &lt;&lt; &quot;returns &quot; &lt;&lt; c-&gt;max( );
         } else if (match( cmd, &quot;print&quot; )) {
           std::cout &lt;&lt; *c;
         } else if (match( cmd, &quot;apply&quot; )) {
           int n = 0;
           std::string order = &quot;dontcare&quot;;
           cmdstream &gt;&gt; order &gt;&gt; n;
           size_t rc = c-&gt;apply( PrintN&lt;ETYPE&gt;( n ), match( order, &quot;ascending&quot; ) ? ascending : match( order, &quot;descending&quot; ) ? descending : dontcare );
           std::cout &lt;&lt; &quot;\nreturns &quot; &lt;&lt; rc;
         } else if (match( cmd, &quot;fadd&quot; )) {
           std::string filename;
           cmdstream &gt;&gt; filename;
           std::ifstream keystream( filename.c_str() );
           while (keystream &gt;&gt; key) { c-&gt;add( key ); }
         } else if (match( cmd, &quot;fremove&quot; )) {
           std::string filename;
           cmdstream &gt;&gt; filename;
           std::ifstream keystream( filename.c_str() );
           while (keystream &gt;&gt; key) { c-&gt;remove( key ); }
         } else if (match( cmd, &quot;radd&quot; )) {
           int seed = -1, count = 1;
           cmdstream &gt;&gt; count &gt;&gt; seed;
           if (seed != -1) setrandom( seed );
           while (count-- &gt; 0) c-&gt;add( nextrandom&lt;ETYPE&gt;() );
         } else if (match( cmd, &quot;rremove&quot; )) {
           int seed = -1, count = 1;
           cmdstream &gt;&gt; count &gt;&gt; seed;
           if (seed != -1) setrandom( seed );
           while (count-- &gt; 0) c-&gt;remove( nextrandom&lt;ETYPE&gt;() );
         } else {
           std::cout &lt;&lt; cmd &lt;&lt; &quot;? try 'help'&quot;;
         }
       }
     } catch (Container&lt;ETYPE&gt;::Exception&amp; e) {
       std::cout &lt;&lt; &quot;Container::Exception &quot; &lt;&lt; e.what();
     } catch (std::exception&amp; e) {
       std::cout &lt;&lt; &quot;Exception &quot; &lt;&lt; e.what();
     } catch (...) {
       std::cout &lt;&lt; &quot;OOPS!&quot;;
     }
   }
   return 0;
 }
</code></pre>
<p>Container-Header:</p>
<pre><code class="language-cpp">[code]
#ifndef CONTAINER_H
 #define CONTAINER_H

 // Container.h
 // 
 // UE Algorithmen und Datenstrukturen - SS 2012 Universitaet Wien
 // Container - Projekt
 // http://www.pri.univie.ac.at/courses/ADS/ss12/

 #include &lt;iostream&gt;
 #include &lt;string&gt;
 #include &quot;DoubleHashing.h&quot;

 enum Order { dontcare, ascending, descending };
 template &lt;typename E&gt; class Functor;

 template &lt;typename E&gt;
 class Container {
   Container&lt;E&gt;&amp; operator=( const Container&lt;E&gt;&amp; );
   Container&lt;E&gt;( const Container&lt;E&gt;&amp; );
 public:
   class Exception;

   Container&lt;E&gt;( ) { }
   virtual ~Container&lt;E&gt;( ) { }

   virtual void add( const E&amp; e ) { add( &amp;e, 1 ); }
   virtual void add( const E e[], size_t s ) = 0;

   virtual void remove( const E&amp; e ) { remove( &amp;e, 1 ); }
   virtual void remove( const E e[], size_t s ) = 0;

   virtual bool member( const E&amp; e ) const = 0;
   virtual size_t size( ) const = 0;

   //nicht implementiert
   virtual bool empty( ) const { return false; } //nicht implementiert

   //nicht implementiert
   virtual size_t apply( const Functor&lt;E&gt;&amp; f, Order order = dontcare ) const { return 0; }

   virtual E min( ) const = 0;
   virtual E max( ) const = 0;

   virtual std::ostream&amp; print( std::ostream&amp; o ) const = 0;
 };

 template &lt;typename E&gt;
 inline std::ostream&amp; operator&lt;&lt;( std::ostream&amp; o, const Container&lt;E&gt;&amp; c ) { return c.print( o ); }

 template &lt;typename E&gt;
 class Container&lt;E&gt;::Exception : public std::exception {
   std::string msg;
 public:
   explicit Exception( const std::string&amp; msg ) throw() : msg( msg ) {}
   virtual ~Exception() throw() {}
   virtual const char * what() const throw() { return msg.c_str(); }
 };

 template &lt;typename E&gt;
 class Functor {
 public:
   virtual bool operator( )( const E&amp; e ) const = 0;
   virtual ~Functor( ) {}
 };

 template &lt;typename E&gt; inline unsigned long hashValue( const E&amp; e ) { return (unsigned long) e * 47114711; }
 template &lt;typename E&gt; inline double doubleValue( const E&amp; e ) { return double( e ); }
 template &lt;typename E&gt; inline unsigned long ordinalValue( const E&amp; e ) { return (unsigned long) e; }

 #endif //CONTAINER_H
</code></pre>
<p>[/code]</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2218661</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2218661</guid><dc:creator><![CDATA[tinkabell]]></dc:creator><pubDate>Sat, 02 Jun 2012 20:52:30 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Sat, 02 Jun 2012 21:09:19 GMT]]></title><description><![CDATA[<p>Du erschlägst uns mit diesem code</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2218669</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2218669</guid><dc:creator><![CDATA[sdfghjkkj]]></dc:creator><pubDate>Sat, 02 Jun 2012 21:09:19 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Sat, 02 Jun 2012 21:16:53 GMT]]></title><description><![CDATA[<p>Den Code kenn ich doch! Wurde pepschi rausgeworfen und nun musst du sein Projekt übernehmen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2218674</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2218674</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sat, 02 Jun 2012 21:16:53 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Sun, 03 Jun 2012 12:56:33 GMT]]></title><description><![CDATA[<p>Es tut mir Leid, dass ich euch mit dem Code erschlage, allerdings war ich mir nicht sicher, ob ihr anhand einzelner Methoden den Aufbau versteht.</p>
<p>Als an min() und max() arbeite ich gerade Container und simpelest wurden verändert und das wusste ich leider bisher nicht, allerdings geht es hier &quot;nur&quot; um das Exception Handling, was ich mittlerweile auch erledigt habe.</p>
<p>Mein größtes und wichtigstes Problem liegt in der add-Methode. Kann mir jemand erklären, was ich falsch mache, bzw. warum er immer nur auf die zweite Hashfunktion zu greift?</p>
<p>Ich bin wirklich schon verzweifelt. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /><br />
Danke für eure Hilfe <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2218845</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2218845</guid><dc:creator><![CDATA[Double Hashing]]></dc:creator><pubDate>Sun, 03 Jun 2012 12:56:33 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Sun, 03 Jun 2012 16:01:56 GMT]]></title><description><![CDATA[<p>niemand hier wird sich 650 Zeilen code antun.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2218890</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2218890</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 03 Jun 2012 16:01:56 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Sun, 03 Jun 2012 16:28:05 GMT]]></title><description><![CDATA[<p>Ich hätte noch eine andere Frage und zwar habe ich die Klasse Exception in meinen Header eingebaut:</p>
<pre><code class="language-cpp">class Exception : public Container&lt;E&gt;::Exception {
  public:

    virtual const char* what() const throw() {
      return &quot;DoubleHashing: container empty&quot;;

    }
  };
</code></pre>
<p>Die Methoden min() und max() sollen darauf zugreifen, allerdings tun sie dass nicht, sondern werfen mir die Fehlermeldung, dass kein geeigneter Standardkonstruktur verfügbar ist. Wenn ich diesen in der Exception Klasse definiere funktioniert es auch nicht. Weiß jemand Rat?</p>
<pre><code class="language-cpp">template &lt;typename E&gt;
  E DoubleHashing&lt;E&gt;::max( ) const {
    if (this-&gt;empty()) throw Exception( );
    E rc = value[0].element;
    for (size_t i = 1; i &lt; maxV; ++i) {
      if (value[i].element &gt; rc) rc = value[i].element;
    }
  return rc;
}

  template &lt;typename E&gt;
  E DoubleHashing&lt;E&gt;::min( ) const {
   if (this-&gt;empty()) throw Exception( );
    E rc = value[0].element;
    for (size_t i = 1; i &lt; maxV; ++i) {
      if (rc &gt; value[i].element) rc = value[i].element;
    }
    return rc;
  }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2218903</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2218903</guid><dc:creator><![CDATA[tinkabell]]></dc:creator><pubDate>Sun, 03 Jun 2012 16:28:05 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Mon, 04 Jun 2012 06:37:38 GMT]]></title><description><![CDATA[<p>tinkabell schrieb:</p>
<blockquote>
<p>Weiß jemand Rat?</p>
</blockquote>
<p>Ja. Nicht alle Exception-Klassen einfach nur &quot;Exception&quot; nennen. Du sagst &quot;Exception&quot; und meinst die Klasse, die du beschrieben hast. Der Compiler denkt aber vermutlich an irgendeine andere Klasse, die &quot;Exception&quot; heißt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2219044</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2219044</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Mon, 04 Jun 2012 06:37:38 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Mon, 04 Jun 2012 10:11:21 GMT]]></title><description><![CDATA[<p>nein wurde ich nciht jedoch verzweifeln sehr sehr viele an diesem projekt! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>aber mit viel überlegen geht das schon!;)</p>
<p>SeppJ schrieb:</p>
<blockquote>
<p>Den Code kenn ich doch! Wurde pepschi rausgeworfen und nun musst du sein Projekt übernehmen?</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2219126</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2219126</guid><dc:creator><![CDATA[pepschi]]></dc:creator><pubDate>Mon, 04 Jun 2012 10:11:21 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Mon, 04 Jun 2012 17:07:38 GMT]]></title><description><![CDATA[<p>Gut, die Klasse für das Exception Handling und die beiden Methode habe ich verändert:</p>
<pre><code class="language-cpp">class CDAEmptyException : public ContainerException{
public:
  virtual const char * what() const throw () { return &quot;DoubleHashing: container empty&quot;; }
};

 template &lt;typename E&gt;
E DoubleHashing&lt;E&gt;::min( ) const {
  if (this-&gt;empty()) throw CDAEmptyException();
  else {
    E rc;
    for(size_t j=0; j &lt; maxV; ++j) {
      if(value[j].element &gt; -1) {
        rc = value[j].element;
        break;
      }
    }
    for (size_t i = 1; i &lt; maxV; ++i) {
      if (rc &gt; value[i].element &amp;&amp; value[i].element &gt; -1) rc = value[i].element;
    }
    return rc;
  }
}

template &lt;typename E&gt;
E DoubleHashing&lt;E&gt;::max( ) const {
  if (this-&gt;empty()) throw CDAEmptyException( );
  else {
    E rc;
    for(size_t j=0; j &lt; maxV; ++j) {
      if(value[j].element &gt; -1) {
        rc = value[j].element;
        break;
      }
    }
    for (size_t i = 1; i &lt; maxV; ++i) {
      if (value[i].element &gt; rc) rc = value[i].element;
    }
    return rc;
  }
}
</code></pre>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28208">@Pepschi</a> schrieb: aber mit viel überlegen geht das schon!;)</p>
<p>Sorry, aber der Ratschlag ist bei mir echt fehl am Platz. Glaub mir es gibt, wahrscheinlich keinem der mehr bei dieser Projektarbeit überlegt hat, als ich. Denn beim letzten Versuch hatte ich eine vollständige Implementierung für einen Heap mit Heapsort fertig und einen abschließenden Success. Ich war so dumm einen meiner Kolleginen meine fertige Arbeit vor dem Abgabegespräch zu geben und sie ist zwei Stunden vor mir zum Abgabegespräch gegangen. Sie hat mein File abgegeben und der Prof meinte dann zu mir man könne nicht beweisen, wer von wem plagiert hat, obwohl ich es definitiv beweisen hätte können. Sie wurde positiv benotet und mir wurde gerade noch kein Plagiat gegeben. Also sorry, dass mich der Spruch nicht gerade erfreut.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2219334</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2219334</guid><dc:creator><![CDATA[tinkabell]]></dc:creator><pubDate>Mon, 04 Jun 2012 17:07:38 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Mon, 04 Jun 2012 17:47:39 GMT]]></title><description><![CDATA[<p>@tinkabell<br />
Ich glaube nicht dass das unbedingt an dich gerichtet war, pepschi hat einfach SeppJ geantwortet.</p>
<p>Vonwegen Plagiat, also da hätte ich Stunk gemacht und &quot;verlangt&quot; dass die Kollegin zumindest auch ne 0 bekommt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2219349</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2219349</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 04 Jun 2012 17:47:39 GMT</pubDate></item><item><title><![CDATA[Reply to C++ DoubleHashing on Mon, 04 Jun 2012 19:10:57 GMT]]></title><description><![CDATA[<p>ja ok das versteh iche cht, das ist echt grausam! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":/"
      alt="😕"
    /></p>
<p>da können wanek und co schon sehr böse sein!</p>
<p>verstehe deinenärger aber mein comment war nicht an dich gerichtet!</p>
<p>wo liegt bei dir der fehler also in deinem programm?!</p>
<p>ich hänge gerade beim quicksort da ich gerade zu blöd bin mein array in den quicksort also in die funktion zukopieren und ein neues array zu erstellen! kannst du mir da vlt weiter helfen?! helfe auch dir gerne weiter!</p>
<p>lg</p>
<p>tinkabell schrieb:</p>
<blockquote>
<p>Gut, die Klasse für das Exception Handling und die beiden Methode habe ich verändert:</p>
<pre><code class="language-cpp">class CDAEmptyException : public ContainerException{
public:
  virtual const char * what() const throw () { return &quot;DoubleHashing: container empty&quot;; }
};

 template &lt;typename E&gt;
E DoubleHashing&lt;E&gt;::min( ) const {
  if (this-&gt;empty()) throw CDAEmptyException();
  else {
    E rc;
    for(size_t j=0; j &lt; maxV; ++j) {
      if(value[j].element &gt; -1) {
        rc = value[j].element;
        break;
      }
    }
    for (size_t i = 1; i &lt; maxV; ++i) {
      if (rc &gt; value[i].element &amp;&amp; value[i].element &gt; -1) rc = value[i].element;
    }
    return rc;
  }
}
 
template &lt;typename E&gt;
E DoubleHashing&lt;E&gt;::max( ) const {
  if (this-&gt;empty()) throw CDAEmptyException( );
  else {
    E rc;
    for(size_t j=0; j &lt; maxV; ++j) {
      if(value[j].element &gt; -1) {
        rc = value[j].element;
        break;
      }
    }
    for (size_t i = 1; i &lt; maxV; ++i) {
      if (value[i].element &gt; rc) rc = value[i].element;
    }
    return rc;
  }
}
</code></pre>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28208">@Pepschi</a> schrieb: aber mit viel überlegen geht das schon!;)</p>
<p>Sorry, aber der Ratschlag ist bei mir echt fehl am Platz. Glaub mir es gibt, wahrscheinlich keinem der mehr bei dieser Projektarbeit überlegt hat, als ich. Denn beim letzten Versuch hatte ich eine vollständige Implementierung für einen Heap mit Heapsort fertig und einen abschließenden Success. Ich war so dumm einen meiner Kolleginen meine fertige Arbeit vor dem Abgabegespräch zu geben und sie ist zwei Stunden vor mir zum Abgabegespräch gegangen. Sie hat mein File abgegeben und der Prof meinte dann zu mir man könne nicht beweisen, wer von wem plagiert hat, obwohl ich es definitiv beweisen hätte können. Sie wurde positiv benotet und mir wurde gerade noch kein Plagiat gegeben. Also sorry, dass mich der Spruch nicht gerade erfreut.</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2219389</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2219389</guid><dc:creator><![CDATA[pepschi]]></dc:creator><pubDate>Mon, 04 Jun 2012 19:10:57 GMT</pubDate></item></channel></rss>