2016-11-10 3 views
0

Ich versuche, ein Element aus einer Liste zu entfernen. Die Elemente sind Strukturen. Ich habe eine schwierige Zeit damit. Die Online-Beispiele sind nicht für Strukturelemente. Ich habe versucht, den Schlüssel/die Werte auf die Standardwerte zu setzen, aber sobald ich die Daten durchlaufen habe, druckt es einen Leerraum, was bedeutet, dass das Element immer noch da ist. Ich muss es komplett entfernen. Unten ist mein Code.Löschen eines Strukturelements in einer Liste

.H Datei

#include<list> 
#include<queue> 
using namespace std; 

template <typename K, typename V, int CAP> 
class HashTable { 
public: 
    HashTable(int(*)(const K&)); 
    bool HashTable<K, V, CAP>::containsKey(const K& key) const; 
    HashTable<K, V, CAP>& operator=(const HashTable<K, V, CAP>&); 
    V& operator[](const K&); // setter 
    V operator[](const K&) const; // getter 
    queue<K> keys() const; 
    int size() const {return siz;}; 
    void deleteKey(const K&); 

private: 
    int getIndex(const K& key) const; 
    struct Node{K key; V value;}; 
    int(*hashCode)(const K&); 
    list<Node> data[CAP]; 
    int cap; 
    int siz; 
}; 

Hier ist die Löschfunktion I umzusetzen versuchen.

template<typename K, typename V, int CAP> 
inline void HashTable<K, V, CAP>::deleteKey(const K & key) 
{ 
    typename list<Node>::iterator it; // getters need to use const_iterator 
    for (int i = 0; i < CAP; i++) 
    { 
    for (it = data[i].begin(); it != data[i].end(); it++) 
    { 
     if (it->key == key) 
     { 
     // these are a few things I tried, I know this is not right. 
     data[i].back().key = K(); 
     data[i].back().value = V(); 
     data[i].remove(key); // Error C2664 'void std::list<HashTable<std::string,int,100>::Node,std::allocator<_Ty>>::remove(const _Ty &)': 
           // cannot convert argument 1 from 'const std::string' to 'const HashTable<std::string,int,100>::Node &' 10HashTable 
     } 
    } 
    } 
} 

Antwort

2

key ist ein std::string, aber die Liste enthält Node s.
Auch data[i].back() ist das letzte Element der Liste und nicht *it.

Sie könnten erase verwenden, um das Element zu entfernen der Iterator entspricht:

template<typename K, typename V, int CAP> 
inline void HashTable<K, V, CAP>::deleteKey(const K & key) 
{ 
    for (int i = 0; i < CAP; i++) 
    { 
    typename list<Node>::iterator it = data[i].begin(); 
    while (it != data[i].end()) 
    { 
     if (it->key == key) 
     { 
     // Make 'it' a valid iterator to the next element 
     it = data[i].erase(it); 
     } 
     else 
     { 
     // Only increment if we didn't erase 
     it++; 
     } 
    } 
    } 
} 

In diesen Tagen, mit C++ 11, sollte die folgende sein genug:

template<typename K, typename V, int CAP> 
inline void HashTable<K, V, CAP>::deleteKey(const K & key) 
{ 
    for (auto& bucket: data) 
    { 
     bucket.remove_if([&] (auto& item) { return item->key == key; }); 
    } 
} 

Aber da dies eine Hashtabelle, vermutlich ist der Index in data der Hash von key, so dass Sie dies in einen Einzeiler verwandeln könnten:

template<typename K, typename V, int CAP> 
inline void HashTable<K, V, CAP>::deleteKey(const K & key) 
{ 
    data[hashCode(key)].remove_if([&] (auto& item) { return item->key == key; }); 
} 

oder, da Sie nur ein Element finden müssen (Ihre Schlüssel nur auf einen Wert Karte), können Sie etwas länger erhalten, aber effizienter:

template<typename K, typename V, int CAP> 
inline void HashTable<K, V, CAP>::deleteKey(const K & key) 
{ 
    auto& bucket = data[hashCode(key)]; 
    auto it = std::find_if(bucket.begin(), 
          bucket.end(), 
          [&] (auto& item) { return item->key == key; }); 
    if (it != bucket.end()) 
    { 
     bucket.erase(it); 
    } 
} 
+0

alle gaben mir Fehler. Der erste Code, den du geschrieben hast, gab mir die geringsten Fehler. es hieß "Fehler \t C2664 \t 'void std :: list :: Knoten, std :: allocator <_Ty>> :: entfernen (const _Ty &)': kann Argument 1 nicht konvertieren 'std :: _ List_iterator :: Knoten >>>' zu 'const HashTable :: Node & '\t 10HashTable " – asmcriminal

+0

@asmcriminal Sieht so aus, als ob Sie" Erase "falsch geschrieben haben. Möglicherweise müssen Sie auch den C++ 11-Modus in Ihrem Compiler für die anderen aktivieren. – molbdnilo

+0

danke das hat funktioniert. Ich dachte, ich kopiere und klebte es direkt. Ich denke nicht. – asmcriminal

0

Der letzte Versuch mit dem remove() ist fast die richtige Lösung. Sie müssen nur den Iterator für das Entfernen verwenden:

data[i].remove(it); 
    break; // found the element, iterator is invalid anyway: exit loop 

Dies wird vorausgesetzt, dass "Schlüssel" eindeutig ist.

+0

Vielen Dank, ich habe das gerade jetzt versucht. Ich habe immer noch einen Compilerfehler. Fehler \t C2664 \t 'void std :: list :: Knoten, std :: allocator <_Ty>> :: entfernen (const _Ty &)': kann nicht Argument 1 von 'Std konvertieren :: _ List_iterator :: Knoten >>> 'zu' const HashTable :: Knoten & '\t 10HashTable – asmcriminal

+0

Siehe Kommentare zum Eintrag von @ P.JBoy. – Rene

0

Rene wurde von Lösch denken, die einen Iterator braucht . list::remove Durchsucht die gesamte Liste nach dem angegebenen Wert und löscht alle Vorkommen. Also, versuchen Sie data[I].erase(it)

+0

danke, diese Art von gearbeitet. Es hat mir Debug Assertion fehlgeschlagen. "Ausdruck: Listeniterator nicht inkrementierbar." – asmcriminal

+0

a) Ja, richtig, hätte gelöscht werden müssen(). b) Dann haben Sie die break-Anweisung nicht kopiert. – Rene

Verwandte Themen