2016-11-10 82 views
0

我想要做的是从列表中删除一个元素。元素是结构。我对此感到困难。在线示例不适用于结构元素。我试图将键/值设置为默认值,但是一旦我遍历数据,它会打印出一个空格,表示元素仍然存在。我需要彻底删除它。以下是我的代码。清除列表中的结构元素

.H文件

#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; 
}; 

这里是删除功能我想实现。

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 
     } 
    } 
    } 
} 

回答

2

keystd::string,但该列表包含Node s。
另外,data[i].back()是列表的最后一个元素,而不是*it

你可以使用erase删除迭代器对应元素:

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++; 
     } 
    } 
    } 
} 

这些天来,与C++ 11,下面应该是足够了:

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; }); 
    } 
} 

但由于这是散列表,大概是data的索引是key的散列,所以你可以把它变成一行:

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; }); 
} 

,或者因为你只需要找到一个元素(你的钥匙只映射到一个值),可以稍长,但更有效的获得:

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

他们都给了我错误。你写的第一个代码给了我最少的错误。它说:“错误\t C2664 \t'void std :: list :: Node,std :: allocator <_Ty>> :: remove(const _Ty&)':不能将参数1从'std :: _ List_iterator ::节点>>>'to'const HashTable :: Node&'\t 10HashTable“ – asmcriminal

+0

@asmcriminal看起来像拼写错误的”擦除“。您可能还需要在其他编译器中为您的编译器启用C++ 11模式。 – molbdnilo

+0

谢谢你的工作。我以为我直接复制并粘贴它。我猜不会。 – asmcriminal

0

最后一次尝试remove()几乎是正确的解决方案。你只需要使用迭代器进行删除:

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

这是假设“密钥”是唯一的。

+0

谢谢,我刚才试过了。我仍然有一个编译器错误。错误\t C2664 \t'void std :: list :: Node,std :: allocator <_Ty>> :: remove(const _Ty&)':不能将参数1从'std :: _ List_iterator :: Node >>>'to const const HashTable '\t 10HashTable – asmcriminal

+0

查看@ P.JBoy的注解。 – Rene

0

刘若英在想擦除的,这确实需要一个迭代器。 list::remove通过整个列表执行搜索以匹配给定值并删除所有出现的事件。因此,试试data[I].erase(it)

+0

谢谢,那种工作。它给了我调试断言失败。 “表达式:列表迭代器不可增量。” – asmcriminal

+0

a)是的,对,应该已经擦除()。 b)然后你没有复制break语句。 – Rene